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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.14  
changed lines
  Added in v.32

  ViewVC Help
Powered by ViewVC 1.1.26