]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-gx.c
1 /* GX target-independent functions for block translation.
2 Copyright (C) 1998 Cygnus Solutions. */
6 #include "sim-assert.h"
11 /* shared object functions */
36 #ifdef HAVE_SYS_STAT_H
45 /* Load the object file with given gx block. Return pointer to GX
46 function or NULL on failure. */
49 sim_gx_compiled_block_f(sim_gx_compiled_block
* gx
)
51 sim_gx_function f
= gx
->function_dlhandle
;
52 SIM_DESC sd
= current_state
;
53 static int dlopened_main
= 0;
58 if(gx
->object_dlhandle
== NULL
&& gx
->object_name
!= NULL
)
62 /* dlopen executable itself first to share symbols with shared library */
63 void* exec_handle
= dlopen(NULL
, RTLD_LAZY
| RTLD_GLOBAL
);
64 if(exec_handle
== NULL
)
66 sim_io_error(sd
, "Load error for executable: %s",
73 /* dlopen the gx block dso itself */
74 gx
->object_dlhandle
= dlopen(gx
->object_name
, RTLD_NOW
);
75 if(gx
->object_dlhandle
== NULL
)
77 sim_io_error(sd
, "Load error for GX object %s: %s",
84 if(gx
->function_dlhandle
== NULL
&& gx
->object_dlhandle
!= NULL
&& gx
->symbol_name
!= NULL
)
86 f
= gx
->function_dlhandle
= dlsym(gx
->object_dlhandle
, gx
->symbol_name
);
89 sim_io_error(sd
, "Resolve error for GX object %s symbol %s: %s",
102 /* Forget about given GX block. Remove its source/object; unload it
105 sim_gx_compiled_block_dispose(sim_gx_compiled_block
* gx
)
107 SIM_DESC sd
= current_state
;
109 char compile_command
[2000];
112 /* forget dl information */
113 gx
->function_dlhandle
= NULL
;
115 /* unload shared library */
116 if(gx
->object_dlhandle
!= NULL
)
118 rc
= dlclose(gx
->object_dlhandle
);
121 sim_io_error(sd
, "dlclose() error for GX object %s: %s",
125 gx
->object_dlhandle
= NULL
;
128 /* uninstall shared object */
130 strcpy(la_name
, gx
->object_name
);
131 strcpy(strstr(la_name
, ".so.0"), ".la");
132 sprintf(compile_command
, "gxtool --silent --mode=uninstall rm -f %s", la_name
);
134 rc
= system(compile_command
);
137 sim_io_error(sd
, "Error during finish: `%s' rc %d",
138 compile_command
, rc
);
143 /* sprintf(compile_command, "rm -f %s", block->source_name); */
146 zfree(gx
->source_name
);
147 zfree(gx
->object_name
);
148 zfree(gx
->symbol_name
);
154 /* Translate a piece of the code segment around given PC, in given mode. */
156 sim_gx_block_create(sim_cia cia
)
160 /* allocate emtpy block */
161 block
= zalloc(sizeof(sim_gx_block
));
163 /* initialize block bounds, callback struct etc. */
164 tgx_block_ctor(block
, cia
);
166 /* create learning mode translation */
167 sim_gx_block_translate(block
, 0 /* learning mode */);
169 /* add block to block list */
170 sim_gx_block_add(block
);
177 /* Write the current block list to the state file */
179 sim_gx_write_block_list()
182 SIM_DESC sd
= current_state
;
183 sim_gx_block_list
* blocks
= STATE_BLOCKS(sd
);
185 char state_file_name
[PATH_MAX
];
188 /* get base of executable name */
189 exec_name
= bfd_get_filename(STATE_PROG_BFD(sd
));
190 if(strrchr(exec_name
, '/') != NULL
)
191 exec_name
= strrchr(exec_name
, '/') + 1;
193 /* generate base name */
194 sprintf(state_file_name
, "%s/%s.gx",
198 f
= fopen(state_file_name
, "w");
201 sim_io_error(sd
, "Error: cannot write to state file %s, errno %d",
202 state_file_name
, errno
);
205 fprintf(f
, "# This file was automatically generated. Do not edit.\n");
207 /* write block descriptors into state file */
208 for(i
=0; i
<blocks
->gx_blocks_used
; i
++)
210 sim_gx_block
* gx
= blocks
->gx_blocks
[i
];
211 sim_gx_compiled_block
* block
;
215 age
= time(NULL
) - gx
->learn_last_change
; /* store interval */
216 fprintf(f
, "BLOCK 0x%x 0x%x %u %u\n", (unsigned)gx
->origin
, (unsigned)gx
->length
, gx
->divisor
, age
);
217 fprintf(f
, "FLAGS ");
218 for(j
=0; j
<GX_PC_FLAGS_INDEX(gx
, gx
->origin
+ gx
->length
); j
++)
220 fprintf(f
, "%2x ", gx
->pc_flags
[j
]);
224 /* write learning mode names */
225 block
= gx
->learning_block
;
226 fprintf(f
, "LEARNING %s %s %s %lu %u\n",
227 block
->source_name
, block
->object_name
, block
->symbol_name
,
228 gx
->compile_time
, gx
->opt_compile_count
);
230 /* write optimized mode names */
231 block
= gx
->optimized_block
;
233 fprintf(f
, "OPTIMIZED %s %s %s\n",
234 block
->source_name
, block
->object_name
, block
->symbol_name
);
236 /* NB: other fields will be filled in with freshly guessed values */
245 print_gx_blocks(sim_gx_block_list
* blocks
, char* where
)
247 printf("print_gx_blocks: %s\n", where
);
254 printf("size: %d, used: %d\n",
255 blocks
->gx_blocks_size
, blocks
->gx_blocks_used
);
258 for(i
=0; i
<blocks
->gx_blocks_used
; i
++)
260 sim_gx_block
* gx
= blocks
->gx_blocks
[i
];
261 printf("block %d: %p\n", i
, (void*) gx
);
263 printf("** NULL!\n");
265 printf(" begin 0x%08x length 0x%08x [opt %d%s]\n",
266 (unsigned)gx
->origin
, (unsigned)gx
->length
,
267 gx
->opt_compile_count
,
268 (gx
->optimized_block
? " loaded" : " discarded"));
276 /* Read the current block list from the cache */
278 sim_gx_read_block_list()
280 SIM_DESC sd
= current_state
;
282 char state_file_name
[PATH_MAX
];
283 const char *exec_name
;
285 /* check for block */
286 if(STATE_PROG_BFD(sd
) == NULL
)
289 /* get base of executable name */
290 exec_name
= bfd_get_filename(STATE_PROG_BFD(sd
));
291 if(strrchr(exec_name
, '/') != NULL
)
292 exec_name
= strrchr(exec_name
, '/') + 1;
294 /* generate base name */
295 sprintf(state_file_name
, "%s/%s.gx",
299 f
= fopen(state_file_name
, "r");
302 /* XXX: print warning */
306 fscanf(f
, "#%*[^\n]\n"); /* swallow # comment line */
310 unsigned_4 origin
, length
;
314 sim_gx_compiled_block
* block
;
318 rc
= fscanf(f
, "BLOCK 0x%0x 0x%x %u %u\n", (unsigned*)& origin
, (unsigned*)& length
, & divisor
, & age
);
319 if(rc
!= 4) /* not all fields matched - assume EOF */
322 gx
= zalloc(sizeof(sim_gx_block
));
324 /* initialize block bounds, callback struct etc. */
325 tgx_block_ctor2(gx
, origin
, length
, divisor
);
329 for(j
=0; j
<GX_PC_FLAGS_INDEX(gx
, gx
->origin
+ gx
->length
); j
++)
332 fscanf(f
, "%2x ", & value
);
333 gx
->pc_flags
[j
] = (unsigned_1
) value
;
337 /* read learning mode info */
338 block
= zalloc(sizeof(sim_gx_compiled_block
));
339 gx
->learning_block
= block
;
340 block
->source_name
= zalloc(PATH_MAX
);
341 block
->object_name
= zalloc(PATH_MAX
);
342 block
->symbol_name
= zalloc(PATH_MAX
);
343 fscanf(f
, "LEARNING %s %s %s %u %u\n",
344 block
->source_name
, block
->object_name
, block
->symbol_name
,
345 (unsigned*) & gx
->compile_time
, & gx
->opt_compile_count
);
347 /* read optimized mode info */
348 block
= zalloc(sizeof(sim_gx_compiled_block
));
349 gx
->optimized_block
= block
;
350 block
->source_name
= zalloc(PATH_MAX
);
351 block
->object_name
= zalloc(PATH_MAX
);
352 block
->symbol_name
= zalloc(PATH_MAX
);
353 rc
= fscanf(f
, "OPTIMIZED %s %s %s\n",
354 block
->source_name
, block
->object_name
, block
->symbol_name
);
357 /* oops, not an optimized block */
358 zfree(block
->source_name
);
359 zfree(block
->object_name
);
360 zfree(block
->symbol_name
);
362 gx
->optimized_block
= NULL
;
365 /* fill in remaining fields */
366 gx
->learn_last_change
= time(NULL
) - age
; /* make absolute */
369 sim_gx_block_add(gx
);
372 /* print_gx_blocks(STATE_BLOCKS(sd), "after restoring state"); */
380 /* Add a gx block to list */
382 sim_gx_block_add(sim_gx_block
* block
)
384 SIM_DESC sd
= current_state
;
385 sim_gx_block_list
* blocks
= STATE_BLOCKS(sd
);
388 /* print_gx_blocks(blocks, "pre add"); */
391 blocks
= STATE_BLOCKS(sd
) = zalloc(sizeof(sim_gx_block_list
));
393 /* need to enlarge block vector? */
394 if(blocks
->gx_blocks_used
== blocks
->gx_blocks_size
)
396 sim_gx_block
** new_blocks
;
399 blocks
->gx_blocks_size
+= 20;
400 new_blocks
= zalloc(blocks
->gx_blocks_size
* sizeof(sim_gx_block
*));
401 for(j
=0; j
<blocks
->gx_blocks_used
; j
++)
402 new_blocks
[j
] = blocks
->gx_blocks
[j
];
403 if(blocks
->gx_blocks
) zfree(blocks
->gx_blocks
);
404 blocks
->gx_blocks
= new_blocks
;
407 /* insert new block */
408 for(i
=0; i
<blocks
->gx_blocks_used
; i
++)
410 ASSERT(blocks
->gx_blocks
[i
] != NULL
);
412 /* insertion point reached? */
413 if(blocks
->gx_blocks
[i
]->origin
> block
->origin
)
416 for(j
=blocks
->gx_blocks_used
; j
>=i
; j
--)
417 blocks
->gx_blocks
[j
] = blocks
->gx_blocks
[j
-1];
418 blocks
->gx_blocks
[i
] = block
;
419 blocks
->gx_blocks_used
++;
424 /* end of block vector */
425 if(i
== blocks
->gx_blocks_used
)
427 blocks
->gx_blocks
[blocks
->gx_blocks_used
++] = block
;
430 /* print_gx_blocks(blocks, "post add"); */
435 /* Remove a gx block from list */
437 sim_gx_block_remove(sim_gx_block
* block
)
439 SIM_DESC sd
= current_state
;
440 sim_gx_block_list
* blocks
= STATE_BLOCKS(sd
);
443 /* print_gx_blocks(blocks, "pre remove"); */
446 for(i
=0; i
<blocks
->gx_blocks_used
; i
++)
448 if(blocks
->gx_blocks
[i
] == block
)
451 while(i
< blocks
->gx_blocks_used
- 1)
453 blocks
->gx_blocks
[i
] = blocks
->gx_blocks
[i
+1];
456 blocks
->gx_blocks_used
--;
461 /* print_gx_blocks(blocks, "post remove"); */
465 /* Find a gx block from list */
467 sim_gx_block_find(sim_cia cia
)
469 SIM_DESC sd
= current_state
;
470 sim_gx_block_list
* blocks
= STATE_BLOCKS(sd
);
473 if(blocks
== NULL
) return NULL
;
475 /* print_gx_blocks(blocks, "pre find"); */
478 for(i
=0; i
<blocks
->gx_blocks_used
; i
++)
480 sim_gx_block
* gx
= blocks
->gx_blocks
[i
];
483 if(GX_PC_INCLUDES(gx
,cia
))
496 sim_gx_block_translate(sim_gx_block
* gx
, int optimized
)
498 char pwd_name
[PATH_MAX
];
499 char dir_name
[PATH_MAX
];
500 char base_name
[PATH_MAX
];
501 char compile_command
[PATH_MAX
*4];
502 const char* exec_name
;
503 SIM_DESC sd
= current_state
;
506 sim_gx_compiled_block
* block
= zalloc(sizeof(sim_gx_compiled_block
));
507 unsigned time_begin
, time_end
;
509 time_begin
= time(NULL
);
511 if(optimized
) gx
->optimized_block
= block
;
512 else gx
->learning_block
= block
;
514 /* get base of executable name */
515 exec_name
= bfd_get_filename(STATE_PROG_BFD(sd
));
516 if(strrchr(exec_name
, '/') != NULL
)
517 exec_name
= strrchr(exec_name
, '/') + 1;
519 /* generate base name */
520 sprintf(dir_name
, "%s/%s",
524 /* generate base name */
525 getcwd(pwd_name
, sizeof(pwd_name
));
527 /* create work directory */
528 rc
= mkdir(GX_DIR
, 0777);
532 sim_io_error(sd
, "Error: cannot create directory %s, errno %d",
536 rc
= mkdir(dir_name
, 0777);
540 sim_io_error(sd
, "Error: cannot create directory %s, errno %d",
544 /* compute base name */
546 sprintf(base_name
, "%08x_opt%d", (unsigned) gx
->origin
, gx
->opt_compile_count
);
548 sprintf(base_name
, "%08x", (unsigned) gx
->origin
);
550 /* generate source/object file names */
551 block
->source_name
= zalloc(PATH_MAX
);
552 block
->object_name
= zalloc(PATH_MAX
);
553 sprintf(block
->source_name
, "%s/%s.c", dir_name
, base_name
);
555 /* generate symbol name for gx function */
556 block
->symbol_name
= zalloc(PATH_MAX
);
557 sprintf(block
->symbol_name
, "gx_%s", base_name
);
559 /* open source file */
560 block
->source_file
= fopen(block
->source_name
, "w");
561 if(block
->source_file
== NULL
)
563 sim_io_error(sd
, "Error: cannot open file %s, errno %d",
564 block
->source_name
, errno
);
568 fprintf(block
->source_file
, "/* sim-gx version %d */\n", GX_VERSION
);
569 fprintf(block
->source_file
, "/* gx block date stamp %lu */\n\n", time(NULL
));
571 /* emit head end of source */
572 tgx_emit_pre_function(gx
, optimized
);
574 /* emit function header */
575 fprintf(block
->source_file
, "\n\n");
576 fprintf(block
->source_file
, "extern int\n");
577 fprintf(block
->source_file
, "%s", block
->symbol_name
);
578 fprintf(block
->source_file
, "(struct tgx_info* info)\n");
579 fprintf(block
->source_file
, "{\n");
580 fprintf(block
->source_file
, " int rc = 0;\n");
582 fprintf(block
->source_file
, " unsigned int insn_count = 0;\n");
584 /* emit threaded goto vector for __GNUC__ */
585 fprintf(block
->source_file
, "#ifdef __GNUC__\n");
586 fprintf(block
->source_file
, " static void* jump_table[] =\n");
587 fprintf(block
->source_file
, " {\n");
589 while(GX_PC_INCLUDES(gx
,gx_cia
))
593 (GX_PC_FLAGS(gx
, gx_cia
) & GX_PCF_JUMPTARGET
))
595 fprintf(block
->source_file
, " && gx_label_%ld,\n",
596 ((gx_cia
- gx
->origin
) / gx
->divisor
));
600 fprintf(block
->source_file
, " && gx_label_default,\n");
602 gx_cia
= gx_cia
+ gx
->divisor
;
604 fprintf(block
->source_file
, " };\n");
605 fprintf(block
->source_file
, "#endif /*__GNUC__*/\n");
607 /* pre-block gunk: register load */
608 tgx_emit_load_block(gx
, optimized
);
610 /* emit intra-block jump label */
611 fprintf(block
->source_file
, "\n");
612 fprintf(block
->source_file
, "shortjump:\n");
613 fprintf(block
->source_file
, " pc = npc;\n");
615 /* translate jumptarget table */
618 fprintf(block
->source_file
, " pc_flags[(pc - 0x%08x) / %u] |= %d;\n",
619 (unsigned)gx
->origin
, gx
->divisor
, GX_PCF_JUMPTARGET
);
622 /* enforce learning mode run limit */
625 fprintf(block
->source_file
, " insn_count++;\n");
626 fprintf(block
->source_file
, " if (insn_count > %d)\n", GX_LEARN_RUN_LIMIT
);
627 fprintf(block
->source_file
, " {\n");
628 fprintf(block
->source_file
, " rc = %d;\n", GX_F_YIELD
);
629 fprintf(block
->source_file
, " npc = pc;\n");
630 fprintf(block
->source_file
, " goto save;\n");
631 fprintf(block
->source_file
, " }\n");
634 /* emit PC switch, use compressed case numbers */
635 fprintf(block
->source_file
, "\n");
636 fprintf(block
->source_file
, "#ifdef __GNUC__\n");
637 fprintf(block
->source_file
, " goto * jump_table[((pc - 0x%08x) / %u)];\n",
638 (unsigned)gx
->origin
, gx
->divisor
);
639 fprintf(block
->source_file
, "#else /* ! __GNUC__*/\n");
640 fprintf(block
->source_file
, " switch((pc - 0x%08x) / %u)\n",
641 (unsigned)gx
->origin
, gx
->divisor
);
642 fprintf(block
->source_file
, "#endif /*__GNUC__*/\n");
643 fprintf(block
->source_file
, " {\n");
645 /* handle bad-PC event */
646 fprintf(block
->source_file
, " /* handle unknown jump target */\n");
647 fprintf(block
->source_file
, "#ifdef __GNUC__\n");
648 fprintf(block
->source_file
, " gx_label_default:\n");
649 fprintf(block
->source_file
, "#else /* ! __GNUC__*/\n");
650 fprintf(block
->source_file
, " default:\n");
651 fprintf(block
->source_file
, "#endif /*__GNUC__*/\n");
652 fprintf(block
->source_file
, " pc_flags[%d] |= %d;\n",
653 GX_PC_FLAGS_INDEX(gx
, gx_cia
), GX_PCF_INSTRUCTION
);
654 fprintf(block
->source_file
, " rc = %d;\n", GX_F_NONPC
);
655 fprintf(block
->source_file
, " npc = pc;\n");
656 fprintf(block
->source_file
, " goto save;\n");
658 /* start translating at the origin */
661 /* translate instructions in block */
662 while(GX_PC_INCLUDES(gx
,gx_cia
))
666 /* translate PC case statement */
667 fprintf(block
->source_file
, "\n");
668 fprintf(block
->source_file
, " /* PC: 0x%08x, flags %02x */\n",
669 gx_cia
, (int) GX_PC_FLAGS(gx
, gx_cia
));
672 /* skip over this instruction if it is not executed */
673 if(optimized
&& !(GX_PC_FLAGS(gx
, gx_cia
) & GX_PCF_INSTRUCTION
))
675 fprintf(block
->source_file
, " /* (not reached) */\n");
677 /* prevent fall-through from previous translated insn */
678 if(gx_cia
> gx
->origin
&&
679 GX_PC_FLAGS(gx
, (gx_cia
- gx
->divisor
)) & GX_PCF_INSTRUCTION
)
681 fprintf(block
->source_file
, " /* prevent fall-through */\n");
682 fprintf(block
->source_file
, " npc = 0x%08x;\n", gx_cia
);
683 fprintf(block
->source_file
, " pc_flags[%d] |= %d;\n",
684 GX_PC_FLAGS_INDEX(gx
, gx_cia
), GX_PCF_INSTRUCTION
);
685 fprintf(block
->source_file
, " rc = %d;\n", GX_F_NONPC
);
686 fprintf(block
->source_file
, " goto save;\n");
689 next_gx_cia
= gx_cia
+ gx
->divisor
;
690 goto skip_instruction
;
693 /* translate PC case statement */
695 (GX_PC_FLAGS(gx
, gx_cia
) & GX_PCF_JUMPTARGET
))
697 fprintf(block
->source_file
, " gx_label_%d:\n",
698 ((gx_cia
- gx
->origin
) / gx
->divisor
));
699 fprintf(block
->source_file
, "#ifndef __GNUC__\n");
700 fprintf(block
->source_file
, " case %d:\n",
701 ((gx_cia
- gx
->origin
) / gx
->divisor
));
702 fprintf(block
->source_file
, "#endif /* !__GNUC__ */\n");
705 /* translate breakpoint check & exit */
706 if(GX_PC_FLAGS(gx
, gx_cia
) & GX_PCF_COND_HALT
)
708 fprintf(block
->source_file
, " if(pc_flags[%d] & %d)\n",
709 GX_PC_FLAGS_INDEX(gx
, gx_cia
),
711 fprintf(block
->source_file
, " {\n");
712 fprintf(block
->source_file
, " rc = %d;\n", GX_F_HALT
);
713 fprintf(block
->source_file
, " npc = pc;\n");
714 fprintf(block
->source_file
, " goto save;\n");
715 fprintf(block
->source_file
, " }\n");
718 /* [don't] emit PC-setting */
719 /* fprintf(block->source_file, " pc = 0x%08x;\n", gx_cia); */
721 /* mark traversed instructions */
724 fprintf(block
->source_file
, " pc_flags[%d] |= %d;\n",
725 GX_PC_FLAGS_INDEX(gx
, gx_cia
),
730 /* translate instruction semantics */
731 next_gx_cia
= tgx_emit_insn(gx
, gx_cia
, optimized
);
735 /* go to next instruction */
736 gx_cia
= next_gx_cia
;
738 fprintf(block
->source_file
, " }\n");
740 /* dropped through last instruction in switch block */
741 fprintf(block
->source_file
, "\n");
742 fprintf(block
->source_file
, " /* dropped through PC switch */\n");
743 fprintf(block
->source_file
, " npc = 0x%08x;\n", gx_cia
);
744 fprintf(block
->source_file
, " rc = %d;\n", GX_F_RANGE
);
745 fprintf(block
->source_file
, " goto save;\n");
747 /* unknown length jump */
748 fprintf(block
->source_file
, "\n");
749 fprintf(block
->source_file
, "unknownjump:\n");
750 fprintf(block
->source_file
, " if(npc >= 0x%08x && npc < 0x%08x)\n",
751 (unsigned)gx
->origin
, (unsigned)gx
->origin
+ gx
->length
);
752 fprintf(block
->source_file
, " goto shortjump;\n");
755 fprintf(block
->source_file
, "\n");
756 fprintf(block
->source_file
, "longjump:\n");
757 fprintf(block
->source_file
, " rc = %d;\n", GX_F_RANGE
);
759 /* post-block gunk: SAVE etc. */
760 fprintf(block
->source_file
, "\n");
761 fprintf(block
->source_file
, "save:\n");
763 tgx_emit_save_block(gx
, optimized
);
765 /* emit tail end of function */
766 fprintf(block
->source_file
, "\n");
767 fprintf(block
->source_file
, " return rc;\n");
768 fprintf(block
->source_file
, "}\n");
770 /* emit tail end of source */
771 tgx_emit_post_function(gx
, optimized
);
773 /* close source file */
774 fclose(block
->source_file
);
775 block
->source_file
= NULL
;
777 /* compile source & produce shared object */
780 char* extra_flags
= NULL
;
782 extra_flags
= getenv("GX_FLAGS");
784 if (extra_flags
== NULL
) extra_flags
= "";
786 sprintf(compile_command
,
787 "gxtool --silent --mode=compile gcc %s %s -c %s",
788 (optimized
? "-O9 -fomit-frame-pointer" : "-O"),
792 rc
= system(compile_command
);
795 sim_io_error(sd
, "Error during compiling: `%s' rc %d",
796 compile_command
, rc
);
801 sprintf(compile_command
,
802 "gxtool --silent --mode=link gcc -export-dynamic -rpath %s %s -o lib%s.la %s.lo",
803 dir_name
, extra_flags
, base_name
, base_name
);
805 rc
= system(compile_command
);
808 sim_io_error(sd
, "Error during linking: `%s' rc %d",
809 compile_command
, rc
);
815 sprintf(compile_command
,
816 "gxtool --silent --mode=install cp lib%s.la %s/%s >/dev/null 2>/dev/null",
817 base_name
, pwd_name
, dir_name
);
819 rc
= system(compile_command
);
822 sim_io_error(sd
, "Error during install: `%s' rc %d",
823 compile_command
, rc
);
829 sprintf(compile_command
,
830 "gxtool --silent --mode=finish %s >/dev/null 2>/dev/null",
833 rc
= system(compile_command
);
836 sim_io_error(sd
, "Error during finish: `%s' rc %d",
837 compile_command
, rc
);
842 sprintf(compile_command
, "gxtool --silent --mode=uninstall rm -f lib%s.la %s.lo", base_name
, base_name
);
843 rc
= system(compile_command
);
846 sim_io_error(sd
, "Error during cleanup: `%s' rc %d",
847 compile_command
, rc
);
850 /* XXX: FILL IN block->object_name from .la file */
851 sprintf(block
->object_name
, "%s/%s/lib%s.so.0",
852 pwd_name
, dir_name
, base_name
);
854 /* measure compile time */
855 time_end
= time(NULL
);
857 if(time_end
== time_begin
) time_end
++; /* clamp minimum duration to 1 */
858 gx
->compile_time
+= time_end
- time_begin
;
859 /* fprintf(stderr, "*** compile time: %d\n", gx->compile_time); */