/[gxemul]/trunk/src/cpus/cpu_dyntrans.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_dyntrans.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 48545 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 /*
2 * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $
29 *
30 * Common dyntrans routines. Included from cpu_*.c.
31 */
32
33
34 #ifdef DYNTRANS_CPU_RUN_INSTR
35 #if 1 /* IC statistics: */
36 static void gather_statistics(struct cpu *cpu)
37 {
38 struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
39 static long long n = 0;
40 static FILE *f = NULL;
41
42 n++;
43 if (n < 100000000)
44 return;
45
46 if (f == NULL) {
47 f = fopen("instruction_call_statistics.raw", "w");
48 if (f == NULL) {
49 fatal("Unable to open statistics file for output.\n");
50 exit(1);
51 }
52 }
53 fwrite(&ic->f, 1, sizeof(void *), f);
54 }
55 #else /* PC statistics: */
56 static void gather_statistics(struct cpu *cpu)
57 {
58 uint64_t a;
59 int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
60 cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
61 if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
62 return;
63
64 #if 0
65 /* Use the physical address: */
66 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
67 cpu->cd.DYNTRANS_ARCH.cur_ic_page;
68 a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
69 #else
70 /* Use the PC (virtual address): */
71 a = cpu->pc;
72 #endif
73
74 a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
75 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
76 a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77
78 /*
79 * TODO: Everything below this line should be cleaned up :-)
80 */
81 a &= 0x03ffffff;
82 {
83 static long long *array = NULL;
84 static char *array_16kpage_in_use = NULL;
85 static int n = 0;
86 a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;
87 if (array == NULL)
88 array = zeroed_alloc(sizeof(long long) * 16384*1024);
89 if (array_16kpage_in_use == NULL)
90 array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);
91 a &= (16384*1024-1);
92 array[a] ++;
93 array_16kpage_in_use[a / 16384] = 1;
94 n++;
95 if ((n & 0x3fffffff) == 0) {
96 FILE *f = fopen("statistics.out", "w");
97 int i, j;
98 printf("Saving statistics... "); fflush(stdout);
99 for (i=0; i<1024; i++)
100 if (array_16kpage_in_use[i]) {
101 for (j=0; j<16384; j++)
102 if (array[i*16384 + j] > 0)
103 fprintf(f, "%lli\t"
104 "0x%016"PRIx64"\n",
105 (uint64_t)array[i*16384+j],
106 (uint64_t)((i*16384+j) <<
107 DYNTRANS_INSTR_ALIGNMENT_SHIFT));
108 }
109 fclose(f);
110 printf("n=0x%08x\n", n);
111 }
112 }
113 }
114 #endif /* PC statistics */
115
116
117 #define S gather_statistics(cpu)
118
119
120 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
121 #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; \
122 cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0]; \
123 ic->f(cpu, ic);
124 #else
125
126 /* The normal instruction execution core: */
127 #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
128
129 /* For heavy debugging: */
130 /* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \
131 { \
132 int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
133 (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
134 sizeof(struct DYNTRANS_IC); \
135 printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n", \
136 cpu->cd.DYNTRANS_ARCH.cur_ic_page, \
137 ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
138 } \
139 ic->f(cpu, ic); */
140
141 /* static long long nr_of_I_calls = 0; */
142
143 /* Temporary hack for finding NULL bugs: */
144 /* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \
145 nr_of_I_calls ++; \
146 if (ic->f == NULL) { \
147 int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
148 (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
149 sizeof(struct DYNTRANS_IC); \
150 cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \
151 DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
152 cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\
153 printf("Crash at %016"PRIx64"\n", cpu->pc); \
154 printf("nr of I calls: %lli\n", nr_of_I_calls); \
155 printf("Next ic = %p\n", cpu->cd. \
156 DYNTRANS_ARCH.next_ic); \
157 printf("cur ic page = %p\n", cpu->cd. \
158 DYNTRANS_ARCH.cur_ic_page); \
159 cpu->running = 0; \
160 return 0; \
161 } \
162 ic->f(cpu, ic); */
163
164 /* Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs: */
165 /* #define I { int k; for (k=1; k<=31; k++) \
166 cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\
167 if (cpu->cd.mips.gpr[0] != 0) { \
168 fatal("NOOOOOO\n"); exit(1); \
169 } \
170 ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
171 */
172 #endif
173
174
175 /*
176 * XXX_cpu_run_instr():
177 *
178 * Execute one or more instructions on a specific CPU, using dyntrans.
179 *
180 * Return value is the number of instructions executed during this call,
181 * 0 if no instructions were executed.
182 */
183 int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)
184 {
185 /*
186 * TODO: Statistics stuff!
187 */
188 int show_opcode_statistics = 0;
189
190 #ifdef MODE32
191 uint32_t cached_pc;
192 #else
193 uint64_t cached_pc;
194 #endif
195 int low_pc, n_instrs;
196
197 #ifdef DYNTRANS_DUALMODE_32
198 if (cpu->is_32bit)
199 DYNTRANS_PC_TO_POINTERS32(cpu);
200 else
201 #endif
202 DYNTRANS_PC_TO_POINTERS(cpu);
203
204 /*
205 * Interrupt assertion? (This is _below_ the initial PC to pointer
206 * conversion; if the conversion caused an exception of some kind
207 * then interrupts are probably disabled, and the exception will get
208 * priority over device interrupts.)
209 *
210 * TODO: Turn this into a family-specific function somewhere...
211 */
212 #ifdef DYNTRANS_ARM
213 if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I))
214 arm_exception(cpu, ARM_EXCEPTION_IRQ);
215 #endif
216 #ifdef DYNTRANS_MIPS
217 {
218 int enabled, mask;
219 int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
220 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
221 /* R3000: */
222 enabled = status & MIPS_SR_INT_IE;
223 } else {
224 /* R4000 and others: */
225 enabled = (status & STATUS_IE)
226 && !(status & STATUS_EXL) && !(status & STATUS_ERL);
227 /* Special case for R5900/C790/TX79: */
228 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
229 !(status & R5900_STATUS_EIE))
230 enabled = 0;
231 }
232 mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]
233 & STATUS_IM_MASK;
234
235 if (enabled && mask)
236 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0);
237 }
238 #endif
239 #ifdef DYNTRANS_PPC
240 if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
241 ppc_exception(cpu, PPC_EXCEPTION_DEC);
242 cpu->cd.ppc.dec_intr_pending = 0;
243 }
244 if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
245 ppc_exception(cpu, PPC_EXCEPTION_EI);
246 #endif
247
248 cached_pc = cpu->pc;
249
250 cpu->n_translated_instrs = 0;
251 cpu->running_translated = 1;
252
253 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
254 cpu->cd.DYNTRANS_ARCH.cur_ic_page;
255
256 if (single_step || cpu->machine->instruction_trace
257 || cpu->machine->register_dump) {
258 /*
259 * Single-step:
260 */
261 struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
262 if (cpu->machine->register_dump) {
263 debug("\n");
264 cpu_register_dump(cpu->machine, cpu, 1, 0x1);
265 }
266 if (cpu->machine->instruction_trace) {
267 #ifdef DYNTRANS_X86
268 unsigned char instr[17];
269 cpu->cd.x86.cursegment = X86_S_CS;
270 cpu->cd.x86.seg_override = 0;
271 #else
272 #ifdef DYNTRANS_M68K
273 unsigned char instr[16]; /* TODO: 16? */
274 #else
275 unsigned char instr[4]; /* General case... */
276 #endif
277 #endif
278
279 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
280 sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
281 fatal("XXX_cpu_run_instr(): could not read "
282 "the instruction\n");
283 } else {
284 cpu_disassemble_instr(cpu->machine, cpu,
285 instr, 1, 0);
286 #ifdef DYNTRANS_DELAYSLOT
287 /* Show the instruction in the delay slot,
288 if any: */
289 if (cpu->instruction_has_delayslot == NULL)
290 fatal("WARNING: ihd func not yet"
291 " implemented?\n");
292 else if (cpu->instruction_has_delayslot(cpu,
293 instr)) {
294 int saved_delayslot = cpu->delay_slot;
295 cpu->memory_rw(cpu, cpu->mem, cached_pc
296 + sizeof(instr), &instr[0],
297 sizeof(instr), MEM_READ,
298 CACHE_INSTRUCTION);
299 cpu->delay_slot = DELAYED;
300 cpu->pc += sizeof(instr);
301 cpu_disassemble_instr(cpu->machine,
302 cpu, instr, 1, 0);
303 cpu->delay_slot = saved_delayslot;
304 cpu->pc -= sizeof(instr);
305 }
306 #endif
307 }
308 }
309
310 /* When single-stepping, multiple instruction calls cannot
311 be combined into one. This clears all translations: */
312 if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {
313 int i;
314 for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
315 cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =
316 #ifdef DYNTRANS_DUALMODE_32
317 cpu->is_32bit?
318 instr32(to_be_translated) :
319 #endif
320 instr(to_be_translated);
321 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
322 cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].
323 arg[0] = 0;
324 #endif
325 }
326 fatal("[ Note: The translation of physical page 0x%"
327 PRIx64" contained combinations of instructions; "
328 "these are now flushed because we are single-"
329 "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.
330 cur_physpage->physaddr);
331 cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=
332 ~(COMBINATIONS | TRANSLATIONS);
333 }
334
335 if (show_opcode_statistics)
336 S;
337
338 /* Execute just one instruction: */
339 I;
340
341 n_instrs = 1;
342 } else if (cpu->machine->cycle_accurate) {
343 /* Executing multiple instructions, and call devices'
344 tick functions: */
345 n_instrs = 0;
346 for (;;) {
347 struct DYNTRANS_IC *ic;
348 /* TODO: continue here */
349 int64_t cycles = cpu->cd.avr.extra_cycles;
350 I;
351 n_instrs += 1;
352 cycles = cpu->cd.avr.extra_cycles - cycles + 1;
353 /* The instruction took 'cycles' cycles. */
354 /* printf("A\n"); */
355 while (cycles-- > 0)
356 cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);
357 /* printf("B\n"); */
358
359 if (!cpu->running_translated ||
360 n_instrs + cpu->n_translated_instrs >=
361 N_SAFE_DYNTRANS_LIMIT)
362 break;
363 }
364 } else if (show_opcode_statistics) {
365 /* Gather statistics while executing multiple instructions: */
366 n_instrs = 0;
367 for (;;) {
368 struct DYNTRANS_IC *ic;
369
370 S; I; S; I; S; I; S; I; S; I; S; I;
371 S; I; S; I; S; I; S; I; S; I; S; I;
372 S; I; S; I; S; I; S; I; S; I; S; I;
373 S; I; S; I; S; I; S; I; S; I; S; I;
374
375 n_instrs += 24;
376
377 if (!cpu->running_translated ||
378 n_instrs + cpu->n_translated_instrs >=
379 N_SAFE_DYNTRANS_LIMIT)
380 break;
381 }
382 } else {
383 /* Execute multiple instructions: */
384 n_instrs = 0;
385 for (;;) {
386 struct DYNTRANS_IC *ic;
387
388 I; I; I; I; I; I; I; I; I; I;
389 I; I; I; I; I; I; I; I; I; I;
390 I; I; I; I; I; I; I; I; I; I;
391 I; I; I; I; I; I; I; I; I; I;
392 I; I; I; I; I; I; I; I; I; I;
393
394 I; I; I; I; I; I; I; I; I; I;
395
396 n_instrs += 60;
397
398 if (!cpu->running_translated ||
399 n_instrs + cpu->n_translated_instrs >=
400 N_SAFE_DYNTRANS_LIMIT)
401 break;
402 }
403 }
404
405 n_instrs += cpu->n_translated_instrs;
406
407 /* Synchronize the program counter: */
408 low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
409 cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
410 if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {
411 cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
412 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
413 cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);
414 } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {
415 /* Switch to next page: */
416 cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
417 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
418 cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
419 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
420 } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE + 1) {
421 /* Switch to next page and skip an instruction which was
422 already executed (in a delay slot): */
423 cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
424 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
425 cpu->pc += ((DYNTRANS_IC_ENTRIES_PER_PAGE + 1) <<
426 DYNTRANS_INSTR_ALIGNMENT_SHIFT);
427 }
428
429 #ifdef DYNTRANS_MIPS
430 /* Update the count register (on everything except EXC3K): */
431 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
432 uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
433 int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
434 int32_t diff2;
435 cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
436 (int32_t) (old + n_instrs);
437 diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
438 cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
439 if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)
440 cpu_interrupt(cpu, 7);
441 }
442 #endif
443 #ifdef DYNTRANS_PPC
444 /* Update the Decrementer and Time base registers: */
445 {
446 uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
447 cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
448 if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
449 && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
450 cpu->cd.ppc.dec_intr_pending = 1;
451 old = cpu->cd.ppc.spr[SPR_TBL];
452 cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
453 if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)
454 cpu->cd.ppc.spr[SPR_TBU] ++;
455 }
456 #endif
457
458 /* Return the nr of instructions executed: */
459 return n_instrs;
460 }
461 #endif /* DYNTRANS_CPU_RUN_INSTR */
462
463
464
465 #ifdef DYNTRANS_FUNCTION_TRACE
466 /*
467 * XXX_cpu_functioncall_trace():
468 *
469 * Without this function, the main trace tree function prints something
470 * like <f()> or <0x1234()> on a function call. It is up to this
471 * function to print the arguments passed.
472 */
473 void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)
474 {
475 char strbuf[50];
476 char *symbol;
477 uint64_t ot;
478 int x, print_dots = 1, n_args_to_print =
479 #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
480 6
481 #else
482 #ifdef DYNTRANS_SH
483 8
484 #else
485 4 /* Default value for most archs */
486 #endif
487 #endif
488 ;
489
490 if (n_args >= 0 && n_args <= n_args_to_print) {
491 print_dots = 0;
492 n_args_to_print = n_args;
493 }
494
495 /*
496 * TODO: The type of each argument should be taken from the symbol
497 * table, in some way.
498 *
499 * The code here does a kind of "heuristic guess" regarding what the
500 * argument values might mean. Sometimes the output looks weird, but
501 * usually it looks good enough.
502 *
503 * Print ".." afterwards to show that there might be more arguments
504 * than were passed in register.
505 */
506 for (x=0; x<n_args_to_print; x++) {
507 int64_t d;
508 #ifdef DYNTRANS_X86
509 d = 0; /* TODO */
510 #else
511 /* Args in registers: */
512 d = cpu->cd.DYNTRANS_ARCH.
513 #ifdef DYNTRANS_ALPHA
514 r[ALPHA_A0
515 #endif
516 #ifdef DYNTRANS_ARM
517 r[0
518 #endif
519 #ifdef DYNTRANS_AVR
520 /* TODO: 24,25 = first register, but then
521 they go downwards, ie. 22,23 and so on */
522 r[24
523 #endif
524 #ifdef DYNTRANS_HPPA
525 r[0 /* TODO */
526 #endif
527 #ifdef DYNTRANS_I960
528 r[0 /* TODO */
529 #endif
530 #ifdef DYNTRANS_IA64
531 r[0 /* TODO */
532 #endif
533 #ifdef DYNTRANS_M68K
534 d[0 /* TODO */
535 #endif
536 #ifdef DYNTRANS_MIPS
537 gpr[MIPS_GPR_A0
538 #endif
539 #ifdef DYNTRANS_PPC
540 gpr[3
541 #endif
542 #ifdef DYNTRANS_SH
543 r[2
544 #endif
545 #ifdef DYNTRANS_SPARC
546 r[24
547 #endif
548 + x];
549 #endif
550 symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
551
552 if (d > -256 && d < 256)
553 fatal("%i", (int)d);
554 else if (memory_points_to_string(cpu, cpu->mem, d, 1))
555 fatal("\"%s\"", memory_conv_to_string(cpu,
556 cpu->mem, d, strbuf, sizeof(strbuf)));
557 else if (symbol != NULL && ot == 0)
558 fatal("&%s", symbol);
559 else {
560 if (cpu->is_32bit)
561 fatal("0x%"PRIx32, (uint32_t)d);
562 else
563 fatal("0x%"PRIx64, (uint64_t)d);
564 }
565
566 if (x < n_args_to_print - 1)
567 fatal(",");
568 }
569
570 if (print_dots)
571 fatal(",..");
572 }
573 #endif
574
575
576
577 #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
578 /*
579 * XXX_tc_allocate_default_page():
580 *
581 * Create a default page (with just pointers to instr(to_be_translated)
582 * at cpu->translation_cache_cur_ofs.
583 */
584 static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE(struct cpu *cpu,
585 uint64_t physaddr)
586 {
587 struct DYNTRANS_TC_PHYSPAGE *ppp;
588
589 ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
590 + cpu->translation_cache_cur_ofs);
591
592 /* Copy the entire template page first: */
593 memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
594 struct DYNTRANS_TC_PHYSPAGE));
595
596 ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
597
598 cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
599
600 cpu->translation_cache_cur_ofs --;
601 cpu->translation_cache_cur_ofs |= 127;
602 cpu->translation_cache_cur_ofs ++;
603 }
604 #endif /* DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE */
605
606
607
608 #ifdef DYNTRANS_PC_TO_POINTERS_FUNC
609 /*
610 * XXX_pc_to_pointers_generic():
611 *
612 * Generic case. See DYNTRANS_PC_TO_POINTERS_FUNC below.
613 */
614 void DYNTRANS_PC_TO_POINTERS_GENERIC(struct cpu *cpu)
615 {
616 #ifdef MODE32
617 uint32_t
618 #else
619 uint64_t
620 #endif
621 cached_pc = cpu->pc, physaddr = 0;
622 uint32_t physpage_ofs;
623 int ok, pagenr, table_index;
624 uint32_t *physpage_entryp;
625 struct DYNTRANS_TC_PHYSPAGE *ppp;
626
627 #ifdef MODE32
628 int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
629 #else
630 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
631 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
632 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
633 uint32_t x1, x2, x3;
634 struct DYNTRANS_L2_64_TABLE *l2;
635 struct DYNTRANS_L3_64_TABLE *l3;
636
637 x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
638 x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
639 x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
640 /* fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n",
641 (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3); */
642 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
643 /* fatal(" l2 = %p\n", l2); */
644 l3 = l2->l3[x2];
645 /* fatal(" l3 = %p\n", l3); */
646 #endif
647
648 /* Virtual to physical address translation: */
649 ok = 0;
650 #ifdef MODE32
651 if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
652 physaddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
653 ok = 1;
654 }
655 #else
656 if (l3->host_load[x3] != NULL) {
657 physaddr = l3->phys_addr[x3];
658 ok = 1;
659 }
660 #endif
661
662 if (!ok) {
663 uint64_t paddr;
664 if (cpu->translate_v2p != NULL) {
665 ok = cpu->translate_v2p(
666 cpu, cached_pc, &paddr, FLAG_INSTR);
667 } else {
668 paddr = cached_pc;
669 ok = 1;
670 }
671 if (!ok) {
672 /* fatal("TODO: instruction vaddr=>paddr translation "
673 "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
674 fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
675
676 ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
677 FLAG_INSTR);
678
679 /* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
680 "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
681 fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
682
683 if (!ok) {
684 fatal("FATAL: could not find physical"
685 " address of the exception handler?");
686 exit(1);
687 }
688 }
689
690 /* If there was an exception, the PC can have changed.
691 Update cached_pc: */
692 cached_pc = cpu->pc;
693
694 #ifdef MODE32
695 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
696 #else
697 x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
698 x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
699 x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
700 & mask3;
701 #endif
702
703 physaddr = paddr;
704 }
705
706 #ifdef MODE32
707 if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
708 #else
709 if (l3->host_load[x3] == NULL) {
710 #endif
711 unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
712 physaddr, MEM_READ);
713 if (host_page != NULL) {
714 int q = DYNTRANS_PAGESIZE - 1;
715 host_page += (physaddr &
716 ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
717 cpu->update_translation_table(cpu, cached_pc & ~q,
718 host_page, 0, physaddr & ~q);
719 #ifndef MODE32
720 /* Recalculate l2 and l3, since they might have
721 changed now: */
722 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
723 l3 = l2->l3[x2];
724 #endif
725 }
726 }
727
728 if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
729 #ifdef UNSTABLE_DEVEL
730 fatal("[ dyntrans: resetting the translation cache ]\n");
731 #endif
732 cpu_create_or_reset_tc(cpu);
733 }
734
735 physaddr &= ~(DYNTRANS_PAGESIZE - 1);
736
737 pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
738 table_index = PAGENR_TO_TABLE_INDEX(pagenr);
739
740 physpage_entryp = &(((uint32_t *)cpu->translation_cache)[table_index]);
741 physpage_ofs = *physpage_entryp;
742 ppp = NULL;
743
744 /* Traverse the physical page chain: */
745 while (physpage_ofs != 0) {
746 ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
747 + physpage_ofs);
748
749 /* If we found the page in the cache, then we're done: */
750 if (ppp->physaddr == physaddr)
751 break;
752
753 /* Try the next page in the chain: */
754 physpage_ofs = ppp->next_ofs;
755 }
756
757 /* If the offset is 0 (or ppp is NULL), then we need to create a
758 new "default" empty translation page. */
759
760 if (ppp == NULL) {
761 /* fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
762 "index %i\n", (long long)pagenr, (uint64_t)physaddr,
763 (int)table_index); */
764 *physpage_entryp = physpage_ofs =
765 cpu->translation_cache_cur_ofs;
766
767 /* Allocate a default page, with to_be_translated entries: */
768 DYNTRANS_TC_ALLOCATE(cpu, physaddr);
769
770 ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
771 + physpage_ofs);
772 }
773
774 #ifdef MODE32
775 if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
776 cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
777 #else
778 if (l3->host_load[x3] != NULL)
779 l3->phys_page[x3] = ppp;
780 #endif
781
782 #ifdef MODE32
783 /* Small optimization: only mark the physical page as non-writable
784 if it did not contain translations. (Because if it does contain
785 translations, it is already non-writable.) */
786 if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &
787 (1 << (pagenr & 31)))
788 #endif
789 cpu->invalidate_translation_caches(cpu, physaddr,
790 JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
791
792 cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
793
794 cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
795 DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
796
797 /* printf("cached_pc=0x%016"PRIx64" pagenr=%lli table_index=%lli, "
798 "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
799 pagenr, (long long)table_index, (uint64_t)physpage_ofs); */
800 }
801
802
803 /*
804 * XXX_pc_to_pointers():
805 *
806 * This function uses the current program counter (a virtual address) to
807 * find out which physical translation page to use, and then sets the current
808 * translation page pointers to that page.
809 *
810 * If there was no translation page for that physical page, then an empty
811 * one is created.
812 *
813 * NOTE: This is the quick lookup version. See
814 * DYNTRANS_PC_TO_POINTERS_GENERIC above for the generic case.
815 */
816 void DYNTRANS_PC_TO_POINTERS_FUNC(struct cpu *cpu)
817 {
818 #ifdef MODE32
819 uint32_t
820 #else
821 uint64_t
822 #endif
823 cached_pc = cpu->pc;
824 struct DYNTRANS_TC_PHYSPAGE *ppp;
825
826 #ifdef MODE32
827 int index;
828 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
829 ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
830 if (ppp != NULL)
831 goto have_it;
832 #else
833 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
834 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
835 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
836 uint32_t x1, x2, x3;
837 struct DYNTRANS_L2_64_TABLE *l2;
838 struct DYNTRANS_L3_64_TABLE *l3;
839
840 x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
841 x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
842 x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
843 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
844 l3 = l2->l3[x2];
845 ppp = l3->phys_page[x3];
846 if (ppp != NULL)
847 goto have_it;
848 #endif
849
850 DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
851 return;
852
853 /* Quick return path: */
854 have_it:
855 cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
856 cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
857 DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
858
859 /* printf("cached_pc=0x%016"PRIx64" pagenr=%lli table_index=%lli, "
860 "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
861 pagenr, (long long)table_index, (uint64_t)physpage_ofs); */
862 }
863 #endif /* DYNTRANS_PC_TO_POINTERS_FUNC */
864
865
866
867 #ifdef DYNTRANS_INIT_TABLES
868
869 /* forward declaration of to_be_translated and end_of_page: */
870 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
871 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
872 #ifdef DYNTRANS_DUALMODE_32
873 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
874 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
875 #endif
876
877 #ifdef DYNTRANS_DELAYSLOT
878 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
879 #ifdef DYNTRANS_DUALMODE_32
880 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
881 #endif
882 #endif
883
884 /*
885 * XXX_init_tables():
886 *
887 * Initializes the default translation page (for newly allocated pages), and
888 * for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
889 */
890 void DYNTRANS_INIT_TABLES(struct cpu *cpu)
891 {
892 #ifndef MODE32
893 struct DYNTRANS_L2_64_TABLE *dummy_l2;
894 struct DYNTRANS_L3_64_TABLE *dummy_l3;
895 int x1, x2;
896 #endif
897 int i;
898 struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
899 struct DYNTRANS_TC_PHYSPAGE));
900
901 if (ppp == NULL) {
902 fprintf(stderr, "out of memory\n");
903 exit(1);
904 }
905
906 ppp->next_ofs = 0;
907 /* ppp->physaddr is filled in by the page allocator */
908
909 for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
910 ppp->ics[i].f =
911 #ifdef DYNTRANS_DUALMODE_32
912 cpu->is_32bit? instr32(to_be_translated) :
913 #endif
914 instr(to_be_translated);
915 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
916 ppp->ics[i].arg[0] = 0;
917 #endif
918 }
919
920 /* End-of-page: */
921 ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
922 #ifdef DYNTRANS_DUALMODE_32
923 cpu->is_32bit? instr32(end_of_page) :
924 #endif
925 instr(end_of_page);
926
927 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
928 ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;
929 #endif
930
931 /* End-of-page-2, for delay-slot architectures: */
932 #ifdef DYNTRANS_DELAYSLOT
933 ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
934 #ifdef DYNTRANS_DUALMODE_32
935 cpu->is_32bit? instr32(end_of_page2) :
936 #endif
937 instr(end_of_page2);
938 #endif
939
940 cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
941
942
943 /* Prepare 64-bit virtual address translation tables: */
944 #ifndef MODE32
945 if (cpu->is_32bit)
946 return;
947
948 dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
949 dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
950
951 cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
952 cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
953
954 for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
955 cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
956
957 for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
958 dummy_l2->l3[x2] = dummy_l3;
959 #endif
960 }
961 #endif /* DYNTRANS_INIT_TABLES */
962
963
964
965 #ifdef DYNTRANS_INVAL_ENTRY
966 /*
967 * XXX_invalidate_tlb_entry():
968 *
969 * Invalidate one translation entry (based on virtual address).
970 *
971 * If the JUST_MARK_AS_NON_WRITABLE flag is set, then the translation entry
972 * is just downgraded to non-writable (ie the host store page is set to
973 * NULL). Otherwise, the entire translation is removed.
974 */
975 static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
976 #ifdef MODE32
977 uint32_t
978 #else
979 uint64_t
980 #endif
981 vaddr_page, int flags)
982 {
983 #ifdef MODE32
984 uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
985
986 #ifdef DYNTRANS_ARM
987 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
988 #endif
989
990 if (flags & JUST_MARK_AS_NON_WRITABLE) {
991 /* printf("JUST MARKING NON-W: vaddr 0x%08x\n",
992 (int)vaddr_page); */
993 cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
994 } else {
995 int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
996 cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
997 cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
998 cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
999 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1000 if (tlbi > 0)
1001 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1002 cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1003 }
1004 #else
1005 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1006 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1007 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1008 uint32_t x1, x2, x3;
1009 struct DYNTRANS_L2_64_TABLE *l2;
1010 struct DYNTRANS_L3_64_TABLE *l3;
1011
1012 x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1013 x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1014 x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))& mask3;
1015
1016 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1017 if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1018 return;
1019
1020 l3 = l2->l3[x2];
1021 if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1022 return;
1023
1024 if (flags & JUST_MARK_AS_NON_WRITABLE) {
1025 l3->host_store[x3] = NULL;
1026 return;
1027 }
1028 l3->host_load[x3] = NULL;
1029 l3->host_store[x3] = NULL;
1030 l3->phys_addr[x3] = 0;
1031 l3->phys_page[x3] = NULL;
1032 l3->refcount --;
1033 if (l3->refcount < 0) {
1034 fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1035 exit(1);
1036 }
1037 if (l3->refcount == 0) {
1038 l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1039 cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1040 l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1041
1042 l2->refcount --;
1043 if (l2->refcount < 0) {
1044 fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1045 exit(1);
1046 }
1047 if (l2->refcount == 0) {
1048 l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1049 cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1050 cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1051 cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1052 }
1053 }
1054 #endif
1055 }
1056 #endif
1057
1058
1059 #ifdef DYNTRANS_INVALIDATE_TC
1060 /*
1061 * XXX_invalidate_translation_caches():
1062 *
1063 * Invalidate all entries matching a specific physical address, a specific
1064 * virtual address, or ALL entries.
1065 *
1066 * flags should be one of
1067 * INVALIDATE_PADDR INVALIDATE_VADDR or INVALIDATE_ALL
1068 *
1069 * In addition, for INVALIDATE_ALL, INVALIDATE_VADDR_UPPER4 may be set and
1070 * bit 31..28 of addr are used to select the virtual addresses to invalidate.
1071 * (This is useful for PowerPC emulation, when segment registers are updated.)
1072 *
1073 * In the case when all translations are invalidated, paddr doesn't need
1074 * to be supplied.
1075 *
1076 * NOTE/TODO: When invalidating a virtual address, it is only cleared from
1077 * the quick translation array, not from the linear
1078 * vph_tlb_entry[] array. Hopefully this is enough anyway.
1079 */
1080 void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
1081 {
1082 int r;
1083 #ifdef MODE32
1084 uint32_t
1085 #else
1086 uint64_t
1087 #endif
1088 addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
1089
1090 /* fatal("invalidate(): "); */
1091
1092 /* Quick case for _one_ virtual addresses: see note above. */
1093 if (flags & INVALIDATE_VADDR) {
1094 /* fatal("vaddr 0x%08x\n", (int)addr_page); */
1095 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
1096 return;
1097 }
1098
1099 /* Invalidate everything: */
1100 #ifdef DYNTRANS_PPC
1101 if (flags & INVALIDATE_ALL && flags & INVALIDATE_VADDR_UPPER4) {
1102 /* fatal("all, upper4 (PowerPC segment)\n"); */
1103 for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1104 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
1105 (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page
1106 & 0xf0000000) == addr_page) {
1107 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
1108 DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1109 0);
1110 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1111 }
1112 }
1113 return;
1114 }
1115 #endif
1116 if (flags & INVALIDATE_ALL) {
1117 /* fatal("all\n"); */
1118 for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1119 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1120 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
1121 DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1122 0);
1123 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1124 }
1125 }
1126 return;
1127 }
1128
1129 /* Invalidate a physical page: */
1130
1131 if (!(flags & INVALIDATE_PADDR))
1132 fatal("HUH? Invalidate: Not vaddr, all, or paddr?\n");
1133
1134 /* fatal("addr 0x%08x\n", (int)addr_page); */
1135
1136 for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1137 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
1138 == cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page) {
1139 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
1140 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1141 flags);
1142 if (flags & JUST_MARK_AS_NON_WRITABLE)
1143 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1144 .writeflag = 0;
1145 else
1146 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1147 .valid = 0;
1148 }
1149 }
1150 }
1151 #endif /* DYNTRANS_INVALIDATE_TC */
1152
1153
1154
1155 #ifdef DYNTRANS_INVALIDATE_TC_CODE
1156 /*
1157 * XXX_invalidate_code_translation():
1158 *
1159 * Invalidate code translations for a specific physical address, a specific
1160 * virtual address, or for all entries in the cache.
1161 */
1162 void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)
1163 {
1164 int r;
1165 #ifdef MODE32
1166 uint32_t
1167 #else
1168 uint64_t
1169 #endif
1170 vaddr_page, paddr_page;
1171
1172 addr &= ~(DYNTRANS_PAGESIZE-1);
1173
1174 /* printf("DYNTRANS_INVALIDATE_TC_CODE addr=0x%08x flags=%i\n",
1175 (int)addr, flags); */
1176
1177 if (flags & INVALIDATE_PADDR) {
1178 int pagenr, table_index;
1179 uint32_t physpage_ofs, *physpage_entryp;
1180 struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1181
1182 pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
1183
1184 #ifdef MODE32
1185 /* If this page isn't marked as having any translations,
1186 then return immediately. */
1187 if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]
1188 & 1 << (pagenr & 31)))
1189 return;
1190 /* Remove the mark: */
1191 cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=
1192 ~ (1 << (pagenr & 31));
1193 #endif
1194
1195 table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1196
1197 physpage_entryp = &(((uint32_t *)cpu->
1198 translation_cache)[table_index]);
1199 physpage_ofs = *physpage_entryp;
1200 prev_ppp = ppp = NULL;
1201
1202 /* Traverse the physical page chain: */
1203 while (physpage_ofs != 0) {
1204 prev_ppp = ppp;
1205 ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1206 (cpu->translation_cache + physpage_ofs);
1207
1208 /* If we found the page in the cache,
1209 then we're done: */
1210 if (ppp->physaddr == addr)
1211 break;
1212
1213 /* Try the next page in the chain: */
1214 physpage_ofs = ppp->next_ofs;
1215 }
1216
1217 if (physpage_ofs == 0)
1218 ppp = NULL;
1219
1220 #if 1
1221 /*
1222 * "Bypass" the page, removing it from the code cache.
1223 *
1224 * NOTE/TODO: This gives _TERRIBLE_ performance with self-
1225 * modifying code, or when a single page is used for both
1226 * code and (writable) data.
1227 */
1228 if (ppp != NULL) {
1229 if (prev_ppp != NULL)
1230 prev_ppp->next_ofs = ppp->next_ofs;
1231 else
1232 *physpage_entryp = ppp->next_ofs;
1233 }
1234 #else
1235 /*
1236 * Instead of removing the page from the code cache, each
1237 * entry can be set to "to_be_translated". This is slow in
1238 * the general case, but in the case of self-modifying code,
1239 * it might be faster since we don't risk wasting cache
1240 * memory as quickly (which would force unnecessary Restarts).
1241 */
1242 if (ppp != NULL) {
1243 /* TODO: Is this faster than copying an entire
1244 template page? */
1245 int i;
1246 for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
1247 ppp->ics[i].f =
1248 #ifdef DYNTRANS_DUALMODE_32
1249 cpu->is_32bit? instr32(to_be_translated) :
1250 #endif
1251 instr(to_be_translated);
1252 }
1253 #endif
1254 }
1255
1256 /* Invalidate entries in the VPH table: */
1257 for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
1258 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1259 vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1260 .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
1261 paddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1262 .paddr_page & ~(DYNTRANS_PAGESIZE-1);
1263
1264 if (flags & INVALIDATE_ALL ||
1265 (flags & INVALIDATE_PADDR && paddr_page == addr) ||
1266 (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
1267 #ifdef MODE32
1268 uint32_t index =
1269 DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1270 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1271 /* Remove the mark: */
1272 index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);
1273 cpu->cd.DYNTRANS_ARCH.phystranslation[
1274 index >> 5] &= ~ (1 << (index & 31));
1275 #else
1276 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1277 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1278 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1279 uint32_t x1, x2, x3;
1280 struct DYNTRANS_L2_64_TABLE *l2;
1281 struct DYNTRANS_L3_64_TABLE *l3;
1282
1283 x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1284 x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1285 DYNTRANS_L2N)) & mask2;
1286 x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1287 DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1288 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1289 l3 = l2->l3[x2];
1290 l3->phys_page[x3] = NULL;
1291 #endif
1292 }
1293 }
1294 }
1295 }
1296 #endif /* DYNTRANS_INVALIDATE_TC_CODE */
1297
1298
1299
1300 #ifdef DYNTRANS_UPDATE_TRANSLATION_TABLE
1301 /*
1302 * XXX_update_translation_table():
1303 *
1304 * Update the virtual memory translation tables.
1305 */
1306 void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1307 unsigned char *host_page, int writeflag, uint64_t paddr_page)
1308 {
1309 #ifndef MODE32
1310 int64_t lowest, highest = -1;
1311 #endif
1312 int found, r, lowest_index, useraccess = 0;
1313
1314 #ifdef MODE32
1315 uint32_t index;
1316 vaddr_page &= 0xffffffffULL;
1317 paddr_page &= 0xffffffffULL;
1318 /* fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1319 " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1320 (int)paddr_page); */
1321 #else /* !MODE32 */
1322 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1323 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1324 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1325 uint32_t x1, x2, x3;
1326 struct DYNTRANS_L2_64_TABLE *l2;
1327 struct DYNTRANS_L3_64_TABLE *l3;
1328 /* fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"
1329 " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1330 (uint64_t)paddr_page); */
1331 #endif
1332
1333 assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1334 assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1335
1336 if (writeflag & MEMORY_USER_ACCESS) {
1337 writeflag &= ~MEMORY_USER_ACCESS;
1338 useraccess = 1;
1339 }
1340
1341 /* Scan the current TLB entries: */
1342 lowest_index = 0;
1343
1344 #ifdef MODE32
1345 /*
1346 * NOTE 1: vaddr_to_tlbindex is one more than the index, so that
1347 * 0 becomes -1, which means a miss.
1348 *
1349 * NOTE 2: When a miss occurs, instead of scanning the entire tlb
1350 * for the entry with the lowest time stamp, just choosing
1351 * one at random will work as well.
1352 */
1353 found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1354 DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1355 if (found < 0) {
1356 static unsigned int x = 0;
1357 lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1358 }
1359 #else
1360 lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1361 found = -1;
1362 for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1363 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1364 lowest = cpu->cd.DYNTRANS_ARCH.
1365 vph_tlb_entry[r].timestamp;
1366 lowest_index = r;
1367 }
1368 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)
1369 highest = cpu->cd.DYNTRANS_ARCH.
1370 vph_tlb_entry[r].timestamp;
1371 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
1372 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==
1373 vaddr_page) {
1374 found = r;
1375 break;
1376 }
1377 }
1378 #endif
1379
1380 if (found < 0) {
1381 /* Create the new TLB entry, overwriting the oldest one: */
1382 r = lowest_index;
1383 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1384 /* This one has to be invalidated first: */
1385 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
1386 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1387 0);
1388 }
1389
1390 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid = 1;
1391 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;
1392 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;
1393 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1394 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1395 writeflag & MEM_WRITE;
1396 #ifndef MODE32
1397 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1398 #endif
1399
1400 /* Add the new translation to the table: */
1401 #ifdef MODE32
1402 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1403 cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1404 cpu->cd.DYNTRANS_ARCH.host_store[index] =
1405 writeflag? host_page : NULL;
1406 cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1407 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1408 cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1409 #ifdef DYNTRANS_ARM
1410 if (useraccess)
1411 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1412 |= 1 << (index & 31);
1413 #endif
1414 #else /* !MODE32 */
1415 x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1416 x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1417 x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1418 & mask3;
1419 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1420 if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1421 if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1422 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1423 cpu->cd.DYNTRANS_ARCH.next_free_l2;
1424 cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1425 } else {
1426 int i;
1427 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1428 malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1429 for (i=0; i<(1 << DYNTRANS_L2N); i++)
1430 l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1431 l3_64_dummy;
1432 }
1433 }
1434 l3 = l2->l3[x2];
1435 if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1436 if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1437 l3 = l2->l3[x2] =
1438 cpu->cd.DYNTRANS_ARCH.next_free_l3;
1439 cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1440 } else {
1441 l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1442 struct DYNTRANS_L3_64_TABLE));
1443 }
1444 l2->refcount ++;
1445 }
1446 l3->host_load[x3] = host_page;
1447 l3->host_store[x3] = writeflag? host_page : NULL;
1448 l3->phys_addr[x3] = paddr_page;
1449 l3->phys_page[x3] = NULL;
1450 l3->vaddr_to_tlbindex[x3] = r + 1;
1451 l3->refcount ++;
1452 #endif /* !MODE32 */
1453 } else {
1454 /*
1455 * The translation was already in the TLB.
1456 * Writeflag = 0: Do nothing.
1457 * Writeflag = 1: Make sure the page is writable.
1458 * Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1459 */
1460 r = found;
1461 #ifndef MODE32
1462 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1463 #endif
1464 if (writeflag & MEM_WRITE)
1465 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1466 if (writeflag & MEM_DOWNGRADE)
1467 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
1468 #ifdef MODE32
1469 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1470 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1471 #ifdef DYNTRANS_ARM
1472 cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1473 if (useraccess)
1474 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1475 |= 1 << (index & 31);
1476 #endif
1477 if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1478 if (writeflag & MEM_WRITE)
1479 cpu->cd.DYNTRANS_ARCH.host_store[index] =
1480 host_page;
1481 if (writeflag & MEM_DOWNGRADE)
1482 cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1483 } else {
1484 /* Change the entire physical/host mapping: */
1485 cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1486 cpu->cd.DYNTRANS_ARCH.host_store[index] =
1487 writeflag? host_page : NULL;
1488 cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1489 }
1490 #else /* !MODE32 */
1491 x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1492 x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1493 x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1494 & mask3;
1495 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1496 l3 = l2->l3[x2];
1497 if (l3->phys_addr[x3] == paddr_page) {
1498 if (writeflag & MEM_WRITE)
1499 l3->host_store[x3] = host_page;
1500 if (writeflag & MEM_DOWNGRADE)
1501 l3->host_store[x3] = NULL;
1502 } else {
1503 /* Change the entire physical/host mapping: */
1504 l3->host_load[x3] = host_page;
1505 l3->host_store[x3] = writeflag? host_page : NULL;
1506 l3->phys_addr[x3] = paddr_page;
1507 }
1508 #endif /* !MODE32 */
1509 }
1510 }
1511 #endif /* DYNTRANS_UPDATE_TRANSLATION_TABLE */
1512
1513
1514 /*****************************************************************************/
1515
1516
1517 #ifdef DYNTRANS_TO_BE_TRANSLATED_HEAD
1518 /*
1519 * Check for breakpoints.
1520 */
1521 if (!single_step_breakpoint) {
1522 MODE_uint_t curpc = cpu->pc;
1523 int i;
1524 for (i=0; i<cpu->machine->n_breakpoints; i++)
1525 if (curpc == (MODE_uint_t)
1526 cpu->machine->breakpoint_addr[i]) {
1527 if (!cpu->machine->instruction_trace) {
1528 int old_quiet_mode = quiet_mode;
1529 quiet_mode = 0;
1530 DISASSEMBLE(cpu, ib, 1, 0);
1531 quiet_mode = old_quiet_mode;
1532 }
1533 fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1534 "instruction has not yet executed.)\n",
1535 (uint64_t)cpu->pc);
1536 #ifdef DYNTRANS_DELAYSLOT
1537 if (cpu->delay_slot != NOT_DELAYED)
1538 fatal("ERROR! Breakpoint in a delay"
1539 " slot! Not yet supported.\n");
1540 #endif
1541 single_step_breakpoint = 1;
1542 single_step = ENTER_SINGLE_STEPPING;
1543 goto stop_running_translated;
1544 }
1545 }
1546 #endif /* DYNTRANS_TO_BE_TRANSLATED_HEAD */
1547
1548
1549 /*****************************************************************************/
1550
1551
1552 #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1553 /*
1554 * If we end up here, then an instruction was translated.
1555 * Mark the page as containing a translation.
1556 *
1557 * (Special case for 32-bit mode: set the corresponding bit in the
1558 * phystranslation[] array.)
1559 */
1560 /* Make sure cur_physpage is in synch: */
1561 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1562 cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1563 #ifdef MODE32
1564 if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1565 uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);
1566 cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1567 (1 << (index & 31));
1568 }
1569 #endif
1570 cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;
1571
1572
1573 /*
1574 * Now it is time to check for combinations of instructions that can
1575 * be converted into a single function call.
1576 *
1577 * Note: Single-stepping or instruction tracing doesn't work with
1578 * instruction combination. For architectures with delay slots,
1579 * we also ignore combinations if the delay slot is across a page
1580 * boundary.
1581 */
1582 if (!single_step && !cpu->machine->instruction_trace
1583 #ifdef DYNTRANS_DELAYSLOT
1584 && !in_crosspage_delayslot
1585 #endif
1586 ) {
1587 if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1588 cpu->machine->speed_tricks)
1589 cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1590 addr & (DYNTRANS_PAGESIZE - 1));
1591 }
1592
1593 cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1594
1595 /* An additional check, to catch some bugs: */
1596 if (ic->f == (
1597 #ifdef DYNTRANS_DUALMODE_32
1598 cpu->is_32bit? instr32(to_be_translated) :
1599 #endif
1600 instr(to_be_translated))) {
1601 fatal("INTERNAL ERROR: ic->f not set!\n");
1602 goto bad;
1603 }
1604 if (ic->f == NULL) {
1605 fatal("INTERNAL ERROR: ic->f == NULL!\n");
1606 goto bad;
1607 }
1608
1609 /* ... and finally execute the translated instruction: */
1610 if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1611 #ifdef DYNTRANS_DELAYSLOT
1612 || in_crosspage_delayslot
1613 #endif
1614 ) {
1615 /*
1616 * Special case when single-stepping: Execute the translated
1617 * instruction, but then replace it with a "to be translated"
1618 * directly afterwards.
1619 */
1620 single_step_breakpoint = 0;
1621 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1622 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1623 #endif
1624 ic->f(cpu, ic);
1625 ic->f =
1626 #ifdef DYNTRANS_DUALMODE_32
1627 cpu->is_32bit? instr32(to_be_translated) :
1628 #endif
1629 instr(to_be_translated);
1630 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1631 ic->arg[0] = 0;
1632 #endif
1633 } else {
1634 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1635 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1636
1637 /* Additional check, for variable length ISAs: */
1638 if (ic->arg[0] == 0) {
1639 fatal("INTERNAL ERROR: instr len = 0!\n");
1640 goto bad;
1641 }
1642 #endif
1643
1644 /* Finally finally :-), execute the instruction: */
1645 ic->f(cpu, ic);
1646 }
1647
1648 return;
1649
1650
1651 bad: /*
1652 * Nothing was translated. (Unimplemented or illegal instruction.)
1653 */
1654
1655 quiet_mode = 0;
1656 fatal("to_be_translated(): TODO: unimplemented instruction");
1657
1658 if (cpu->machine->instruction_trace)
1659 #ifdef MODE32
1660 fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1661 #else
1662 fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1663 #endif
1664 else {
1665 fatal(":\n");
1666 DISASSEMBLE(cpu, ib, 1, 0);
1667 }
1668
1669 cpu->running = 0;
1670 cpu->dead = 1;
1671 stop_running_translated:
1672 debugger_n_steps_left_before_interaction = 0;
1673 cpu->running_translated = 0;
1674 ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1675 cpu->cd.DYNTRANS_ARCH.next_ic ++;
1676
1677 /* Execute the "nothing" instruction: */
1678 ic->f(cpu, ic);
1679 #endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */
1680

  ViewVC Help
Powered by ViewVC 1.1.26