Commit | Line | Data |
---|---|---|
92fa4579 FCE |
1 | /* GX generic simulator run. |
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 | #ifdef HAVE_TIME_H | |
10 | #include <time.h> | |
11 | #endif | |
12 | ||
13 | ||
14 | /* GX implementation of sim_engine_run that works within the | |
15 | sim_engine setjmp/longjmp framework. */ | |
16 | ||
17 | ||
18 | void | |
19 | sim_engine_run (SIM_DESC sd, | |
20 | int next_cpu_nr, | |
21 | int nr_cpus, /* ignore */ | |
22 | int siggnal) /* ignore */ | |
23 | { | |
24 | sim_cpu* cpu; | |
25 | int cont = 1; | |
26 | int rc; | |
27 | ||
28 | SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); | |
29 | cpu = STATE_CPU (sd, next_cpu_nr); | |
30 | ||
31 | while(cont) | |
32 | { | |
33 | sim_gx_block* block; | |
34 | sim_gx_compiled_block* compiled_block; | |
35 | sim_gx_function f; | |
36 | sim_cia cia = CIA_GET(cpu); | |
37 | int optimized; | |
38 | int pre_checksum, post_checksum; | |
39 | ||
40 | /* find optimized gx block that includes this PC */ | |
41 | block = sim_gx_block_find(cia); | |
42 | if(block == NULL) | |
43 | { | |
44 | /* start new learning block */ | |
45 | block = sim_gx_block_create(cia); | |
46 | } | |
47 | ASSERT(block != NULL); | |
48 | ||
49 | /* pick preferred compiled block */ | |
50 | if(block->optimized_block != NULL) | |
51 | { | |
52 | compiled_block = block->optimized_block; | |
53 | /* no stats */ | |
54 | } | |
55 | else | |
56 | { | |
57 | /* test for optimization policy */ | |
58 | if(tgx_optimize_test(block)) | |
59 | { | |
60 | block->opt_compile_count ++; | |
61 | sim_gx_block_translate(block, 1 /* optimized */); | |
62 | compiled_block = block->optimized_block; | |
63 | optimized = 1; | |
64 | } | |
65 | else | |
66 | { | |
67 | compiled_block = block->learning_block; | |
68 | optimized = 0; | |
69 | } | |
70 | } | |
71 | ASSERT(compiled_block != NULL); | |
72 | ||
73 | /* load & resolve gx function */ | |
74 | f = sim_gx_compiled_block_f(compiled_block); | |
75 | ||
76 | /* XXX: debug | |
77 | printf("calling into gx function %p, pc=%08lx, opt %d\n", | |
78 | (void*) f, (unsigned long) cpu->regs.h_pc, optimized); | |
79 | */ | |
80 | ||
81 | /* compute pc_flags checksum */ | |
82 | if(! optimized) | |
83 | { | |
84 | int i; | |
85 | pre_checksum = 0; | |
86 | for(i=0; i < block->length / block->divisor; i++) | |
87 | pre_checksum += block->pc_flags[i]; | |
88 | } | |
89 | ||
90 | /* call into gx function */ | |
91 | rc = (*f)(& cpu->regs, block->pc_flags, block->callbacks); | |
92 | ||
93 | /* compute pc_flags checksum */ | |
94 | if(! optimized) | |
95 | { | |
96 | int i; | |
97 | post_checksum = 0; | |
98 | for(i=0; i < block->length / block->divisor; i++) | |
99 | post_checksum += block->pc_flags[i]; | |
100 | ||
101 | if(post_checksum != pre_checksum) /* system changing */ | |
102 | { | |
103 | block->learn_last_change = time(NULL); | |
104 | } | |
105 | } | |
106 | ||
107 | /* XXX: debug | |
108 | printf("returned from gx function %p, rc=%d, pc=%08lx\n", | |
109 | (void*) f, rc, (unsigned long) cpu->regs.h_pc); | |
110 | */ | |
111 | ||
112 | switch(rc) | |
113 | { | |
114 | case GX_F_YIELD: /* gx block voluntarily gave up control */ | |
115 | case GX_F_RANGE: /* PC travelled outside this block */ | |
116 | ; /* continue block dispatch loop */ | |
117 | break; | |
118 | ||
119 | case GX_F_NONPC: /* non-instruction PC in this block */ | |
120 | if(compiled_block == block->optimized_block) | |
121 | { | |
122 | /* sim_io_printf(sd, "NOTE: cancelling premature optimization, GX block %p, PC %08lx\n", | |
123 | block, (long) cpu->regs.h_pc); */ | |
124 | sim_gx_compiled_block_dispose(compiled_block); | |
125 | block->learn_last_change = time(NULL); | |
126 | block->optimized_block = NULL; | |
127 | } | |
128 | else | |
129 | { | |
130 | /* learning-mode gx block should not fail this way */ | |
131 | sim_io_error(sd, "Internal error - GX block cia %08lx NONPC\n", (long) cia); | |
132 | } | |
133 | break; | |
134 | ||
135 | case GX_F_HALT: /* gx function returning control */ | |
136 | cont = 0; /* merely exit loop */ | |
137 | break; | |
138 | ||
139 | /* should not happen */ | |
140 | default: | |
141 | sim_io_error(sd, "Translation error (bad rc 0x%d in gx block)", rc); | |
142 | /* NOTREACHED */ | |
143 | } | |
144 | ||
145 | if(sim_events_tick(sd)) | |
146 | sim_events_process(sd); | |
147 | } | |
148 | } |