]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/sim-gx.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / common / sim-gx.c
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"
10
11 /* shared object functions */
12 #ifdef HAVE_DLFCN_H
13 #include <dlfcn.h>
14 #else
15 #error "need dlfcn.h"
16 #endif
17
18 #ifdef HAVE_ERRNO_H
19 #include <errno.h>
20 #else
21 #error "need errno.h"
22 #endif
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
27 #ifdef HAVE_TIME_H
28 #include <time.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36 #ifdef HAVE_SYS_STAT_H
37 #include <sys/stat.h>
38 #endif
39
40 #include "bfd.h"
41
42
43
44
45 /* Load the object file with given gx block. Return pointer to GX
46 function or NULL on failure. */
47
48 sim_gx_function
49 sim_gx_compiled_block_f(sim_gx_compiled_block* gx)
50 {
51 sim_gx_function f = gx->function_dlhandle;
52 SIM_DESC sd = current_state;
53 static int dlopened_main = 0;
54
55 if(f == NULL)
56 {
57 /* load object */
58 if(gx->object_dlhandle == NULL && gx->object_name != NULL)
59 {
60 if(! dlopened_main)
61 {
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)
65 {
66 sim_io_error(sd, "Load error for executable: %s",
67 dlerror());
68 }
69
70 dlopened_main = 1;
71 }
72
73 /* dlopen the gx block dso itself */
74 gx->object_dlhandle = dlopen(gx->object_name, RTLD_NOW);
75 if(gx->object_dlhandle == NULL)
76 {
77 sim_io_error(sd, "Load error for GX object %s: %s",
78 gx->object_name,
79 dlerror());
80 }
81 }
82
83 /* locate function */
84 if(gx->function_dlhandle == NULL && gx->object_dlhandle != NULL && gx->symbol_name != NULL)
85 {
86 f = gx->function_dlhandle = dlsym(gx->object_dlhandle, gx->symbol_name);
87 if(f == NULL)
88 {
89 sim_io_error(sd, "Resolve error for GX object %s symbol %s: %s",
90 gx->object_name,
91 gx->symbol_name,
92 dlerror());
93 }
94 }
95 } /* f == NULL */
96
97 return f;
98 }
99
100
101
102 /* Forget about given GX block. Remove its source/object; unload it
103 from memory. */
104 void
105 sim_gx_compiled_block_dispose(sim_gx_compiled_block* gx)
106 {
107 SIM_DESC sd = current_state;
108 int rc;
109 char compile_command[2000];
110 char la_name[2000];
111
112 /* forget dl information */
113 gx->function_dlhandle = NULL;
114
115 /* unload shared library */
116 if(gx->object_dlhandle != NULL)
117 {
118 rc = dlclose(gx->object_dlhandle);
119 if(rc != 0)
120 {
121 sim_io_error(sd, "dlclose() error for GX object %s: %s",
122 gx->object_name,
123 dlerror());
124 }
125 gx->object_dlhandle = NULL;
126 }
127
128 /* uninstall shared object */
129
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);
133
134 rc = system(compile_command);
135 if(rc != 0)
136 {
137 sim_io_error(sd, "Error during finish: `%s' rc %d",
138 compile_command, rc);
139 }
140
141
142 /* erase source */
143 /* sprintf(compile_command, "rm -f %s", block->source_name); */
144
145 /* final gasps */
146 zfree(gx->source_name);
147 zfree(gx->object_name);
148 zfree(gx->symbol_name);
149 zfree(gx);
150 }
151
152
153
154 /* Translate a piece of the code segment around given PC, in given mode. */
155 sim_gx_block*
156 sim_gx_block_create(sim_cia cia)
157 {
158 sim_gx_block* block;
159
160 /* allocate emtpy block */
161 block = zalloc(sizeof(sim_gx_block));
162
163 /* initialize block bounds, callback struct etc. */
164 tgx_block_ctor(block, cia);
165
166 /* create learning mode translation */
167 sim_gx_block_translate(block, 0 /* learning mode */);
168
169 /* add block to block list */
170 sim_gx_block_add(block);
171
172 return block;
173 }
174
175
176
177 /* Write the current block list to the state file */
178 void
179 sim_gx_write_block_list()
180 {
181 int i;
182 SIM_DESC sd = current_state;
183 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
184 FILE* f;
185 char state_file_name[PATH_MAX];
186 char *exec_name;
187
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;
192
193 /* generate base name */
194 sprintf(state_file_name, "%s/%s.gx",
195 GX_DIR,
196 exec_name);
197
198 f = fopen(state_file_name, "w");
199 if(f == NULL)
200 {
201 sim_io_error(sd, "Error: cannot write to state file %s, errno %d",
202 state_file_name, errno);
203 }
204
205 fprintf(f, "# This file was automatically generated. Do not edit.\n");
206
207 /* write block descriptors into state file */
208 for(i=0; i<blocks->gx_blocks_used; i++)
209 {
210 sim_gx_block* gx = blocks->gx_blocks[i];
211 sim_gx_compiled_block* block;
212 int j;
213 int age;
214
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++)
219 {
220 fprintf(f, "%2x ", gx->pc_flags[j]);
221 }
222 fprintf(f, "\n");
223
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);
229
230 /* write optimized mode names */
231 block = gx->optimized_block;
232 if(block)
233 fprintf(f, "OPTIMIZED %s %s %s\n",
234 block->source_name, block->object_name, block->symbol_name);
235
236 /* NB: other fields will be filled in with freshly guessed values */
237 }
238
239 (void) fclose(f);
240 }
241
242
243
244 void
245 print_gx_blocks(sim_gx_block_list* blocks, char* where)
246 {
247 printf("print_gx_blocks: %s\n", where);
248
249 if(blocks == NULL)
250 printf("(null)\n");
251 else
252 {
253 int i;
254 printf("size: %d, used: %d\n",
255 blocks->gx_blocks_size, blocks->gx_blocks_used);
256
257 /* linear search */
258 for(i=0; i<blocks->gx_blocks_used; i++)
259 {
260 sim_gx_block* gx = blocks->gx_blocks[i];
261 printf("block %d: %p\n", i, (void*) gx);
262 if(gx == NULL)
263 printf("** NULL!\n");
264 else
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"));
269 }
270
271 }
272 }
273
274
275
276 /* Read the current block list from the cache */
277 void
278 sim_gx_read_block_list()
279 {
280 SIM_DESC sd = current_state;
281 FILE* f;
282 char state_file_name[PATH_MAX];
283 const char *exec_name;
284
285 /* check for block */
286 if(STATE_PROG_BFD(sd) == NULL)
287 return;
288
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;
293
294 /* generate base name */
295 sprintf(state_file_name, "%s/%s.gx",
296 GX_DIR,
297 exec_name);
298
299 f = fopen(state_file_name, "r");
300 if(f == NULL)
301 {
302 /* XXX: print warning */
303 return;
304 }
305
306 fscanf(f, "#%*[^\n]\n"); /* swallow # comment line */
307
308 while(1)
309 {
310 unsigned_4 origin, length;
311 unsigned divisor;
312 sim_gx_block* gx;
313 int rc;
314 sim_gx_compiled_block* block;
315 unsigned age;
316 int j;
317
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 */
320 break;
321
322 gx = zalloc(sizeof(sim_gx_block));
323
324 /* initialize block bounds, callback struct etc. */
325 tgx_block_ctor2(gx, origin, length, divisor);
326
327 /* read flags */
328 fscanf(f, "FLAGS");
329 for(j=0; j<GX_PC_FLAGS_INDEX(gx, gx->origin + gx->length); j++)
330 {
331 unsigned value;
332 fscanf(f, "%2x ", & value);
333 gx->pc_flags[j] = (unsigned_1) value;
334 }
335 fscanf(f, "\n");
336
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);
346
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);
355 if(rc != 3)
356 {
357 /* oops, not an optimized block */
358 zfree(block->source_name);
359 zfree(block->object_name);
360 zfree(block->symbol_name);
361 zfree(block);
362 gx->optimized_block = NULL;
363 }
364
365 /* fill in remaining fields */
366 gx->learn_last_change = time(NULL) - age; /* make absolute */
367
368 /* store it away */
369 sim_gx_block_add(gx);
370 }
371
372 /* print_gx_blocks(STATE_BLOCKS(sd), "after restoring state"); */
373 }
374
375
376
377
378
379
380 /* Add a gx block to list */
381 void
382 sim_gx_block_add(sim_gx_block* block)
383 {
384 SIM_DESC sd = current_state;
385 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
386 int i;
387
388 /* print_gx_blocks(blocks, "pre add"); */
389
390 if(blocks == NULL)
391 blocks = STATE_BLOCKS(sd) = zalloc(sizeof(sim_gx_block_list));
392
393 /* need to enlarge block vector? */
394 if(blocks->gx_blocks_used == blocks->gx_blocks_size)
395 {
396 sim_gx_block** new_blocks;
397 int j;
398
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;
405 }
406
407 /* insert new block */
408 for(i=0; i<blocks->gx_blocks_used; i++)
409 {
410 ASSERT(blocks->gx_blocks[i] != NULL);
411
412 /* insertion point reached? */
413 if(blocks->gx_blocks[i]->origin > block->origin)
414 {
415 int j;
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 ++;
420 break;
421 }
422 }
423
424 /* end of block vector */
425 if(i == blocks->gx_blocks_used)
426 {
427 blocks->gx_blocks[blocks->gx_blocks_used ++] = block;
428 }
429
430 /* print_gx_blocks(blocks, "post add"); */
431 }
432
433
434
435 /* Remove a gx block from list */
436 void
437 sim_gx_block_remove(sim_gx_block* block)
438 {
439 SIM_DESC sd = current_state;
440 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
441 int i;
442
443 /* print_gx_blocks(blocks, "pre remove"); */
444
445 /* linear search */
446 for(i=0; i<blocks->gx_blocks_used; i++)
447 {
448 if(blocks->gx_blocks[i] == block)
449 {
450 /* found it */
451 while(i < blocks->gx_blocks_used - 1)
452 {
453 blocks->gx_blocks[i] = blocks->gx_blocks[i+1];
454 i++;
455 }
456 blocks->gx_blocks_used --;
457 break;
458 }
459 }
460
461 /* print_gx_blocks(blocks, "post remove"); */
462 }
463
464
465 /* Find a gx block from list */
466 sim_gx_block*
467 sim_gx_block_find(sim_cia cia)
468 {
469 SIM_DESC sd = current_state;
470 sim_gx_block_list* blocks = STATE_BLOCKS(sd);
471 int i;
472
473 if(blocks == NULL) return NULL;
474
475 /* print_gx_blocks(blocks, "pre find"); */
476
477 /* linear search */
478 for(i=0; i<blocks->gx_blocks_used; i++)
479 {
480 sim_gx_block* gx = blocks->gx_blocks[i];
481 ASSERT(gx != NULL);
482
483 if(GX_PC_INCLUDES(gx,cia))
484 {
485 return gx;
486 }
487 }
488
489 return NULL;
490 }
491
492
493
494 /* generate */
495 void
496 sim_gx_block_translate(sim_gx_block* gx, int optimized)
497 {
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;
504 int rc;
505 sim_cia gx_cia;
506 sim_gx_compiled_block* block = zalloc(sizeof(sim_gx_compiled_block));
507 unsigned time_begin, time_end;
508
509 time_begin = time(NULL);
510
511 if(optimized) gx->optimized_block = block;
512 else gx->learning_block = block;
513
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;
518
519 /* generate base name */
520 sprintf(dir_name, "%s/%s",
521 GX_DIR,
522 exec_name);
523
524 /* generate base name */
525 getcwd(pwd_name, sizeof(pwd_name));
526
527 /* create work directory */
528 rc = mkdir(GX_DIR, 0777);
529 if(rc != 0 &&
530 errno != EEXIST)
531 {
532 sim_io_error(sd, "Error: cannot create directory %s, errno %d",
533 GX_DIR, errno);
534 }
535
536 rc = mkdir(dir_name, 0777);
537 if(rc != 0 &&
538 errno != EEXIST)
539 {
540 sim_io_error(sd, "Error: cannot create directory %s, errno %d",
541 dir_name, errno);
542 }
543
544 /* compute base name */
545 if(optimized)
546 sprintf(base_name, "%08x_opt%d", (unsigned) gx->origin, gx->opt_compile_count);
547 else
548 sprintf(base_name, "%08x", (unsigned) gx->origin);
549
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);
554
555 /* generate symbol name for gx function */
556 block->symbol_name = zalloc(PATH_MAX);
557 sprintf(block->symbol_name, "gx_%s", base_name);
558
559 /* open source file */
560 block->source_file = fopen(block->source_name, "w");
561 if(block->source_file == NULL)
562 {
563 sim_io_error(sd, "Error: cannot open file %s, errno %d",
564 block->source_name, errno);
565 }
566
567 /* front matter */
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));
570
571 /* emit head end of source */
572 tgx_emit_pre_function(gx, optimized);
573
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");
581 if(! optimized)
582 fprintf(block->source_file, " unsigned int insn_count = 0;\n");
583
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");
588 gx_cia = gx->origin;
589 while(GX_PC_INCLUDES(gx,gx_cia))
590 {
591 sim_cia next_gx_cia;
592 if((! optimized) ||
593 (GX_PC_FLAGS(gx, gx_cia) & GX_PCF_JUMPTARGET))
594 {
595 fprintf(block->source_file, " && gx_label_%ld,\n",
596 ((gx_cia - gx->origin) / gx->divisor));
597 }
598 else
599 {
600 fprintf(block->source_file, " && gx_label_default,\n");
601 }
602 gx_cia = gx_cia + gx->divisor;
603 }
604 fprintf(block->source_file, " };\n");
605 fprintf(block->source_file, "#endif /*__GNUC__*/\n");
606
607 /* pre-block gunk: register load */
608 tgx_emit_load_block(gx, optimized);
609
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");
614
615 /* translate jumptarget table */
616 if(! optimized)
617 {
618 fprintf(block->source_file, " pc_flags[(pc - 0x%08x) / %u] |= %d;\n",
619 (unsigned)gx->origin, gx->divisor, GX_PCF_JUMPTARGET);
620 }
621
622 /* enforce learning mode run limit */
623 if(! optimized)
624 {
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");
632 }
633
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");
644
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");
657
658 /* start translating at the origin */
659 gx_cia = gx->origin;
660
661 /* translate instructions in block */
662 while(GX_PC_INCLUDES(gx,gx_cia))
663 {
664 sim_cia next_gx_cia;
665
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));
670
671
672 /* skip over this instruction if it is not executed */
673 if(optimized && !(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_INSTRUCTION))
674 {
675 fprintf(block->source_file, " /* (not reached) */\n");
676
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)
680 {
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");
687 }
688
689 next_gx_cia = gx_cia + gx->divisor;
690 goto skip_instruction;
691 }
692
693 /* translate PC case statement */
694 if((! optimized) ||
695 (GX_PC_FLAGS(gx, gx_cia) & GX_PCF_JUMPTARGET))
696 {
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");
703 }
704
705 /* translate breakpoint check & exit */
706 if(GX_PC_FLAGS(gx, gx_cia) & GX_PCF_COND_HALT)
707 {
708 fprintf(block->source_file, " if(pc_flags[%d] & %d)\n",
709 GX_PC_FLAGS_INDEX(gx, gx_cia),
710 GX_PCF_HALT);
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");
716 }
717
718 /* [don't] emit PC-setting */
719 /* fprintf(block->source_file, " pc = 0x%08x;\n", gx_cia); */
720
721 /* mark traversed instructions */
722 if(! optimized)
723 {
724 fprintf(block->source_file, " pc_flags[%d] |= %d;\n",
725 GX_PC_FLAGS_INDEX(gx, gx_cia),
726 GX_PCF_INSTRUCTION);
727 }
728
729
730 /* translate instruction semantics */
731 next_gx_cia = tgx_emit_insn(gx, gx_cia, optimized);
732
733 skip_instruction:
734
735 /* go to next instruction */
736 gx_cia = next_gx_cia;
737 }
738 fprintf(block->source_file, " }\n");
739
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");
746
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");
753
754 /* long jump */
755 fprintf(block->source_file, "\n");
756 fprintf(block->source_file, "longjump:\n");
757 fprintf(block->source_file, " rc = %d;\n", GX_F_RANGE);
758
759 /* post-block gunk: SAVE etc. */
760 fprintf(block->source_file, "\n");
761 fprintf(block->source_file, "save:\n");
762
763 tgx_emit_save_block(gx, optimized);
764
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");
769
770 /* emit tail end of source */
771 tgx_emit_post_function(gx, optimized);
772
773 /* close source file */
774 fclose(block->source_file);
775 block->source_file = NULL;
776
777 /* compile source & produce shared object */
778
779 {
780 char* extra_flags = NULL;
781 #ifdef HAVE_GETENV
782 extra_flags = getenv("GX_FLAGS");
783 #endif
784 if (extra_flags == NULL) extra_flags = "";
785
786 sprintf(compile_command,
787 "gxtool --silent --mode=compile gcc %s %s -c %s",
788 (optimized ? "-O9 -fomit-frame-pointer" : "-O"),
789 extra_flags,
790 block->source_name);
791
792 rc = system(compile_command);
793 if(rc != 0)
794 {
795 sim_io_error(sd, "Error during compiling: `%s' rc %d",
796 compile_command, rc);
797 }
798
799 /* link source */
800
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);
804
805 rc = system(compile_command);
806 if(rc != 0)
807 {
808 sim_io_error(sd, "Error during linking: `%s' rc %d",
809 compile_command, rc);
810 }
811 }
812
813 /* install */
814
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);
818
819 rc = system(compile_command);
820 if(rc != 0)
821 {
822 sim_io_error(sd, "Error during install: `%s' rc %d",
823 compile_command, rc);
824 }
825
826
827 /* finish */
828
829 sprintf(compile_command,
830 "gxtool --silent --mode=finish %s >/dev/null 2>/dev/null",
831 dir_name);
832
833 rc = system(compile_command);
834 if(rc != 0)
835 {
836 sim_io_error(sd, "Error during finish: `%s' rc %d",
837 compile_command, rc);
838 }
839
840 /* clean up */
841
842 sprintf(compile_command, "gxtool --silent --mode=uninstall rm -f lib%s.la %s.lo", base_name, base_name);
843 rc = system(compile_command);
844 if(rc != 0)
845 {
846 sim_io_error(sd, "Error during cleanup: `%s' rc %d",
847 compile_command, rc);
848 }
849
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);
853
854 /* measure compile time */
855 time_end = time(NULL);
856
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); */
860 }
861