/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 49688 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 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