/[gxemul]/upstream/0.4.2/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 /upstream/0.4.2/src/cpus/cpu_dyntrans.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26