/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 50822 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26