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

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

  ViewVC Help
Powered by ViewVC 1.1.26