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