* r5900.igen (CVT.W.S): Always round towards zero.
[deliverable/binutils-gdb.git] / sim / common / sim-gx.c
CommitLineData
92fa4579
FCE
1/* GX target-independent functions for block translation.
2 Copyright (C) 1998 Cygnus Solutions. */
3
4
5#include "sim-main.h"
6#include "sim-assert.h"
7#include "sim-gx.h"
8
9#include "config.h"
ca0669a3 10/* #include "cconfig.h" */
92fa4579
FCE
11
12/* shared object functions */
13#ifdef HAVE_DLFCN_H
14#include <dlfcn.h>
15#else
16#error "need dlfcn.h"
17#endif
18
19#ifdef HAVE_ERRNO_H
20#include <errno.h>
21#else
22#error "need errno.h"
23#endif
24
25#include <stdlib.h>
26#include <string.h>
27#include <limits.h>
28#ifdef HAVE_TIME_H
29#include <time.h>
30#endif
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34#ifdef HAVE_FCNTL_H
35#include <fcntl.h>
36#endif
37#ifdef HAVE_SYS_STAT_H
38#include <sys/stat.h>
39#endif
40
41#include "bfd.h"
42
43
44
45
46/* Load the object file with given gx block. Return pointer to GX
47 function or NULL on failure. */
48
49sim_gx_function
50sim_gx_compiled_block_f(sim_gx_compiled_block* gx)
51{
52 sim_gx_function f = gx->function_dlhandle;
53 SIM_DESC sd = current_state;
54 int rc;
55
56 if(f == NULL)
57 {
58 /* compile object */
59 if(gx->object_name == NULL && gx->source_name != NULL)
60 {
61 char compile_command[2000];
62
63 gx->object_name = strdup(gx->source_name);
64 /* turn *.c into *.o */
65 gx->object_name[strlen(gx->object_name)]='o';
66
67 /* compute command string to compile object */
68 sprintf(compile_command,
69 "make -f %s OBJ=%s SRC=%s gx",
70#define GX_MAKEFILE "--no-makefile-yet--"
71 GX_MAKEFILE,
72 gx->object_name,
73 gx->source_name);
74
75 rc = system(compile_command);
76 if(rc != 0)
77 {
78 sim_io_error(sd, "Compile error rc %d for GX source %s: %s",
79 rc,
80 gx->source_name,
81 strerror(errno));
82 }
83 }
84
85 /* load object */
86 if(gx->object_dlhandle == NULL && gx->object_name != NULL)
87 {
88 gx->object_dlhandle = dlopen(gx->object_name, RTLD_NOW);
89 if(gx->object_dlhandle == NULL)
90 {
91 sim_io_error(sd, "Load error for GX object %s: %s",
92 gx->object_name,
93 dlerror());
94 }
95 }
96
97 /* locate function */
98 if(gx->function_dlhandle == NULL && gx->object_dlhandle != NULL && gx->symbol_name != NULL)
99 {
100 f = gx->function_dlhandle = dlsym(gx->object_dlhandle, gx->symbol_name);
101 if(f == NULL)
102 {
103 sim_io_error(sd, "Resolve error for GX object %s symbol %s: %s",
104 gx->object_name,
105 gx->symbol_name,
106 dlerror());
107 }
108 }
109 } /* f == NULL */
110
111 return f;
112}
113
114
115
116/* Forget about given GX block. Remove its source/object; unload it
117 from memory. */
118void
119sim_gx_compiled_block_dispose(sim_gx_compiled_block* gx)
120{
121 SIM_DESC sd = current_state;
122 int rc;
123
124 /* forget dl information */
125 gx->function_dlhandle = NULL;
126
127 /* unload shared library */
128 if(gx->object_dlhandle != NULL)
129 {
130 rc = dlclose(gx->object_dlhandle);
131 if(rc != 0)
132 {
133 sim_io_error(sd, "dlclose() error for GX object %s: %s",
134 gx->object_name,
135 dlerror());
136 }
137 gx->object_dlhandle = NULL;
138 }
139
140 /* final gasps */
141 zfree(gx->source_name);
142 zfree(gx->object_name);
143 zfree(gx->symbol_name);
144 zfree(gx);
145}
146
147
148
149/* Translate a piece of the code segment around given PC, in given mode. */
150sim_gx_block*
151sim_gx_block_create(sim_cia cia)
152{
153 sim_gx_block* block;
154
155 /* allocate emtpy block */
156 block = zalloc(sizeof(sim_gx_block));
157
158 /* initialize block bounds, callback struct etc. */
159 tgx_block_ctor(block, cia);
160
161 /* create learning mode translation */
162 sim_gx_block_translate(block, 0 /* learning mode */);
163
164 /* add block to block list */
165 sim_gx_block_add(block);
166
167 return block;
168}
169
170
171
172/* Write the current block list to the state file */
173void
174sim_gx_write_block_list()
175{
176 int i;
177 SIM_DESC sd = current_state;
178 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
179 FILE* f;
180 char state_file_name[PATH_MAX];
181 char *exec_name;
182
183 /* get base of executable name */
184 exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
185 if(strrchr(exec_name, '/') != NULL)
186 exec_name = strrchr(exec_name, '/') + 1;
187
188 /* generate base name */
189 sprintf(state_file_name, "%s/%s.gx",
190 GX_DIR,
191 exec_name);
192
193 f = fopen(state_file_name, "w");
194 if(f == NULL)
195 {
196 sim_io_error(sd, "Error: cannot write to state file %s, errno %d",
197 state_file_name, errno);
198 }
199
200 fprintf(f, "# This file was automatically generated. Do not edit.\n");
201
202 /* write block descriptors into state file */
203 for(i=0; i<blocks->gx_blocks_used; i++)
204 {
205 sim_gx_block* gx = blocks->gx_blocks[i];
206 sim_gx_compiled_block* block;
207 int j;
208 int age;
209
210 age = time(NULL) - gx->learn_last_change; /* store interval */
211 fprintf(f, "BLOCK 0x%lx 0x%lx %u %u\n", gx->origin, gx->length, gx->divisor, age);
212 fprintf(f, "FLAGS ");
213 for(j=0; j<GX_PC_FLAGS_INDEX(gx, gx->origin + gx->length); j++)
214 {
215 fprintf(f, "%2x ", gx->pc_flags[j]);
216 }
217 fprintf(f, "\n");
218
219 /* write learning mode names */
220 block = gx->learning_block;
221 fprintf(f, "LEARNING %s %s %s %lu %u\n",
222 block->source_name, block->object_name, block->symbol_name,
223 gx->compile_time, gx->opt_compile_count);
224
225 /* write optimized mode names */
226 block = gx->optimized_block;
227 if(block)
228 fprintf(f, "OPTIMIZED %s %s %s\n",
229 block->source_name, block->object_name, block->symbol_name);
230
231 /* NB: other fields will be filled in with freshly guessed values */
232 }
233
234 (void) fclose(f);
235}
236
237
238
239void
240print_gx_blocks(sim_gx_block_list* blocks, char* where)
241{
242 printf("print_gx_blocks: %s\n", where);
243
244 if(blocks == NULL)
245 printf("(null)\n");
246 else
247 {
248 int i;
249 printf("size: %d, used: %d\n",
250 blocks->gx_blocks_size, blocks->gx_blocks_used);
251
252 /* linear search */
253 for(i=0; i<blocks->gx_blocks_used; i++)
254 {
255 sim_gx_block* gx = blocks->gx_blocks[i];
256 printf("block %d: %p\n", i, (void*) gx);
257 if(gx == NULL)
258 printf("** NULL!\n");
259 else
260 printf(" begin 0x%08x length 0x%08x [opt %d%s]\n",
261 (unsigned)gx->origin, (unsigned)gx->length,
262 gx->opt_compile_count,
263 (gx->optimized_block ? " loaded" : " discarded"));
264 }
265
266 }
267}
268
269
270
271/* Read the current block list from the cache */
272void
273sim_gx_read_block_list()
274{
275 SIM_DESC sd = current_state;
276 FILE* f;
277 char state_file_name[PATH_MAX];
278 char *exec_name;
279
280 /* check for block */
281 if(STATE_PROG_BFD(sd) == NULL)
282 return;
283
284 /* get base of executable name */
285 exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
286 if(strrchr(exec_name, '/') != NULL)
287 exec_name = strrchr(exec_name, '/') + 1;
288
289 /* generate base name */
290 sprintf(state_file_name, "%s/%s.gx",
291 GX_DIR,
292 exec_name);
293
294 f = fopen(state_file_name, "r");
295 if(f == NULL)
296 {
297 /* XXX: print warning */
298 return;
299 }
300
301 fscanf(f, "#%*[^\n]\n"); /* swallow # comment line */
302
303 while(1)
304 {
305 unsigned_4 origin, length;
306 unsigned divisor;
307 sim_gx_block* gx;
308 int rc;
309 sim_gx_compiled_block* block;
310 unsigned age;
311 int j;
312
313 rc = fscanf(f, "BLOCK 0x%0lx 0x%lx %u %u\n", & origin, & length, & divisor, & age);
314 if(rc != 4) /* not all fields matched - assume EOF */
315 break;
316
317 gx = zalloc(sizeof(sim_gx_block));
318
319 /* initialize block bounds, callback struct etc. */
320 tgx_block_ctor2(gx, origin, length, divisor);
321
322 /* read flags */
323 fscanf(f, "FLAGS");
324 for(j=0; j<GX_PC_FLAGS_INDEX(gx, gx->origin + gx->length); j++)
325 {
326 unsigned value;
327 fscanf(f, "%2x ", & value);
328 gx->pc_flags[j] = (unsigned_1) value;
329 }
330 fscanf(f, "\n");
331
332 /* read learning mode info */
333 block = zalloc(sizeof(sim_gx_compiled_block));
334 gx->learning_block = block;
335 block->source_name = zalloc(PATH_MAX);
336 block->object_name = zalloc(PATH_MAX);
337 block->symbol_name = zalloc(PATH_MAX);
338 fscanf(f, "LEARNING %s %s %s %lu %u\n",
339 block->source_name, block->object_name, block->symbol_name,
340 & gx->compile_time, & gx->opt_compile_count);
341
342 /* read optimized mode info */
343 block = zalloc(sizeof(sim_gx_compiled_block));
344 gx->optimized_block = block;
345 block->source_name = zalloc(PATH_MAX);
346 block->object_name = zalloc(PATH_MAX);
347 block->symbol_name = zalloc(PATH_MAX);
348 rc = fscanf(f, "OPTIMIZED %s %s %s\n",
349 block->source_name, block->object_name, block->symbol_name);
350 if(rc != 3)
351 {
352 /* oops, not an optimized block */
353 zfree(block->source_name);
354 zfree(block->object_name);
355 zfree(block->symbol_name);
356 zfree(block);
357 gx->optimized_block = NULL;
358 }
359
360 /* fill in remaining fields */
361 gx->learn_last_change = time(NULL) - age; /* make absolute */
362
363 /* store it away */
364 sim_gx_block_add(gx);
365 }
366
367 print_gx_blocks(STATE_BLOCKS(sd), "after restoring state");
368}
369
370
371
372
373
374
375/* Add a gx block to list */
376void
377sim_gx_block_add(sim_gx_block* block)
378{
379 SIM_DESC sd = current_state;
380 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
381 int i;
382
383 /* print_gx_blocks(blocks, "pre add"); */
384
385 if(blocks == NULL)
386 blocks = STATE_BLOCKS(sd) = zalloc(sizeof(sim_gx_block_list));
387
388 /* need to enlarge block vector? */
389 if(blocks->gx_blocks_used == blocks->gx_blocks_size)
390 {
391 sim_gx_block** new_blocks;
392 int j;
393
394 blocks->gx_blocks_size += 20;
395 new_blocks = zalloc(blocks->gx_blocks_size * sizeof(sim_gx_block*));
396 for(j=0; j<blocks->gx_blocks_used; j++)
397 new_blocks[j] = blocks->gx_blocks[j];
398 if(blocks->gx_blocks) zfree(blocks->gx_blocks);
399 blocks->gx_blocks = new_blocks;
400 }
401
402 /* insert new block */
403 for(i=0; i<blocks->gx_blocks_used; i++)
404 {
405 ASSERT(blocks->gx_blocks[i] != NULL);
406
407 /* insertion point reached? */
408 if(blocks->gx_blocks[i]->origin > block->origin)
409 {
410 int j;
411 for(j=blocks->gx_blocks_used; j>=i; j--)
412 blocks->gx_blocks[j] = blocks->gx_blocks[j-1];
413 blocks->gx_blocks[i] = block;
414 blocks->gx_blocks_used ++;
415 break;
416 }
417 }
418
419 /* end of block vector */
420 if(i == blocks->gx_blocks_used)
421 {
422 blocks->gx_blocks[blocks->gx_blocks_used ++] = block;
423 }
424
425 /* print_gx_blocks(blocks, "post add"); */
426}
427
428
429
430/* Remove a gx block from list */
431void
432sim_gx_block_remove(sim_gx_block* block)
433{
434 SIM_DESC sd = current_state;
435 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
436 int i;
437
438 /* print_gx_blocks(blocks, "pre remove"); */
439
440 /* linear search */
441 for(i=0; i<blocks->gx_blocks_used; i++)
442 {
443 if(blocks->gx_blocks[i] == block)
444 {
445 /* found it */
446 while(i < blocks->gx_blocks_used - 1)
447 {
448 blocks->gx_blocks[i] = blocks->gx_blocks[i+1];
449 i++;
450 }
451 blocks->gx_blocks_used --;
452 break;
453 }
454 }
455
456 /* print_gx_blocks(blocks, "post remove"); */
457}
458
459
460/* Find a gx block from list */
461sim_gx_block*
462sim_gx_block_find(sim_cia cia)
463{
464 SIM_DESC sd = current_state;
465 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
466 int i;
467
468 if(blocks == NULL) return NULL;
469
470 /* print_gx_blocks(blocks, "pre find"); */
471
472 /* linear search */
473 for(i=0; i<blocks->gx_blocks_used; i++)
474 {
475 sim_gx_block* gx = blocks->gx_blocks[i];
476 ASSERT(gx != NULL);
477
478 if(GX_PC_INCLUDES(gx,cia))
479 {
480 return gx;
481 }
482 }
483
484 return NULL;
485}
486
487
488
489/* generate */
490void
491sim_gx_block_translate(sim_gx_block* gx, int optimized)
492{
493 char pwd_name[PATH_MAX];
494 char dir_name[PATH_MAX];
495 char base_name[PATH_MAX];
496 char compile_command[PATH_MAX*4];
497 char* exec_name;
498 SIM_DESC sd = current_state;
499 int rc;
500 sim_cia gx_cia;
501 sim_gx_compiled_block* block = zalloc(sizeof(sim_gx_compiled_block));
502 unsigned time_begin, time_end;
503
504 time_begin = time(NULL);
505
506 if(optimized) gx->optimized_block = block;
507 else gx->learning_block = block;
508
509 /* get base of executable name */
510 exec_name = bfd_get_filename(STATE_PROG_BFD(sd));
511 if(strrchr(exec_name, '/') != NULL)
512 exec_name = strrchr(exec_name, '/') + 1;
513
514 /* generate base name */
515 sprintf(dir_name, "%s/%s",
516 GX_DIR,
517 exec_name);
518
519 /* generate base name */
520 getcwd(pwd_name, sizeof(pwd_name));
521
522 /* create work directory */
523 rc = mkdir(GX_DIR, 0777);
524 if(rc != 0 &&
525 errno != EEXIST)
526 {
527 sim_io_error(sd, "Error: cannot create directory %s, errno %d",
528 GX_DIR, errno);
529 }
530
531 rc = mkdir(dir_name, 0777);
532 if(rc != 0 &&
533 errno != EEXIST)
534 {
535 sim_io_error(sd, "Error: cannot create directory %s, errno %d",
536 dir_name, errno);
537 }
538
539 /* compute base name */
540 if(optimized)
541 sprintf(base_name, "%08lx_opt%d", gx->origin, gx->opt_compile_count);
542 else
543 sprintf(base_name, "%08lx", gx->origin);
544
545 /* generate source/object file names */
546 block->source_name = zalloc(PATH_MAX);
547 block->object_name = zalloc(PATH_MAX);
548 sprintf(block->source_name, "%s/%s.c", dir_name, base_name);
549
550 /* generate symbol name for gx function */
551 block->symbol_name = zalloc(PATH_MAX);
552 sprintf(block->symbol_name, "gx_%s", base_name);
553
554 /* open source file */
555 block->source_file = fopen(block->source_name, "w");
556 if(block->source_file == NULL)
557 {
558 sim_io_error(sd, "Error: cannot open file %s, errno %d",
559 block->source_name, errno);
560 }
561
562 /* front matter */
563 fprintf(block->source_file, "/* sim-gx version %d */\n", GX_VERSION);
564 fprintf(block->source_file, "/* gx block date stamp %lu */\n\n", time(NULL));
565
566 /* emit head end of source */
567 tgx_emit_pre_function(gx, optimized);
568
569 /* emit function header */
570 fprintf(block->source_file, "\n\n");
571 fprintf(block->source_file, "extern int\n");
572 fprintf(block->source_file, "%s", block->symbol_name);
573 fprintf(block->source_file, "(struct tgx_cpu_regs* regs, char* pc_flags, struct tgx_callbacks* callbacks)\n");
574 fprintf(block->source_file, "{\n");
575 fprintf(block->source_file, " int rc = 0;\n");
576 if(! optimized)
577 fprintf(block->source_file, " unsigned int insn_count = 0;\n");
578
579 /* pre-block gunk: register load */
580 tgx_emit_load_block(gx, optimized);
581
582 /* emit intra-block jump label */
583 fprintf(block->source_file, "\n");
584 fprintf(block->source_file, "shortjump:\n");
585 fprintf(block->source_file, " pc = npc;\n");
586
587 /* translate jumptarget table */
588 if(! optimized)
589 {
590 fprintf(block->source_file, " pc_flags[(pc - 0x%08x) / %u] |= %d;\n",
591 (unsigned)gx->origin, gx->divisor, GX_PCF_JUMPTARGET);
592 }
593
594 /* enforce learning mode run limit */
595 if(! optimized)
596 {
597 fprintf(block->source_file, " insn_count++;\n");
598 fprintf(block->source_file, " if (insn_count > %d)\n", GX_LEARN_RUN_LIMIT);
599 fprintf(block->source_file, " {\n");
600 fprintf(block->source_file, " rc = %d;\n", GX_F_YIELD);
601 fprintf(block->source_file, " npc = pc;\n");
602 fprintf(block->source_file, " goto save;\n");
603 fprintf(block->source_file, " }\n");
604 }
605
606 /* emit PC switch, use compressed case numbers */
607 fprintf(block->source_file, "\n");
608 fprintf(block->source_file, " switch((pc - 0x%08x) / %u)\n",
609 (unsigned)gx->origin, gx->divisor);
610 fprintf(block->source_file, " {\n");
611
612 /* handle bad-PC event */
613 fprintf(block->source_file, " /* handle unknown jump target */\n");
614 fprintf(block->source_file, " default:\n");
615 fprintf(block->source_file, " rc = %d;\n", GX_F_NONPC);
616 fprintf(block->source_file, " npc = pc;\n");
617 fprintf(block->source_file, " goto save;\n");
618
619 /* start translating at the origin */
620 gx_cia = gx->origin;
621
622 /* translate instructions in block */
623 while(GX_PC_INCLUDES(gx,gx_cia))
624 {
625 sim_cia next_gx_cia;
626
627 /* translate PC case statement */
628 fprintf(block->source_file, "\n");
629 fprintf(block->source_file, " /* PC: 0x%08x, flags %02x */\n",
630 gx_cia, (int) GX_PC_FLAGS(gx, gx_cia));
631
632
633 /* skip over this instruction if it is not executed */
634 if(optimized && !(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_INSTRUCTION))
635 {
636 fprintf(block->source_file, " /* (not reached) */\n");
637
638 /* prevent fall-through from previous translated insn */
639 if(gx_cia > gx->origin &&
640 GX_PC_FLAGS(gx, (gx_cia - gx->divisor)) & GX_PCF_INSTRUCTION)
641 {
642 fprintf(block->source_file, " /* prevent fall-through */\n");
643 fprintf(block->source_file, " npc = 0x%08x;\n", gx_cia);
644 fprintf(block->source_file, " rc = %d;\n", GX_F_NONPC);
645 fprintf(block->source_file, " goto save;\n");
646 }
647
648 next_gx_cia = gx_cia + gx->divisor;
649 goto skip_instruction;
650 }
651
652 /* translate PC case statement */
653 if((! optimized) ||
654 (GX_PC_FLAGS(gx, gx_cia) & GX_PCF_JUMPTARGET))
655 {
656 fprintf(block->source_file, " case %ld:\n",
657 ((gx_cia - gx->origin) / gx->divisor));
658 }
659
660 /* translate breakpoint check & exit */
661 if(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_COND_HALT)
662 {
663 fprintf(block->source_file, " if(pc_flags[%ld] & %d)\n",
664 GX_PC_FLAGS_INDEX(gx, gx_cia),
665 GX_PCF_HALT);
666 fprintf(block->source_file, " {\n");
667 fprintf(block->source_file, " rc = %d;\n", GX_F_HALT);
668 fprintf(block->source_file, " npc = pc;\n");
669 fprintf(block->source_file, " goto save;\n");
670 fprintf(block->source_file, " }\n");
671 }
672
673 /* [don't] emit PC-setting */
674 /* fprintf(block->source_file, " pc = 0x%08x;\n", gx_cia); */
675
676 /* mark traversed instructions */
677 if(! optimized)
678 {
679 fprintf(block->source_file, " pc_flags[%ld] |= %d;\n",
680 GX_PC_FLAGS_INDEX(gx, gx_cia),
681 GX_PCF_INSTRUCTION);
682 }
683
684
685 /* translate instruction semantics */
686 next_gx_cia = tgx_emit_insn(gx, gx_cia, optimized);
687
688 skip_instruction:
689
690 /* go to next instruction */
691 gx_cia = next_gx_cia;
692 }
693 fprintf(block->source_file, " }\n");
694
695 /* dropped through last instruction in switch block */
696 fprintf(block->source_file, "\n");
697 fprintf(block->source_file, " /* dropped through PC switch */\n");
698 fprintf(block->source_file, " npc = 0x%08x;\n", gx_cia);
699 fprintf(block->source_file, " rc = %d;\n", GX_F_RANGE);
700 fprintf(block->source_file, " goto save;\n");
701
702 /* unknown length jump */
703 fprintf(block->source_file, "\n");
704 fprintf(block->source_file, "unknownjump:\n");
705 fprintf(block->source_file, " if(npc >= 0x%08lx && npc < 0x%08lx)\n",
706 gx->origin, gx->origin + gx->length);
707 fprintf(block->source_file, " goto shortjump;\n");
708
709 /* long jump */
710 fprintf(block->source_file, "\n");
711 fprintf(block->source_file, "longjump:\n");
712 fprintf(block->source_file, " rc = %d;\n", GX_F_RANGE);
713
714 /* post-block gunk: SAVE etc. */
715 fprintf(block->source_file, "\n");
716 fprintf(block->source_file, "save:\n");
717
718 tgx_emit_save_block(gx, optimized);
719
720 /* emit tail end of function */
721 fprintf(block->source_file, "\n");
722 fprintf(block->source_file, " return rc;\n");
723 fprintf(block->source_file, "}\n");
724
725 /* emit tail end of source */
726 tgx_emit_post_function(gx, optimized);
727
728 /* close source file */
729 fclose(block->source_file);
730 block->source_file = NULL;
731
732 /* compile source & produce shared object */
733
734 sprintf(compile_command,
735 "gxtool --silent --mode=compile gcc -c -g %s %s",
736 (optimized ? "-O3" : "-O"), block->source_name);
737
738 rc = system(compile_command);
739 if(rc != 0)
740 {
741 sim_io_error(sd, "Error during compiling: `%s' rc %d",
742 compile_command, rc);
743 }
744
745 /* link source */
746
747 sprintf(compile_command,
748 "gxtool --silent --mode=link gcc -export-dynamic -rpath %s -g -o lib%s.la %s.lo",
749 dir_name, base_name, base_name);
750
751 rc = system(compile_command);
752 if(rc != 0)
753 {
754 sim_io_error(sd, "Error during linking: `%s' rc %d",
755 compile_command, rc);
756 }
757
758
759 /* install */
760
761 sprintf(compile_command,
762 "gxtool --silent --mode=install cp lib%s.la %s/%s >/dev/null 2>/dev/null",
763 base_name, pwd_name, dir_name);
764
765 rc = system(compile_command);
766 if(rc != 0)
767 {
768 sim_io_error(sd, "Error during install: `%s' rc %d",
769 compile_command, rc);
770 }
771
772
773 /* finish */
774
775 sprintf(compile_command,
776 "gxtool --silent --mode=finish %s >/dev/null 2>/dev/null",
777 dir_name);
778
779 rc = system(compile_command);
780 if(rc != 0)
781 {
782 sim_io_error(sd, "Error during finish: `%s' rc %d",
783 compile_command, rc);
784 }
785
786 /* clean up */
787
788 sprintf(compile_command, "rm -f lib%s.la %s.lo", base_name, base_name);
789 rc = system(compile_command);
790 if(rc != 0)
791 {
792 sim_io_error(sd, "Error during cleanup: `%s' rc %d",
793 compile_command, rc);
794 }
795
796 /* XXX: FILL IN block->object_name from .la file */
797 sprintf(block->object_name, "%s/%s/lib%s.so.0",
798 pwd_name, dir_name, base_name);
799
800 /* measure compile time */
801 time_end = time(NULL);
802
803 if(time_end == time_begin) time_end ++; /* clamp minimum duration to 1 */
804 gx->compile_time += time_end - time_begin;
805 /* fprintf(stderr, "*** compile time: %d\n", gx->compile_time); */
806}
807
This page took 0.052339 seconds and 4 git commands to generate.