/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 31309 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

1 dpavlin 14 /*
2     * Copyright (C) 2005 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.19 2005/10/07 22:10:51 debug Exp $
29     *
30     * Common dyntrans routines. Included from cpu_*.c.
31     */
32    
33    
34     #ifdef DYNTRANS_CPU_RUN_INSTR
35     /*
36     * XXX_cpu_run_instr():
37     *
38     * Execute one or more instructions on a specific CPU, using dyntrans.
39     *
40     * Return value is the number of instructions executed during this call,
41     * 0 if no instructions were executed.
42     */
43     int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)
44     {
45     #ifdef MODE32
46     uint32_t cached_pc;
47     #else
48     uint64_t cached_pc;
49     #endif
50     int low_pc, n_instrs;
51    
52     #ifdef DYNTRANS_DUALMODE_32
53     if (cpu->is_32bit)
54     DYNTRANS_PC_TO_POINTERS32(cpu);
55     else
56     #endif
57     DYNTRANS_PC_TO_POINTERS(cpu);
58    
59     /*
60     * Interrupt assertion? (This is _below_ the initial PC to pointer
61     * conversion; if the conversion caused an exception of some kind
62     * then interrupts are probably disabled, and the exception will get
63     * priority over device interrupts.)
64     */
65     #ifdef DYNTRANS_ARM
66     if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I))
67     arm_exception(cpu, ARM_EXCEPTION_IRQ);
68     #endif
69    
70     cached_pc = cpu->pc;
71    
72     cpu->n_translated_instrs = 0;
73     cpu->running_translated = 1;
74    
75     if (single_step || cpu->machine->instruction_trace) {
76     /*
77     * Single-step:
78     */
79     struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic
80     #ifndef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
81     ++
82     #endif
83     ;
84     if (cpu->machine->instruction_trace) {
85     #ifdef DYNTRANS_X86
86     unsigned char instr[17];
87     cpu->cd.x86.cursegment = X86_S_CS;
88     cpu->cd.x86.seg_override = 0;
89     #else
90     #ifdef DYNTRANS_M68K
91     unsigned char instr[16]; /* TODO: 16? */
92     #else
93     unsigned char instr[4]; /* General case... */
94     #endif
95     #endif
96     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
97     sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
98     fatal("XXX_cpu_run_instr(): could not read "
99     "the instruction\n");
100     } else
101     cpu_disassemble_instr(cpu->machine, cpu,
102     instr, 1, 0, 0);
103     }
104    
105     /* When single-stepping, multiple instruction calls cannot
106     be combined into one. This clears all translations: */
107     if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {
108     int i;
109     for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
110     cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =
111     #ifdef DYNTRANS_DUALMODE_32
112     cpu->is_32bit?
113     instr32(to_be_translated) :
114     #endif
115     instr(to_be_translated);
116     fatal("[ Note: The translation of physical page 0x%llx"
117     " contained combinations of instructions; these "
118     "are now flushed because we are single-stepping."
119     " ]\n", (long long)cpu->cd.DYNTRANS_ARCH.
120     cur_physpage->physaddr);
121     cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=
122     ~(COMBINATIONS | TRANSLATIONS);
123     }
124    
125     /* Execute just one instruction: */
126     ic->f(cpu, ic);
127     n_instrs = 1;
128     } else {
129     /* Execute multiple instructions: */
130     n_instrs = 0;
131     for (;;) {
132     struct DYNTRANS_IC *ic;
133    
134     #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
135     #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic; ic->f(cpu, ic);
136     #else
137     #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
138     #endif
139    
140     I; I; I; I; I; I; I; I; I; I;
141     I; I; I; I; I; I; I; I; I; I;
142     I; I; I; I; I; I; I; I; I; I;
143     I; I; I; I; I; I; I; I; I; I;
144     I; I; I; I; I; I; I; I; I; I;
145    
146     I; I; I; I; I; I; I; I; I; I;
147     I; I; I; I; I; I; I; I; I; I;
148     I; I; I; I; I; I; I; I; I; I;
149     I; I; I; I; I; I; I; I; I; I;
150     I; I; I; I; I; I; I; I; I; I;
151    
152     I; I; I; I; I; I; I; I; I; I;
153     I; I; I; I; I; I; I; I; I; I;
154    
155     n_instrs += 120;
156    
157     if (!cpu->running_translated ||
158     n_instrs + cpu->n_translated_instrs >= 16384)
159     break;
160     }
161     }
162    
163    
164     /*
165     * Update the program counter and return the correct number of
166     * executed instructions:
167     */
168     low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
169     cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
170    
171     if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {
172     #ifdef DYNTRANS_ARM
173     cpu->cd.arm.r[ARM_PC] &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1)<<2);
174     cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
175     cpu->pc = cpu->cd.arm.r[ARM_PC];
176     #else
177     cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
178     DYNTRANS_INSTR_ALIGNMENT_SHIFT);
179     cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);
180     #endif
181     } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {
182     /* Switch to next page: */
183     #ifdef DYNTRANS_ARM
184     cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
185     cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE << 2);
186     cpu->pc = cpu->cd.arm.r[ARM_PC];
187     #else
188     cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
189     DYNTRANS_INSTR_ALIGNMENT_SHIFT);
190     cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
191     DYNTRANS_INSTR_ALIGNMENT_SHIFT);
192     #endif
193     } else {
194     /* debug("debug: Outside a page (This is actually ok)\n"); */
195     }
196    
197     return n_instrs + cpu->n_translated_instrs;
198     }
199     #endif /* DYNTRANS_CPU_RUN_INSTR */
200    
201    
202    
203     #ifdef DYNTRANS_FUNCTION_TRACE
204     /*
205     * XXX_cpu_functioncall_trace():
206     *
207     * Without this function, the main trace tree function prints something
208     * like <f()> or <0x1234()> on a function call. It is up to this
209     * function to print the arguments passed.
210     */
211     void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)
212     {
213     char strbuf[50];
214     char *symbol;
215     uint64_t ot;
216     int x, print_dots = 1, n_args_to_print =
217     #ifdef DYNTRANS_ALPHA
218     6
219     #else
220     #ifdef DYNTRANS_SH
221     8
222     #else
223     4 /* Default value for most archs */
224     #endif
225     #endif
226     ;
227    
228     if (n_args >= 0 && n_args <= n_args_to_print) {
229     print_dots = 0;
230     n_args_to_print = n_args;
231     }
232    
233     /*
234     * TODO: The type of each argument should be taken from the symbol
235     * table, in some way.
236     *
237     * The code here does a kind of "heuristic guess" regarding what the
238     * argument values might mean. Sometimes the output looks weird, but
239     * usually it looks good enough.
240     *
241     * Print ".." afterwards to show that there might be more arguments
242     * than were passed in register.
243     */
244     for (x=0; x<n_args_to_print; x++) {
245     int64_t d;
246     #ifdef DYNTRANS_X86
247     d = 0; /* TODO */
248     #else
249     /* Args in registers: */
250     d = cpu->cd.DYNTRANS_ARCH.
251     #ifdef DYNTRANS_ALPHA
252     r[ALPHA_A0
253     #endif
254     #ifdef DYNTRANS_ARM
255     r[0
256     #endif
257     #ifdef DYNTRANS_AVR
258     /* TODO: 24,25 = first register, but then
259     they go downwards, ie. 22,23 and so on */
260     r[24
261     #endif
262     #ifdef DYNTRANS_HPPA
263     r[0 /* TODO */
264     #endif
265     #ifdef DYNTRANS_I960
266     r[0 /* TODO */
267     #endif
268     #ifdef DYNTRANS_IA64
269     r[0 /* TODO */
270     #endif
271     #ifdef DYNTRANS_M68K
272     d[0 /* TODO */
273     #endif
274     #ifdef DYNTRANS_MIPS
275     gpr[MIPS_GPR_A0
276     #endif
277     #ifdef DYNTRANS_PPC
278     gpr[3
279     #endif
280     #ifdef DYNTRANS_SH
281     r[2
282     #endif
283     #ifdef DYNTRANS_SPARC
284     r_i[0
285     #endif
286     + x];
287     #endif
288     symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
289    
290     if (d > -256 && d < 256)
291     fatal("%i", (int)d);
292     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
293     fatal("\"%s\"", memory_conv_to_string(cpu,
294     cpu->mem, d, strbuf, sizeof(strbuf)));
295     else if (symbol != NULL && ot == 0)
296     fatal("&%s", symbol);
297     else {
298     if (cpu->is_32bit)
299     fatal("0x%x", (int)d);
300     else
301     fatal("0x%llx", (long long)d);
302     }
303    
304     if (x < n_args_to_print - 1)
305     fatal(",");
306     }
307    
308     if (print_dots)
309     fatal(",..");
310     }
311     #endif
312    
313    
314    
315     #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
316     /* forward declaration of to_be_translated and end_of_page: */
317     static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
318     static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
319     #ifdef DYNTRANS_DUALMODE_32
320     static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
321     static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
322     #endif
323     /*
324     * XXX_tc_allocate_default_page():
325     *
326     * Create a default page (with just pointers to instr(to_be_translated)
327     * at cpu->translation_cache_cur_ofs.
328     */
329     static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE(struct cpu *cpu,
330     uint64_t physaddr)
331     {
332     struct DYNTRANS_TC_PHYSPAGE *ppp;
333     int i;
334    
335     /* Create the physpage header: */
336     ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
337     + cpu->translation_cache_cur_ofs);
338     ppp->next_ofs = 0;
339     ppp->physaddr = physaddr;
340    
341     /* TODO: Is this faster than copying an entire template page? */
342     for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
343     ppp->ics[i].f =
344     #ifdef DYNTRANS_DUALMODE_32
345     cpu->is_32bit? instr32(to_be_translated) :
346     #endif
347     instr(to_be_translated);
348    
349     ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE].f =
350     #ifdef DYNTRANS_DUALMODE_32
351     cpu->is_32bit? instr32(end_of_page) :
352     #endif
353     instr(end_of_page);
354    
355     cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
356     }
357     #endif /* DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE */
358    
359    
360    
361     #ifdef DYNTRANS_PC_TO_POINTERS_FUNC
362     /*
363     * XXX_pc_to_pointers_generic():
364     *
365     * Generic case. See DYNTRANS_PC_TO_POINTERS_FUNC below.
366     */
367     void DYNTRANS_PC_TO_POINTERS_GENERIC(struct cpu *cpu)
368     {
369     #ifdef MODE32
370     uint32_t
371     #else
372     uint64_t
373     #endif
374     cached_pc, physaddr;
375     uint32_t physpage_ofs;
376     int ok, pagenr, table_index;
377     uint32_t *physpage_entryp;
378     struct DYNTRANS_TC_PHYSPAGE *ppp;
379    
380     #ifdef MODE32
381     int index;
382     cached_pc = cpu->pc;
383     index = cached_pc >> 12;
384     #else
385     #ifdef DYNTRANS_ALPHA
386     uint32_t a, b;
387     int kernel = 0;
388     struct alpha_vph_page *vph_p;
389     cached_pc = cpu->pc;
390     a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
391     b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
392     if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
393     vph_p = cpu->cd.alpha.vph_table0_kernel[a];
394     kernel = 1;
395     } else
396     vph_p = cpu->cd.alpha.vph_table0[a];
397     #else
398     #ifdef DYNTRANS_IA64
399     fatal("IA64 todo\n");
400     #else
401     fatal("Neither alpha, ia64, nor 32-bit? 3\n");
402     exit(1);
403     #endif
404     #endif
405     #endif
406    
407     /* Virtual to physical address translation: */
408     ok = 0;
409     #ifdef MODE32
410     if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
411     physaddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
412     ok = 1;
413     }
414     #else
415     #ifdef DYNTRANS_ALPHA
416     if (vph_p->host_load[b] != NULL) {
417     physaddr = vph_p->phys_addr[b];
418     ok = 1;
419     }
420     #else
421     #ifdef DYNTRANS_IA64
422     fatal("IA64 todo\n");
423     #else
424     fatal("Neither alpha, ia64, nor 32-bit? 4\n");
425     exit(1);
426     #endif
427     #endif
428     #endif
429    
430     if (!ok) {
431     uint64_t paddr;
432     if (cpu->translate_address != NULL)
433     ok = cpu->translate_address(cpu, cached_pc,
434     &paddr, FLAG_INSTR);
435     else {
436     paddr = cached_pc;
437     ok = 1;
438     }
439     if (!ok) {
440     /*
441     fatal("TODO: instruction vaddr=>paddr translation"
442     " failed. vaddr=0x%llx\n", (long long)cached_pc);
443     fatal("!! cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,
444     cpu->cd.arm.r[ARM_PC]);
445     */
446     ok = cpu->translate_address(cpu, cpu->pc, &paddr,
447     FLAG_INSTR);
448     /*
449     printf("EXCEPTION HANDLER: vaddr = 0x%x ==> paddr = 0x%x\n",
450     (int)cpu->pc, (int)paddr);
451     fatal("!? cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,
452     cpu->cd.arm.r[ARM_PC]);
453     */
454     if (!ok) {
455     fatal("FATAL: could not find physical"
456     " address of the exception handler?");
457     exit(1);
458     }
459     }
460     cached_pc = cpu->pc;
461     physaddr = paddr;
462     }
463    
464     if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE)
465     cpu_create_or_reset_tc(cpu);
466    
467     pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
468     table_index = PAGENR_TO_TABLE_INDEX(pagenr);
469    
470     physpage_entryp = &(((uint32_t *)cpu->translation_cache)[table_index]);
471     physpage_ofs = *physpage_entryp;
472     ppp = NULL;
473    
474     /* Traverse the physical page chain: */
475     while (physpage_ofs != 0) {
476     ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
477     + physpage_ofs);
478     /* If we found the page in the cache, then we're done: */
479     if (ppp->physaddr == physaddr)
480     break;
481     /* Try the next page in the chain: */
482     physpage_ofs = ppp->next_ofs;
483     }
484    
485     /* If the offset is 0 (or ppp is NULL), then we need to create a
486     new "default" empty translation page. */
487    
488     if (ppp == NULL) {
489     /* fatal("CREATING page %lli (physaddr 0x%llx), table index "
490     "%i\n", (long long)pagenr, (long long)physaddr,
491     (int)table_index); */
492     *physpage_entryp = physpage_ofs =
493     cpu->translation_cache_cur_ofs;
494    
495     /* Allocate a default page, with to_be_translated entries: */
496     DYNTRANS_TC_ALLOCATE(cpu, physaddr);
497    
498     ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
499     + physpage_ofs);
500     }
501    
502     #ifdef MODE32
503     if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
504     cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
505     #endif
506    
507     #ifdef DYNTRANS_ALPHA
508     if (vph_p->host_load[b] != NULL)
509     vph_p->phys_page[b] = ppp;
510     #endif
511    
512     cpu->invalidate_translation_caches_paddr(cpu, physaddr,
513     JUST_MARK_AS_NON_WRITABLE);
514    
515     cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;
516     cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
517     cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
518     DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
519    
520     /* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, "
521     "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,
522     (long long)table_index, (long long)physpage_ofs); */
523     }
524    
525    
526     /*
527     * XXX_pc_to_pointers():
528     *
529     * This function uses the current program counter (a virtual address) to
530     * find out which physical translation page to use, and then sets the current
531     * translation page pointers to that page.
532     *
533     * If there was no translation page for that physical page, then an empty
534     * one is created.
535     *
536     * NOTE: This is the quick lookup version. See
537     * DYNTRANS_PC_TO_POINTERS_GENERIC above for the generic case.
538     */
539     void DYNTRANS_PC_TO_POINTERS_FUNC(struct cpu *cpu)
540     {
541     #ifdef MODE32
542     uint32_t
543     #else
544     uint64_t
545     #endif
546     cached_pc;
547     struct DYNTRANS_TC_PHYSPAGE *ppp;
548    
549     #ifdef MODE32
550     int index;
551     cached_pc = cpu->pc;
552     index = cached_pc >> 12;
553     ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
554     if (ppp != NULL)
555     goto have_it;
556     #else
557     #ifdef DYNTRANS_ALPHA
558     uint32_t a, b;
559     int kernel = 0;
560     struct alpha_vph_page *vph_p;
561     cached_pc = cpu->pc;
562     a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
563     b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
564     if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
565     vph_p = cpu->cd.alpha.vph_table0_kernel[a];
566     kernel = 1;
567     } else
568     vph_p = cpu->cd.alpha.vph_table0[a];
569     if (vph_p != cpu->cd.alpha.vph_default_page) {
570     ppp = vph_p->phys_page[b];
571     if (ppp != NULL)
572     goto have_it;
573     }
574     #else
575     #ifdef DYNTRANS_IA64
576     fatal("IA64 todo\n");
577     #else
578     fatal("Neither alpha, ia64, nor 32-bit? 1\n");
579     { char *p = (char *) 0; *p = 0; }
580     exit(1);
581     #endif
582     #endif
583     #endif
584    
585     DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
586     return;
587    
588     /* Quick return path: */
589     have_it:
590     cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;
591     cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
592     cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
593     DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
594    
595     /* printf("cached_pc=0x%016llx pagenr=%lli table_index=%lli, "
596     "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,
597     (long long)table_index, (long long)physpage_ofs); */
598     }
599     #endif /* DYNTRANS_PC_TO_POINTERS_FUNC */
600    
601    
602    
603     #ifdef DYNTRANS_INVAL_ENTRY
604     /*
605     * XXX_invalidate_tlb_entry():
606     *
607     * Invalidate one translation entry (based on virtual address).
608     *
609     * If the JUST_MARK_AS_NON_WRITABLE flag is set, then the translation entry
610     * is just downgraded to non-writable (ie the host store page is set to
611     * NULL). Otherwise, the entire translation is removed.
612     */
613     void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
614     #ifdef MODE32
615     uint32_t
616     #else
617     uint64_t
618     #endif
619     vaddr_page, int flags)
620     {
621     #ifdef MODE32
622     uint32_t index = vaddr_page >> 12;
623    
624     if (flags & JUST_MARK_AS_NON_WRITABLE) {
625     /* printf("JUST MARKING NON-W: vaddr 0x%08x\n",
626     (int)vaddr_page); */
627     cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
628     } else {
629     cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
630     cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
631     cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
632     cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
633     }
634     #else
635     /* 2-level: */
636     #ifdef DYNTRANS_ALPHA
637     struct alpha_vph_page *vph_p;
638     uint32_t a, b;
639     int kernel = 0;
640    
641     a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
642     b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
643     if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
644     vph_p = cpu->cd.alpha.vph_table0_kernel[a];
645     kernel = 1;
646     } else
647     vph_p = cpu->cd.alpha.vph_table0[a];
648    
649     if (vph_p == cpu->cd.alpha.vph_default_page) {
650     fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n");
651     exit(1);
652     }
653    
654     if (flags & JUST_MARK_AS_NON_WRITABLE) {
655     vph_p->host_store[b] = NULL;
656     return;
657     }
658     vph_p->host_load[b] = NULL;
659     vph_p->host_store[b] = NULL;
660     vph_p->phys_addr[b] = 0;
661     vph_p->phys_page[b] = NULL;
662     vph_p->refcount --;
663     if (vph_p->refcount < 0) {
664     fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n");
665     exit(1);
666     }
667     if (vph_p->refcount == 0) {
668     vph_p->next = cpu->cd.alpha.vph_next_free_page;
669     cpu->cd.alpha.vph_next_free_page = vph_p;
670     if (kernel)
671     cpu->cd.alpha.vph_table0_kernel[a] =
672     cpu->cd.alpha.vph_default_page;
673     else
674     cpu->cd.alpha.vph_table0[a] =
675     cpu->cd.alpha.vph_default_page;
676     }
677     #else /* !DYNTRANS_ALPHA */
678     #ifdef DYNTRANS_IA64
679     fatal("IA64: blah blah TODO\n");
680     #else
681     fatal("Not yet for non-1-level, non-Alpha, non-ia64\n");
682     #endif /* !DYNTRANS_IA64 */
683     #endif /* !DYNTRANS_ALPHA */
684     #endif
685     }
686     #endif
687    
688    
689     #ifdef DYNTRANS_INVALIDATE_TC_PADDR
690     /*
691     * XXX_invalidate_translation_caches_paddr():
692     *
693     * Invalidate all entries matching a specific physical address, a specific
694     * virtual address, or ALL entries.
695     *
696     * flags should be one of
697     * INVALIDATE_PADDR INVALIDATE_VADDR or INVALIDATE_ALL
698     *
699     * In the case when all translations are invalidated, paddr doesn't need
700     * to be supplied.
701     *
702     * NOTE/TODO: Poorly choosen name for this function, as it can
703     * invalidate based on virtual address as well.
704     */
705     void DYNTRANS_INVALIDATE_TC_PADDR(struct cpu *cpu, uint64_t paddr, int flags)
706     {
707     int r;
708     #ifdef MODE32
709     uint32_t
710     #else
711     uint64_t
712     #endif
713     addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);
714    
715     for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
716     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (
717     (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==
718     addr_page && flags & INVALIDATE_PADDR) ||
719     (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==
720     addr_page && flags & INVALIDATE_VADDR) ||
721     flags & INVALIDATE_ALL) ) {
722     DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
723     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
724     flags);
725     if (flags & JUST_MARK_AS_NON_WRITABLE)
726     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
727     .writeflag = 0;
728     else
729     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
730     .valid = 0;
731     }
732     }
733     }
734     #endif /* DYNTRANS_INVALIDATE_TC_PADDR */
735    
736    
737    
738     #ifdef DYNTRANS_INVALIDATE_TC_CODE
739     /*
740     * XXX_invalidate_code_translation():
741     *
742     * Invalidate code translations for a specific physical address, a specific
743     * virtual address, or for all entries in the cache.
744     */
745     void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)
746     {
747     int r;
748     #ifdef MODE_32
749     uint32_t
750     #else
751     uint64_t
752     #endif
753     vaddr_page, paddr_page;
754    
755     addr &= ~(DYNTRANS_PAGESIZE-1);
756    
757     /* printf("DYNTRANS_INVALIDATE_TC_CODE addr=0x%08x flags=%i\n",
758     (int)addr, flags); */
759    
760     if (flags & INVALIDATE_PADDR) {
761     int pagenr, table_index;
762     uint32_t physpage_ofs, *physpage_entryp;
763     struct DYNTRANS_TC_PHYSPAGE *ppp;
764    
765     pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
766     table_index = PAGENR_TO_TABLE_INDEX(pagenr);
767    
768     physpage_entryp = &(((uint32_t *)cpu->
769     translation_cache)[table_index]);
770     physpage_ofs = *physpage_entryp;
771     ppp = NULL;
772    
773     /* Traverse the physical page chain: */
774     while (physpage_ofs != 0) {
775     ppp = (struct DYNTRANS_TC_PHYSPAGE *)
776     (cpu->translation_cache + physpage_ofs);
777     /* If we found the page in the cache,
778     then we're done: */
779     if (ppp->physaddr == addr)
780     break;
781     /* Try the next page in the chain: */
782     physpage_ofs = ppp->next_ofs;
783     }
784    
785     /* If the page was found, then we should invalidate all
786     code translations: */
787     if (ppp != NULL) {
788     /* TODO: Is this faster than copying an entire
789     template page? */
790     int i;
791     for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
792     ppp->ics[i].f =
793     #ifdef DYNTRANS_DUALMODE_32
794     cpu->is_32bit? instr32(to_be_translated) :
795     #endif
796     instr(to_be_translated);
797     }
798     }
799    
800     /* Invalidate entries in the VPH table: */
801     for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
802     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
803     vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
804     .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
805     paddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
806     .paddr_page & ~(DYNTRANS_PAGESIZE-1);
807    
808     if (flags & INVALIDATE_ALL ||
809     (flags & INVALIDATE_PADDR && paddr_page == addr) ||
810     (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
811     #ifdef MODE32
812     uint32_t index = vaddr_page >> 12;
813     cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
814     #else
815     /* 2-level: */
816     #ifdef DYNTRANS_ALPHA
817     struct alpha_vph_page *vph_p;
818     uint32_t a, b;
819     int kernel = 0;
820    
821     a = (vaddr_page >> ALPHA_LEVEL0_SHIFT)
822     & (ALPHA_LEVEL0 - 1);
823     b = (vaddr_page >> ALPHA_LEVEL1_SHIFT)
824     & (ALPHA_LEVEL1 - 1);
825     if ((vaddr_page >> ALPHA_TOPSHIFT) ==
826     ALPHA_TOP_KERNEL) {
827     vph_p = cpu->cd.alpha.
828     vph_table0_kernel[a];
829     kernel = 1;
830     } else
831     vph_p = cpu->cd.alpha.vph_table0[a];
832     vph_p->phys_page[b] = NULL;
833     #else /* !DYNTRANS_ALPHA */
834     #ifdef DYNTRANS_IA64
835     fatal("IA64: blah yo yo TODO\n");
836     #else
837     fatal("Not yet for non-1-level, non-Alpha, "
838     "non-ia64\n");
839     #endif /* !DYNTRANS_IA64 */
840     #endif /* !DYNTRANS_ALPHA */
841     #endif
842     }
843     }
844     }
845     }
846     #endif /* DYNTRANS_INVALIDATE_TC_CODE */
847    
848    
849    
850     #ifdef DYNTRANS_UPDATE_TRANSLATION_TABLE
851     /*
852     * XXX_update_translation_table():
853     *
854     * Update the virtual memory translation tables.
855     */
856     void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
857     unsigned char *host_page, int writeflag, uint64_t paddr_page)
858     {
859     int64_t lowest, highest = -1;
860     int found, r, lowest_index;
861    
862     #ifdef DYNTRANS_ALPHA
863     uint32_t a, b;
864     struct alpha_vph_page *vph_p;
865     int kernel = 0;
866     /* fatal("update_translation_table(): v=0x%llx, h=%p w=%i"
867     " p=0x%llx\n", (long long)vaddr_page, host_page, writeflag,
868     (long long)paddr_page); */
869     #else
870     #ifdef MODE32
871     uint32_t index;
872     vaddr_page &= 0xffffffffULL;
873     paddr_page &= 0xffffffffULL;
874     /* fatal("update_translation_table(): v=0x%x, h=%p w=%i"
875     " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
876     (int)paddr_page); */
877     #else /* !MODE32 */
878     #ifdef DYNTRANS_IA64
879     fatal("IA64 update todo\n");
880     #else
881     fatal("Neither 32-bit, IA64, nor Alpha? 2\n");
882     exit(1);
883     #endif
884     #endif
885     #endif
886    
887     /* Scan the current TLB entries: */
888     found = -1; lowest_index = 0;
889     lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
890     for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
891     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
892     lowest = cpu->cd.DYNTRANS_ARCH.
893     vph_tlb_entry[r].timestamp;
894     lowest_index = r;
895     }
896     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)
897     highest = cpu->cd.DYNTRANS_ARCH.
898     vph_tlb_entry[r].timestamp;
899     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
900     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==
901     vaddr_page) {
902     found = r;
903     break;
904     }
905     }
906    
907     if (found < 0) {
908     /* Create the new TLB entry, overwriting the oldest one: */
909     r = lowest_index;
910     if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
911     /* This one has to be invalidated first: */
912     DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
913     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
914     0);
915     }
916    
917     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid = 1;
918     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;
919     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;
920     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
921     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = writeflag;
922     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
923    
924     /* Add the new translation to the table: */
925     #ifdef DYNTRANS_ALPHA
926     a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
927     b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
928     if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
929     vph_p = cpu->cd.alpha.vph_table0_kernel[a];
930     kernel = 1;
931     } else
932     vph_p = cpu->cd.alpha.vph_table0[a];
933     if (vph_p == cpu->cd.alpha.vph_default_page) {
934     if (cpu->cd.alpha.vph_next_free_page != NULL) {
935     if (kernel)
936     vph_p = cpu->cd.alpha.vph_table0_kernel
937     [a] = cpu->cd.alpha.
938     vph_next_free_page;
939     else
940     vph_p = cpu->cd.alpha.vph_table0[a] =
941     cpu->cd.alpha.vph_next_free_page;
942     cpu->cd.alpha.vph_next_free_page = vph_p->next;
943     } else {
944     if (kernel)
945     vph_p = cpu->cd.alpha.vph_table0_kernel
946     [a] = malloc(sizeof(struct
947     alpha_vph_page));
948     else
949     vph_p = cpu->cd.alpha.vph_table0[a] =
950     malloc(sizeof(struct
951     alpha_vph_page));
952     memset(vph_p, 0, sizeof(struct alpha_vph_page));
953     }
954     }
955     vph_p->refcount ++;
956     vph_p->host_load[b] = host_page;
957     vph_p->host_store[b] = writeflag? host_page : NULL;
958     vph_p->phys_addr[b] = paddr_page;
959     vph_p->phys_page[b] = NULL;
960     #else
961     #ifdef MODE32
962     index = vaddr_page >> 12;
963     cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
964     cpu->cd.DYNTRANS_ARCH.host_store[index] =
965     writeflag? host_page : NULL;
966     cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
967     cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
968     #endif /* 32 */
969     #endif /* !ALPHA */
970     } else {
971     /*
972     * The translation was already in the TLB.
973     * Writeflag = 0: Do nothing.
974     * Writeflag = 1: Make sure the page is writable.
975     * Writeflag = -1: Downgrade to readonly.
976     */
977     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[found].timestamp =
978     highest + 1;
979     if (writeflag == 1)
980     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
981     if (writeflag == -1)
982     cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
983     #ifdef DYNTRANS_ALPHA
984     a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
985     b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
986     if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
987     vph_p = cpu->cd.alpha.vph_table0_kernel[a];
988     kernel = 1;
989     } else
990     vph_p = cpu->cd.alpha.vph_table0[a];
991     vph_p->phys_page[b] = NULL;
992     if (vph_p->phys_addr[b] == paddr_page) {
993     if (writeflag == 1)
994     vph_p->host_store[b] = host_page;
995     if (writeflag == -1)
996     vph_p->host_store[b] = NULL;
997     } else {
998     /* Change the entire physical/host mapping: */
999     vph_p->host_load[b] = host_page;
1000     vph_p->host_store[b] = writeflag? host_page : NULL;
1001     vph_p->phys_addr[b] = paddr_page;
1002     }
1003     #else
1004     #ifdef MODE32
1005     index = vaddr_page >> 12;
1006     cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1007     if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1008     if (writeflag == 1)
1009     cpu->cd.DYNTRANS_ARCH.host_store[index] =
1010     host_page;
1011     if (writeflag == -1)
1012     cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1013     } else {
1014     /* Change the entire physical/host mapping: */
1015     cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1016     cpu->cd.DYNTRANS_ARCH.host_store[index] =
1017     writeflag? host_page : NULL;
1018     cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1019     }
1020     #endif /* 32 */
1021     #endif /* !ALPHA */
1022     }
1023     }
1024     #endif /* DYNTRANS_UPDATE_TRANSLATION_TABLE */
1025    
1026    
1027     /*****************************************************************************/
1028    
1029    
1030     #ifdef DYNTRANS_TO_BE_TRANSLATED_HEAD
1031     /*
1032     * Check for breakpoints.
1033     */
1034     if (!single_step_breakpoint) {
1035     #ifdef MODE32
1036     uint32_t curpc = cpu->pc;
1037     #else
1038     uint64_t curpc = cpu->pc;
1039     #endif
1040     int i;
1041     for (i=0; i<cpu->machine->n_breakpoints; i++)
1042     if (curpc ==
1043     #ifdef MODE32
1044     (uint32_t)
1045     #endif
1046     cpu->machine->breakpoint_addr[i]) {
1047     if (!cpu->machine->instruction_trace) {
1048     int old_quiet_mode = quiet_mode;
1049     quiet_mode = 0;
1050     DISASSEMBLE(cpu, ib, 1, 0, 0);
1051     quiet_mode = old_quiet_mode;
1052     }
1053     fatal("BREAKPOINT: pc = 0x%llx\n(The "
1054     "instruction has not yet executed.)\n",
1055     (long long)cpu->pc);
1056     single_step_breakpoint = 1;
1057     single_step = 1;
1058     goto stop_running_translated;
1059     }
1060     }
1061     #endif /* DYNTRANS_TO_BE_TRANSLATED_HEAD */
1062    
1063    
1064     /*****************************************************************************/
1065    
1066    
1067     #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1068     /*
1069     * If we end up here, then an instruction was translated.
1070     */
1071     translated;
1072    
1073     /*
1074     * Now it is time to check for combinations of instructions that can
1075     * be converted into a single function call.
1076     *
1077     * Note: Single-stepping or instruction tracing doesn't work with
1078     * instruction combination.
1079     */
1080     if (!single_step && !cpu->machine->instruction_trace)
1081     COMBINE_INSTRUCTIONS(cpu, ic, addr);
1082    
1083     /* ... and finally execute the translated instruction: */
1084     if (single_step_breakpoint) {
1085     /*
1086     * Special case when single-stepping: Execute the translated
1087     * instruction, but then replace it with a "to be translated"
1088     * directly afterwards.
1089     */
1090     single_step_breakpoint = 0;
1091     ic->f(cpu, ic);
1092     ic->f =
1093     #ifdef DYNTRANS_DUALMODE_32
1094     cpu->is_32bit? instr32(to_be_translated) :
1095     #endif
1096     instr(to_be_translated);
1097     } else
1098     ic->f(cpu, ic);
1099    
1100     return;
1101    
1102    
1103     bad: /*
1104     * Nothing was translated. (Unimplemented or illegal instruction.)
1105     */
1106    
1107     quiet_mode = 0;
1108     fatal("to_be_translated(): TODO: unimplemented instruction");
1109    
1110     if (cpu->machine->instruction_trace)
1111     #ifdef MODE32
1112     fatal(" at 0x%x\n", (int)cpu->pc);
1113     #else
1114     fatal(" at 0x%llx\n", (long long)cpu->pc);
1115     #endif
1116     else {
1117     fatal(":\n");
1118     DISASSEMBLE(cpu, ib, 1, 0, 0);
1119     }
1120    
1121     cpu->running = 0;
1122     cpu->dead = 1;
1123     stop_running_translated:
1124     debugger_n_steps_left_before_interaction = 0;
1125     cpu->running_translated = 0;
1126     ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1127     cpu->cd.DYNTRANS_ARCH.next_ic ++;
1128    
1129     /* Execute the "nothing" instruction: */
1130     ic->f(cpu, ic);
1131     #endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */
1132    

  ViewVC Help
Powered by ViewVC 1.1.26