/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (hide 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 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 38 * $Id: cpu_dyntrans.c,v 1.145 2007/04/10 17:26:20 debug Exp $
29 dpavlin 14 *
30     * Common dyntrans routines. Included from cpu_*.c.
31     */
32    
33    
34 dpavlin 28 #ifndef STATIC_STUFF
35     #define STATIC_STUFF
36     /*
37     * gather_statistics():
38     */
39 dpavlin 18 static void gather_statistics(struct cpu *cpu)
40     {
41 dpavlin 28 char ch, buf[60];
42 dpavlin 22 struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
43 dpavlin 28 int i = 0;
44 dpavlin 18 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 dpavlin 32 if (cpu->machine->statistics_file == NULL) {
49     fatal("statistics gathering with no filename set is"
50     " meaningless\n");
51     return;
52     }
53    
54 dpavlin 28 buf[0] = '\0';
55 dpavlin 18
56 dpavlin 28 while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
57     if (i != 0)
58     strlcat(buf, " ", sizeof(buf));
59 dpavlin 18
60 dpavlin 28 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 dpavlin 18 }
104 dpavlin 28
105     fprintf(cpu->machine->statistics_file, "%s\n", buf);
106 dpavlin 18 }
107    
108 dpavlin 24
109 dpavlin 18 #define S gather_statistics(cpu)
110    
111 dpavlin 24
112 dpavlin 18 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
113 dpavlin 20 #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; \
114 dpavlin 22 cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0]; \
115 dpavlin 20 ic->f(cpu, ic);
116 dpavlin 18 #else
117 dpavlin 24
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 dpavlin 18 #endif
165 dpavlin 28 #endif /* STATIC STUFF */
166 dpavlin 18
167    
168 dpavlin 28
169     #ifdef DYNTRANS_RUN_INSTR
170 dpavlin 14 /*
171 dpavlin 28 * XXX_run_instr():
172 dpavlin 14 *
173     * Execute one or more instructions on a specific CPU, using dyntrans.
174 dpavlin 28 * (For dualmode archs, this function is included twice.)
175 dpavlin 14 *
176     * Return value is the number of instructions executed during this call,
177     * 0 if no instructions were executed.
178     */
179 dpavlin 28 int DYNTRANS_RUN_INSTR(struct cpu *cpu)
180 dpavlin 14 {
181 dpavlin 28 MODE_uint_t cached_pc;
182     int low_pc, n_instrs;
183 dpavlin 24
184 dpavlin 28 /* Ugly... fix this some day. */
185     #ifdef DYNTRANS_DUALMODE_32
186 dpavlin 26 #ifdef MODE32
187 dpavlin 28 DYNTRANS_PC_TO_POINTERS32(cpu);
188 dpavlin 26 #else
189 dpavlin 28 DYNTRANS_PC_TO_POINTERS(cpu);
190 dpavlin 14 #endif
191 dpavlin 28 #else
192     DYNTRANS_PC_TO_POINTERS(cpu);
193 dpavlin 14 #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 dpavlin 24 *
201     * TODO: Turn this into a family-specific function somewhere...
202 dpavlin 14 */
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 dpavlin 24 #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 dpavlin 20 #ifdef DYNTRANS_PPC
231     if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
232 dpavlin 30 if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
233     ppc_exception(cpu, PPC_EXCEPTION_DEC);
234 dpavlin 20 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 dpavlin 32 #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 dpavlin 14
246     cached_pc = cpu->pc;
247    
248     cpu->n_translated_instrs = 0;
249    
250 dpavlin 18 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
251     cpu->cd.DYNTRANS_ARCH.cur_ic_page;
252    
253 dpavlin 24 if (single_step || cpu->machine->instruction_trace
254     || cpu->machine->register_dump) {
255 dpavlin 14 /*
256     * Single-step:
257     */
258 dpavlin 24 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 dpavlin 14 if (cpu->machine->instruction_trace) {
264 dpavlin 32 /* 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 dpavlin 14 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
269     sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
270 dpavlin 28 fatal("XXX_run_instr(): could not read "
271 dpavlin 14 "the instruction\n");
272 dpavlin 22 } else {
273 dpavlin 24 #ifdef DYNTRANS_DELAYSLOT
274 dpavlin 32 int len =
275     #endif
276     cpu_disassemble_instr(
277     cpu->machine, cpu, instr, 1, 0);
278     #ifdef DYNTRANS_DELAYSLOT
279 dpavlin 22 /* Show the instruction in the delay slot,
280     if any: */
281 dpavlin 24 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 dpavlin 32 + len, &instr[0],
289 dpavlin 24 sizeof(instr), MEM_READ,
290     CACHE_INSTRUCTION);
291     cpu->delay_slot = DELAYED;
292 dpavlin 32 cpu->pc += len;
293 dpavlin 24 cpu_disassemble_instr(cpu->machine,
294     cpu, instr, 1, 0);
295     cpu->delay_slot = saved_delayslot;
296 dpavlin 32 cpu->pc -= len;
297 dpavlin 24 }
298 dpavlin 22 #endif
299     }
300 dpavlin 14 }
301    
302 dpavlin 28 if (cpu->machine->statistics_enabled)
303 dpavlin 18 S;
304    
305 dpavlin 14 /* Execute just one instruction: */
306 dpavlin 24 I;
307    
308 dpavlin 14 n_instrs = 1;
309 dpavlin 24 } 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 dpavlin 30 if (n_instrs + cpu->n_translated_instrs >=
327 dpavlin 26 N_SAFE_DYNTRANS_LIMIT)
328 dpavlin 24 break;
329     }
330 dpavlin 28 } else if (cpu->machine->statistics_enabled) {
331 dpavlin 18 /* 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 dpavlin 30 if (n_instrs + cpu->n_translated_instrs >=
344 dpavlin 26 N_SAFE_DYNTRANS_LIMIT)
345 dpavlin 18 break;
346     }
347 dpavlin 14 } else {
348     /* Execute multiple instructions: */
349 dpavlin 34 n_instrs = 0;
350 dpavlin 14 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 dpavlin 34 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 dpavlin 14
367 dpavlin 34 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 dpavlin 14 break;
372     }
373     }
374    
375 dpavlin 20 n_instrs += cpu->n_translated_instrs;
376 dpavlin 14
377 dpavlin 20 /* Synchronize the program counter: */
378 dpavlin 14 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 dpavlin 22 } 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 dpavlin 14 }
398    
399 dpavlin 24 #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 dpavlin 32
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 dpavlin 34 INTERRUPT_ASSERT(
416     cpu->cd.mips.irq_compare);
417 dpavlin 32 } else
418     #endif
419     {
420     if (diff1 > 0 && diff2 <= 0)
421 dpavlin 34 INTERRUPT_ASSERT(
422     cpu->cd.mips.irq_compare);
423 dpavlin 32 }
424     }
425 dpavlin 24 }
426     #endif
427 dpavlin 20 #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 dpavlin 22 if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
433     && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
434 dpavlin 20 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 dpavlin 14 }
445 dpavlin 28 #endif /* DYNTRANS_RUN_INSTR */
446 dpavlin 14
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 dpavlin 24 #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
464 dpavlin 14 6
465     #else
466     #ifdef DYNTRANS_SH
467 dpavlin 32 8 /* Both for 32-bit and 64-bit SuperH */
468 dpavlin 14 #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 dpavlin 38 int64_t d = cpu->cd.DYNTRANS_ARCH.
492 dpavlin 14 #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 dpavlin 32 r[4 /* NetBSD seems to use 4? But 2 seems
514     to be used by other code? TODO */
515 dpavlin 14 #endif
516     #ifdef DYNTRANS_SPARC
517 dpavlin 32 r[8 /* o0..o5 */
518 dpavlin 14 #endif
519     + x];
520 dpavlin 38
521 dpavlin 14 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 dpavlin 24 fatal("0x%"PRIx32, (uint32_t)d);
533 dpavlin 14 else
534 dpavlin 24 fatal("0x%"PRIx64, (uint64_t)d);
535 dpavlin 14 }
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 dpavlin 26 /* Copy the entire template page first: */
564     memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
565     struct DYNTRANS_TC_PHYSPAGE));
566 dpavlin 14
567 dpavlin 26 ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
568 dpavlin 14
569     cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
570 dpavlin 18
571     cpu->translation_cache_cur_ofs --;
572 dpavlin 26 cpu->translation_cache_cur_ofs |= 127;
573 dpavlin 18 cpu->translation_cache_cur_ofs ++;
574 dpavlin 14 }
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 dpavlin 24 cached_pc = cpu->pc, physaddr = 0;
593 dpavlin 14 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 dpavlin 24 int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
600 dpavlin 14 #else
601 dpavlin 24 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 dpavlin 14 #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 dpavlin 24 if (l3->host_load[x3] != NULL) {
628     physaddr = l3->phys_addr[x3];
629 dpavlin 14 ok = 1;
630     }
631     #endif
632    
633     if (!ok) {
634     uint64_t paddr;
635 dpavlin 26 if (cpu->translate_v2p != NULL) {
636 dpavlin 30 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 dpavlin 26 ok = cpu->translate_v2p(
643 dpavlin 30 cpu, vaddr, &paddr, FLAG_INSTR);
644 dpavlin 26 } else {
645 dpavlin 14 paddr = cached_pc;
646     ok = 1;
647     }
648     if (!ok) {
649 dpavlin 28 /*
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 dpavlin 24 /* 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 dpavlin 20
659 dpavlin 28 /* If there was an exception, the PC has changed.
660     Update cached_pc: */
661     cached_pc = cpu->pc;
662 dpavlin 20
663 dpavlin 28 #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 dpavlin 34 x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
672     & mask2;
673     x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
674     - DYNTRANS_L3N)) & mask3;
675 dpavlin 28 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 dpavlin 20 /* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
689     "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
690 dpavlin 24 fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
691 dpavlin 20
692 dpavlin 14 if (!ok) {
693     fatal("FATAL: could not find physical"
694     " address of the exception handler?");
695     exit(1);
696     }
697     }
698 dpavlin 24
699 dpavlin 14 physaddr = paddr;
700     }
701    
702 dpavlin 28 physaddr &= ~(DYNTRANS_PAGESIZE - 1);
703    
704 dpavlin 18 #ifdef MODE32
705     if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
706 dpavlin 24 #else
707     if (l3->host_load[x3] == NULL) {
708     #endif
709 dpavlin 28 int q = DYNTRANS_PAGESIZE - 1;
710 dpavlin 18 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 dpavlin 28 host_page, 0, physaddr);
715 dpavlin 18 }
716     }
717    
718 dpavlin 34 if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) {
719 dpavlin 26 #ifdef UNSTABLE_DEVEL
720     fatal("[ dyntrans: resetting the translation cache ]\n");
721     #endif
722 dpavlin 14 cpu_create_or_reset_tc(cpu);
723 dpavlin 18 }
724 dpavlin 14
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 dpavlin 26
737 dpavlin 14 /* If we found the page in the cache, then we're done: */
738 dpavlin 26 if (ppp->physaddr == physaddr)
739 dpavlin 14 break;
740 dpavlin 26
741 dpavlin 14 /* Try the next page in the chain: */
742     physpage_ofs = ppp->next_ofs;
743     }
744    
745 dpavlin 38 /*
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 dpavlin 14
753 dpavlin 24 /* fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
754     "index %i\n", (long long)pagenr, (uint64_t)physaddr,
755 dpavlin 14 (int)table_index); */
756 dpavlin 38
757     previous_first_page_in_chain = *physpage_entryp;
758    
759     /* Insert the new page first in the chain: */
760 dpavlin 14 *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 dpavlin 38
769     /* Point to the other pages in the same chain: */
770     ppp->next_ofs = previous_first_page_in_chain;
771 dpavlin 14 }
772    
773 dpavlin 38 /* Here, ppp points to a valid physical page struct. */
774    
775 dpavlin 14 #ifdef MODE32
776     if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
777     cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
778 dpavlin 24 #else
779     if (l3->host_load[x3] != NULL)
780     l3->phys_page[x3] = ppp;
781 dpavlin 14 #endif
782    
783 dpavlin 28 /*
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 dpavlin 14
793     cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
794 dpavlin 18
795 dpavlin 14 cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
796     DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
797    
798 dpavlin 24 /* 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 dpavlin 14 }
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 dpavlin 22 cached_pc = cpu->pc;
825 dpavlin 14 struct DYNTRANS_TC_PHYSPAGE *ppp;
826    
827     #ifdef MODE32
828     int index;
829 dpavlin 18 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
830 dpavlin 14 ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
831     if (ppp != NULL)
832     goto have_it;
833     #else
834 dpavlin 24 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 dpavlin 14 #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 dpavlin 24 /* 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 dpavlin 14 }
864     #endif /* DYNTRANS_PC_TO_POINTERS_FUNC */
865    
866    
867    
868 dpavlin 26 #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 dpavlin 24 /*
886 dpavlin 26 * XXX_init_tables():
887 dpavlin 24 *
888 dpavlin 26 * 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 dpavlin 24 */
891 dpavlin 26 void DYNTRANS_INIT_TABLES(struct cpu *cpu)
892 dpavlin 24 {
893 dpavlin 26 #ifndef MODE32
894 dpavlin 24 struct DYNTRANS_L2_64_TABLE *dummy_l2;
895     struct DYNTRANS_L3_64_TABLE *dummy_l3;
896     int x1, x2;
897 dpavlin 26 #endif
898     int i;
899     struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
900     struct DYNTRANS_TC_PHYSPAGE));
901 dpavlin 24
902 dpavlin 26 if (ppp == NULL) {
903     fprintf(stderr, "out of memory\n");
904     exit(1);
905     }
906    
907     ppp->next_ofs = 0;
908 dpavlin 28 ppp->translations = 0;
909 dpavlin 26 /* 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 dpavlin 24 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 dpavlin 26 #endif
962 dpavlin 24 }
963 dpavlin 26 #endif /* DYNTRANS_INIT_TABLES */
964 dpavlin 24
965    
966    
967 dpavlin 14 #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 dpavlin 18 static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
978 dpavlin 14 #ifdef MODE32
979     uint32_t
980     #else
981     uint64_t
982     #endif
983     vaddr_page, int flags)
984     {
985     #ifdef MODE32
986 dpavlin 18 uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
987 dpavlin 14
988 dpavlin 18 #ifdef DYNTRANS_ARM
989 dpavlin 20 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
990 dpavlin 18 #endif
991    
992 dpavlin 14 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 dpavlin 24 int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
998 dpavlin 14 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 dpavlin 24 if (tlbi > 0)
1003     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1004 dpavlin 18 cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1005 dpavlin 14 }
1006     #else
1007 dpavlin 24 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 dpavlin 14
1014 dpavlin 24 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 dpavlin 14
1018 dpavlin 24 l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1019     if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1020     return;
1021 dpavlin 14
1022 dpavlin 24 l3 = l2->l3[x2];
1023     if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1024     return;
1025    
1026 dpavlin 14 if (flags & JUST_MARK_AS_NON_WRITABLE) {
1027 dpavlin 24 l3->host_store[x3] = NULL;
1028 dpavlin 14 return;
1029     }
1030 dpavlin 28
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 dpavlin 24 l3->host_load[x3] = NULL;
1076     l3->host_store[x3] = NULL;
1077     l3->phys_addr[x3] = 0;
1078     l3->phys_page[x3] = NULL;
1079 dpavlin 28 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 dpavlin 24 if (l3->refcount < 0) {
1087     fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1088 dpavlin 14 exit(1);
1089     }
1090 dpavlin 28
1091 dpavlin 24 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 dpavlin 28 #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 dpavlin 24 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 dpavlin 14 }
1120     #endif
1121     }
1122     #endif
1123    
1124    
1125 dpavlin 18 #ifdef DYNTRANS_INVALIDATE_TC
1126 dpavlin 14 /*
1127 dpavlin 18 * XXX_invalidate_translation_caches():
1128 dpavlin 14 *
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 dpavlin 22 * 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 dpavlin 14 * In the case when all translations are invalidated, paddr doesn't need
1140     * to be supplied.
1141     *
1142 dpavlin 18 * 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 dpavlin 14 */
1146 dpavlin 22 void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
1147 dpavlin 14 {
1148     int r;
1149     #ifdef MODE32
1150     uint32_t
1151     #else
1152     uint64_t
1153     #endif
1154 dpavlin 22 addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
1155 dpavlin 14
1156 dpavlin 20 /* fatal("invalidate(): "); */
1157    
1158 dpavlin 22 /* Quick case for _one_ virtual addresses: see note above. */
1159 dpavlin 18 if (flags & INVALIDATE_VADDR) {
1160 dpavlin 20 /* fatal("vaddr 0x%08x\n", (int)addr_page); */
1161 dpavlin 18 DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
1162     return;
1163     }
1164    
1165 dpavlin 22 /* 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 dpavlin 20 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 dpavlin 22 /* Invalidate a physical page: */
1196 dpavlin 20
1197 dpavlin 22 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 dpavlin 14 for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1203 dpavlin 22 if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
1204     == cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page) {
1205 dpavlin 14 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 dpavlin 18 #endif /* DYNTRANS_INVALIDATE_TC */
1218 dpavlin 14
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 dpavlin 18 #ifdef MODE32
1232 dpavlin 14 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 dpavlin 18 struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1247 dpavlin 14
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 dpavlin 34
1255     /* Return immediately if there is no code translation
1256     for this page. */
1257     if (physpage_ofs == 0)
1258     return;
1259    
1260 dpavlin 18 prev_ppp = ppp = NULL;
1261 dpavlin 14
1262     /* Traverse the physical page chain: */
1263     while (physpage_ofs != 0) {
1264 dpavlin 18 prev_ppp = ppp;
1265 dpavlin 14 ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1266     (cpu->translation_cache + physpage_ofs);
1267 dpavlin 26
1268 dpavlin 14 /* If we found the page in the cache,
1269     then we're done: */
1270     if (ppp->physaddr == addr)
1271     break;
1272 dpavlin 26
1273 dpavlin 14 /* Try the next page in the chain: */
1274     physpage_ofs = ppp->next_ofs;
1275     }
1276    
1277 dpavlin 34 /* 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 dpavlin 38 if (physpage_ofs == 0)
1280 dpavlin 34 return;
1281 dpavlin 18
1282 dpavlin 28 #if 0
1283 dpavlin 18 /*
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 dpavlin 14 if (ppp != NULL) {
1291 dpavlin 18 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 dpavlin 28 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 dpavlin 14 #ifdef DYNTRANS_DUALMODE_32
1316 dpavlin 28 cpu->is_32bit?
1317     instr32(to_be_translated) :
1318 dpavlin 14 #endif
1319 dpavlin 28 instr(to_be_translated);
1320     }
1321    
1322     x >>= 1;
1323     }
1324    
1325     ppp->translations = 0;
1326 dpavlin 14 }
1327 dpavlin 18 #endif
1328 dpavlin 14 }
1329    
1330 dpavlin 26 /* Invalidate entries in the VPH table: */
1331     for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
1332 dpavlin 14 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 dpavlin 18 uint32_t index =
1343     DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1344 dpavlin 14 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1345     #else
1346 dpavlin 24 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 dpavlin 14
1353 dpavlin 24 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 dpavlin 14 #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 dpavlin 32 int found, r, useraccess = 0;
1380 dpavlin 14
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 dpavlin 24 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 dpavlin 28
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 dpavlin 24 (uint64_t)paddr_page); */
1399 dpavlin 14 #endif
1400    
1401 dpavlin 26 assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1402     assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1403    
1404 dpavlin 18 if (writeflag & MEMORY_USER_ACCESS) {
1405     writeflag &= ~MEMORY_USER_ACCESS;
1406     useraccess = 1;
1407     }
1408    
1409 dpavlin 14 /* Scan the current TLB entries: */
1410 dpavlin 18
1411     #ifdef MODE32
1412 dpavlin 20 /*
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 dpavlin 18 DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1422 dpavlin 30 #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 dpavlin 20 if (found < 0) {
1441 dpavlin 32 /* Create the new TLB entry, overwriting a "random" entry: */
1442 dpavlin 20 static unsigned int x = 0;
1443 dpavlin 32 r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1444 dpavlin 14
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 dpavlin 20 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1457     writeflag & MEM_WRITE;
1458 dpavlin 14
1459     /* Add the new translation to the table: */
1460     #ifdef MODE32
1461 dpavlin 18 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1462 dpavlin 14 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 dpavlin 18 cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1468     #ifdef DYNTRANS_ARM
1469     if (useraccess)
1470 dpavlin 20 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1471     |= 1 << (index & 31);
1472 dpavlin 18 #endif
1473 dpavlin 24 #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 dpavlin 28 l2->refcount = 0;
1485 dpavlin 24 for (i=0; i<(1 << DYNTRANS_L2N); i++)
1486     l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1487     l3_64_dummy;
1488     }
1489 dpavlin 28 if (l2->refcount != 0) {
1490     fatal("Huh? l2 Refcount problem.\n");
1491     exit(1);
1492     }
1493 dpavlin 24 }
1494 dpavlin 28 if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1495     fatal("INTERNAL ERROR L2 reuse\n");
1496     exit(1);
1497     }
1498 dpavlin 24 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 dpavlin 28 if (l3->refcount != 0) {
1509     fatal("Huh? l3 Refcount problem.\n");
1510     exit(1);
1511     }
1512 dpavlin 24 l2->refcount ++;
1513     }
1514 dpavlin 28 if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1515     fatal("INTERNAL ERROR L3 reuse\n");
1516     exit(1);
1517     }
1518    
1519 dpavlin 24 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 dpavlin 28
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 dpavlin 24 #endif /* !MODE32 */
1550 dpavlin 14 } 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 dpavlin 20 * Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1556 dpavlin 14 */
1557 dpavlin 18 r = found;
1558 dpavlin 20 if (writeflag & MEM_WRITE)
1559 dpavlin 14 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1560 dpavlin 20 if (writeflag & MEM_DOWNGRADE)
1561 dpavlin 14 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
1562     #ifdef MODE32
1563 dpavlin 18 index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1564 dpavlin 14 cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1565 dpavlin 18 #ifdef DYNTRANS_ARM
1566 dpavlin 20 cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1567 dpavlin 18 if (useraccess)
1568 dpavlin 20 cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1569     |= 1 << (index & 31);
1570 dpavlin 18 #endif
1571 dpavlin 14 if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1572 dpavlin 20 if (writeflag & MEM_WRITE)
1573 dpavlin 14 cpu->cd.DYNTRANS_ARCH.host_store[index] =
1574     host_page;
1575 dpavlin 20 if (writeflag & MEM_DOWNGRADE)
1576 dpavlin 14 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 dpavlin 24 #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 dpavlin 28 printf("HOST LOAD 2 set to %p\n", host_page);
1599 dpavlin 24 l3->host_load[x3] = host_page;
1600     l3->host_store[x3] = writeflag? host_page : NULL;
1601     l3->phys_addr[x3] = paddr_page;
1602     }
1603 dpavlin 28
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 dpavlin 24 #endif /* !MODE32 */
1631 dpavlin 14 }
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 dpavlin 24 MODE_uint_t curpc = cpu->pc;
1645 dpavlin 14 int i;
1646     for (i=0; i<cpu->machine->n_breakpoints; i++)
1647 dpavlin 24 if (curpc == (MODE_uint_t)
1648 dpavlin 14 cpu->machine->breakpoint_addr[i]) {
1649     if (!cpu->machine->instruction_trace) {
1650     int old_quiet_mode = quiet_mode;
1651     quiet_mode = 0;
1652 dpavlin 24 DISASSEMBLE(cpu, ib, 1, 0);
1653 dpavlin 14 quiet_mode = old_quiet_mode;
1654     }
1655 dpavlin 24 fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1656 dpavlin 14 "instruction has not yet executed.)\n",
1657 dpavlin 24 (uint64_t)cpu->pc);
1658 dpavlin 22 #ifdef DYNTRANS_DELAYSLOT
1659 dpavlin 24 if (cpu->delay_slot != NOT_DELAYED)
1660 dpavlin 22 fatal("ERROR! Breakpoint in a delay"
1661     " slot! Not yet supported.\n");
1662     #endif
1663 dpavlin 14 single_step_breakpoint = 1;
1664 dpavlin 26 single_step = ENTER_SINGLE_STEPPING;
1665 dpavlin 14 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 dpavlin 28 * 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 dpavlin 14 */
1679 dpavlin 28
1680 dpavlin 24 /* Make sure cur_physpage is in synch: */
1681     cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1682     cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1683 dpavlin 28
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 dpavlin 18 }
1692 dpavlin 14
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 dpavlin 24 * instruction combination. For architectures with delay slots,
1699     * we also ignore combinations if the delay slot is across a page
1700     * boundary.
1701 dpavlin 14 */
1702 dpavlin 24 if (!single_step && !cpu->machine->instruction_trace
1703     #ifdef DYNTRANS_DELAYSLOT
1704     && !in_crosspage_delayslot
1705     #endif
1706 dpavlin 30 && 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 dpavlin 18 }
1711 dpavlin 14
1712 dpavlin 24 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 dpavlin 14 /* ... and finally execute the translated instruction: */
1729 dpavlin 24 if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1730     #ifdef DYNTRANS_DELAYSLOT
1731     || in_crosspage_delayslot
1732     #endif
1733     ) {
1734 dpavlin 14 /*
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 dpavlin 24 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1741     cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1742     #endif
1743 dpavlin 14 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 dpavlin 24 #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 dpavlin 14 ic->f(cpu, ic);
1765 dpavlin 24 }
1766 dpavlin 14
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 dpavlin 24 fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1780 dpavlin 14 #else
1781 dpavlin 24 fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1782 dpavlin 14 #endif
1783     else {
1784     fatal(":\n");
1785 dpavlin 24 DISASSEMBLE(cpu, ib, 1, 0);
1786 dpavlin 14 }
1787    
1788     cpu->running = 0;
1789 dpavlin 30
1790     /* Note: Single-stepping can jump here. */
1791 dpavlin 14 stop_running_translated:
1792 dpavlin 30
1793 dpavlin 14 debugger_n_steps_left_before_interaction = 0;
1794 dpavlin 30
1795 dpavlin 14 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 dpavlin 30
1801 dpavlin 14 #endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */
1802    

  ViewVC Help
Powered by ViewVC 1.1.26