/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.54 2006/02/09 22:55:20 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.113 2006/07/21 20:09:15 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  #if 1   /*  IC statistics:  */  #define STATIC_STUFF
36    /*
37     *  gather_statistics():
38     */
39  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
40  {  {
41            char ch, buf[60];
42          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
43          static long long n = 0;          int i = 0;
         static FILE *f = NULL;  
   
         n++;  
         if (n < 100000000)  
                 return;  
   
         if (f == NULL) {  
                 f = fopen("instruction_call_statistics.raw", "w");  
                 if (f == NULL) {  
                         fatal("Unable to open statistics file for output.\n");  
                         exit(1);  
                 }  
         }  
         fwrite(&ic->f, 1, sizeof(void *), f);  
 }  
 #else   /*  PC statistics:  */  
 static void gather_statistics(struct cpu *cpu)  
 {  
44          uint64_t a;          uint64_t a;
45          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          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);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
         if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
                 return;  
47    
48  #if 0          buf[0] = '\0';
         /*  Use the physical address:  */  
         cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)  
             cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
         a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;  
 #else  
         /*  Use the PC (virtual address):  */  
         a = cpu->pc;  
 #endif  
   
         a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<  
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
49    
50          /*          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
51           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
52           */                          strlcat(buf, " ", sizeof(buf));
53  a &= 0x03ffffff;  
54  {                  switch (ch) {
55          static long long *array = NULL;                  case 'i':
56          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
57          static int n = 0;                              "%p", (void *)ic->f);
58          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
59          if (array == NULL)                  case 'p':
60                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
61          if (array_16kpage_in_use == NULL)                          /*  (low_pc must be within the page!)  */
62                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                          if (low_pc < 0 ||
63          a &= (16384*1024-1);                              low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
64          array[a] ++;                                  strlcat(buf, "-", sizeof(buf));
65          array_16kpage_in_use[a / 16384] = 1;                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
66          n++;                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
67          if ((n & 0x3fffffff) == 0) {                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
68                  FILE *f = fopen("statistics.out", "w");                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
69                  int i, j;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
70                  printf("Saving statistics... "); fflush(stdout);                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
71                  for (i=0; i<1024; i++)                          if (cpu->is_32bit)
72                          if (array_16kpage_in_use[i]) {                                  snprintf(buf + strlen(buf), sizeof(buf),
73                                  for (j=0; j<16384; j++)                                      "0x%016"PRIx32, (uint32_t)a);
74                                          if (array[i*16384 + j] > 0)                          else
75                                                  fprintf(f, "%lli\t0x%016llx\n",                                  snprintf(buf + strlen(buf), sizeof(buf),
76                                                      (long long)array[i*16384+j],                                      "0x%016"PRIx64, (uint64_t)a);
77                                                      (long long)((i*16384+j) <<                          break;
78                                  DYNTRANS_INSTR_ALIGNMENT_SHIFT));                  case 'v':
79                          }                          /*  Virtual program counter address:  */
80                  fclose(f);                          /*  (low_pc inside the page, or in a delay slot)  */
81                  printf("n=0x%08x\n", n);                          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  }  
 #endif  /*  PC statistics  */  
102    
103  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
104    
105    
106  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
107  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \
108                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \
109                          ic->f(cpu, ic);                          ic->f(cpu, ic);
110  #else  #else
111  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  
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  #endif
159    #endif  /*  STATIC STUFF  */
160    
161    
162    
163    #ifdef  DYNTRANS_RUN_INSTR
164  /*  /*
165   *  XXX_cpu_run_instr():   *  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  #ifdef DYNTRANS_PPC
225          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
226                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  ppc_exception(cpu, PPC_EXCEPTION_DEC);
# Line 174  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 238  int DYNTRANS_CPU_RUN_INSTR(struct emul *
238          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
239              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
240    
241          if (single_step || cpu->machine->instruction_trace) {          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 195  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_MIPS  #ifdef DYNTRANS_DELAYSLOT
 /*  TODO: generalize, not just MIPS  */  
272                                  /*  Show the instruction in the delay slot,                                  /*  Show the instruction in the delay slot,
273                                      if any:  */                                      if any:  */
274                                  fatal("TODO: check for delay slot!\n");                                  if (cpu->instruction_has_delayslot == NULL)
275                                            fatal("WARNING: ihd func not yet"
276                                                " implemented?\n");
277                                    else if (cpu->instruction_has_delayslot(cpu,
278                                        instr)) {
279                                            int saved_delayslot = cpu->delay_slot;
280                                            cpu->memory_rw(cpu, cpu->mem, cached_pc
281                                                + 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                          }                          }
293                  }                  }
# Line 215  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 296  int DYNTRANS_CPU_RUN_INSTR(struct emul *
296                      be combined into one. This clears all translations:  */                      be combined into one. This clears all translations:  */
297                  if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {                  if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {
298                          int i;                          int i;
299                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
300                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =
301  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
302                                      cpu->is_32bit?                                      cpu->is_32bit?
303                                          instr32(to_be_translated) :                                          instr32(to_be_translated) :
304  #endif  #endif
305                                          instr(to_be_translated);                                          instr(to_be_translated);
306                          fatal("[ Note: The translation of physical page 0x%llx"  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
307                              " contained combinations of instructions; these "                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].
308                              "are now flushed because we are single-stepping."                                      arg[0] = 0;
309                              " ]\n", (long long)cpu->cd.DYNTRANS_ARCH.  #endif
310                            }
311    
312                            fatal("[ Note: The translation of physical page 0x%"
313                                PRIx64" contained combinations of instructions; "
314                                "these are now flushed because we are single-"
315                                "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.
316                              cur_physpage->physaddr);                              cur_physpage->physaddr);
317    
318                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=
319                              ~(COMBINATIONS | TRANSLATIONS);                              ~COMBINATIONS;
320                            cpu->cd.DYNTRANS_ARCH.cur_physpage->translations = 0;
321                  }                  }
322    
323                  if (show_opcode_statistics)                  if (cpu->machine->statistics_enabled)
324                          S;                          S;
325    
326                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
327                  ic->f(cpu, ic);                  I;
328    
329                  n_instrs = 1;                  n_instrs = 1;
330          } else if (show_opcode_statistics) {          } else if (cpu->machine->cycle_accurate) {
331                    /*  Executing multiple instructions, and call devices'
332                        tick functions:  */
333                    n_instrs = 0;
334                    for (;;) {
335                            struct DYNTRANS_IC *ic;
336    /*  TODO: continue here  */
337    int64_t cycles = cpu->cd.avr.extra_cycles;
338                            I;
339                            n_instrs += 1;
340    cycles = cpu->cd.avr.extra_cycles - cycles + 1;
341    /*  The instruction took 'cycles' cycles.  */
342    /* printf("A\n"); */
343    while (cycles-- > 0)
344            cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);
345    /* printf("B\n"); */
346    
347                            if (!cpu->running_translated ||
348                                n_instrs + cpu->n_translated_instrs >=
349                                N_SAFE_DYNTRANS_LIMIT)
350                                    break;
351                    }
352            } else if (cpu->machine->statistics_enabled) {
353                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
354                  n_instrs = 0;                  n_instrs = 0;
355                  for (;;) {                  for (;;) {
# Line 251  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 363  int DYNTRANS_CPU_RUN_INSTR(struct emul *
363                          n_instrs += 24;                          n_instrs += 24;
364    
365                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
366                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >=
367                                N_SAFE_DYNTRANS_LIMIT)
368                                  break;                                  break;
369                  }                  }
370          } else {          } else {
# Line 271  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 384  int DYNTRANS_CPU_RUN_INSTR(struct emul *
384                          n_instrs += 60;                          n_instrs += 60;
385    
386                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
387                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >=
388                                N_SAFE_DYNTRANS_LIMIT)
389                                  break;                                  break;
390                  }                  }
391          }          }
# Line 300  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 414  int DYNTRANS_CPU_RUN_INSTR(struct emul *
414                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
415          }          }
416    
417    #ifdef DYNTRANS_MIPS
418            /*  Update the count register (on everything except EXC3K):  */
419            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
420                    uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
421                    int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
422                    int32_t diff2;
423                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
424                        (int32_t) (old + n_instrs);
425                    diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
426                        cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
427                    if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)
428                            cpu_interrupt(cpu, 7);
429            }
430    #endif
431  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
432          /*  Update the Decrementer and Time base registers:  */          /*  Update the Decrementer and Time base registers:  */
433          {          {
# Line 318  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 446  int DYNTRANS_CPU_RUN_INSTR(struct emul *
446          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
447          return n_instrs;          return n_instrs;
448  }  }
449  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
450    
451    
452    
# Line 336  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 464  void DYNTRANS_FUNCTION_TRACE(struct cpu
464          char *symbol;          char *symbol;
465          uint64_t ot;          uint64_t ot;
466          int x, print_dots = 1, n_args_to_print =          int x, print_dots = 1, n_args_to_print =
467  #ifdef DYNTRANS_ALPHA  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
468              6              6
469  #else  #else
470  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
# Line 365  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 493  void DYNTRANS_FUNCTION_TRACE(struct cpu
493           */           */
494          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
495                  int64_t d;                  int64_t d;
496  #ifdef DYNTRANS_X86  #if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER)
497                  d = 0;          /*  TODO  */                  d = 0;          /*  TODO  */
498  #else  #else
499                  /*  Args in registers:  */                  /*  Args in registers:  */
# Line 418  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 546  void DYNTRANS_FUNCTION_TRACE(struct cpu
546                          fatal("&%s", symbol);                          fatal("&%s", symbol);
547                  else {                  else {
548                          if (cpu->is_32bit)                          if (cpu->is_32bit)
549                                  fatal("0x%x", (int)d);                                  fatal("0x%"PRIx32, (uint32_t)d);
550                          else                          else
551                                  fatal("0x%llx", (long long)d);                                  fatal("0x%"PRIx64, (uint64_t)d);
552                  }                  }
553    
554                  if (x < n_args_to_print - 1)                  if (x < n_args_to_print - 1)
# Line 435  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 563  void DYNTRANS_FUNCTION_TRACE(struct cpu
563    
564    
565  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
   
 /*  forward declaration of to_be_translated and end_of_page:  */  
 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
   
 #ifdef DYNTRANS_DELAYSLOT  
 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
 #endif  
   
566  /*  /*
567   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
568   *   *
# Line 461  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 573  static void DYNTRANS_TC_ALLOCATE_DEFAULT
573          uint64_t physaddr)          uint64_t physaddr)
574  {  {
575          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
576    
         /*  Create the physpage header:  */  
577          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
578              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
   
         /*  TODO: Is this faster than copying an entire template page?  */  
         for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)  
                 ppp->ics[i].f =  
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
579    
580          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =          /*  Copy the entire template page first:  */
581  #ifdef DYNTRANS_DUALMODE_32          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
582              cpu->is_32bit? instr32(end_of_page) :              struct DYNTRANS_TC_PHYSPAGE));
 #endif  
             instr(end_of_page);  
583    
584  #ifdef DYNTRANS_DELAYSLOT          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =  
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page2) :  
 #endif  
             instr(end_of_page2);  
 #endif  
585    
586          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
587    
588          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
589          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
590          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
591  }  }
592  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 514  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 606  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
606  #else  #else
607          uint64_t          uint64_t
608  #endif  #endif
609              cached_pc, physaddr = 0;              cached_pc = cpu->pc, physaddr = 0;
610          uint32_t physpage_ofs;          uint32_t physpage_ofs;
611          int ok, pagenr, table_index;          int ok, pagenr, table_index;
612          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
613          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
614    
615  #ifdef MODE32  #ifdef MODE32
616          int index;          int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
         cached_pc = cpu->pc;  
         index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
617  #else  #else
618  #ifdef DYNTRANS_ALPHA          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
619          uint32_t a, b;          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
620          int kernel = 0;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
621          struct alpha_vph_page *vph_p;          uint32_t x1, x2, x3;
622          cached_pc = cpu->pc;          struct DYNTRANS_L2_64_TABLE *l2;
623          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          struct DYNTRANS_L3_64_TABLE *l3;
624          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
625          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
626                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
627                  kernel = 1;          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
628          } else          /*  fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n",
629                  vph_p = cpu->cd.alpha.vph_table0[a];              (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3);  */
630  #else          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
631          fatal("Neither alpha nor 32-bit? 3\n");          /*  fatal("  l2 = %p\n", l2);  */
632          exit(1);          l3 = l2->l3[x2];
633  #endif          /*  fatal("  l3 = %p\n", l3);  */
634  #endif  #endif
635    
636          /*  Virtual to physical address translation:  */          /*  Virtual to physical address translation:  */
# Line 551  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 641  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
641                  ok = 1;                  ok = 1;
642          }          }
643  #else  #else
644  #ifdef DYNTRANS_ALPHA          if (l3->host_load[x3] != NULL) {
645          if (vph_p->host_load[b] != NULL) {                  physaddr = l3->phys_addr[x3];
                 physaddr = vph_p->phys_addr[b];  
646                  ok = 1;                  ok = 1;
647          }          }
 #else  
         fatal("Neither alpha nor 32-bit? 4\n");  
         exit(1);  
 #endif  
648  #endif  #endif
649    
650          if (!ok) {          if (!ok) {
651                  uint64_t paddr;                  uint64_t paddr;
652                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
653                          ok = cpu->translate_address(cpu, cached_pc,                          ok = cpu->translate_v2p(
654                              &paddr, FLAG_INSTR);                              cpu, cached_pc, &paddr, FLAG_INSTR);
655                  else {                  } else {
656                          paddr = cached_pc;                          paddr = cached_pc;
657                          ok = 1;                          ok = 1;
658                  }                  }
659                  if (!ok) {                  if (!ok) {
660                          /*  fatal("TODO: instruction vaddr=>paddr translation"                          /*
661                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                           *  The PC is now set to the exception handler.
662                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */                           *  Try to find the paddr in the translation arrays,
663                             *  or if that fails, call translate_v2p for the
664                             *  exception handler.
665                             */
666                            /*  fatal("TODO: instruction vaddr=>paddr translation "
667                                "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
668                            fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
669    
670                            /*  If there was an exception, the PC has changed.
671                                Update cached_pc:  */
672                            cached_pc = cpu->pc;
673    
674    #ifdef MODE32
675                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
676                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
677                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
678                                    ok = 1;
679                            }
680    #else
681                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
682                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
683                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
684                                & mask3;
685                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
686                            l3 = l2->l3[x2];
687                            if (l3->host_load[x3] != NULL) {
688                                    paddr = l3->phys_addr[x3];
689                                    ok = 1;
690                            }
691    #endif
692    
693                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          if (!ok) {
694                              FLAG_INSTR);                                  ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
695                                        FLAG_INSTR);
696                            }
697    
698                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
699                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
700                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */                          fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
701    
702                          if (!ok) {                          if (!ok) {
703                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
# Line 589  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 705  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
705                                  exit(1);                                  exit(1);
706                          }                          }
707                  }                  }
708                  cached_pc = cpu->pc;  
 #ifdef MODE32  
                 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
 #endif  
709                  physaddr = paddr;                  physaddr = paddr;
710          }          }
711    
712            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
713    
714  #ifdef MODE32  #ifdef MODE32
715          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
716    #else
717            if (l3->host_load[x3] == NULL) {
718    #endif
719                    int q = DYNTRANS_PAGESIZE - 1;
720                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
721                      physaddr, MEM_READ);                      physaddr, MEM_READ);
722                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
723                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
724                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr);
725                  }                  }
726          }          }
 #endif  
727    
728          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
729                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
730                    fatal("[ dyntrans: resetting the translation cache ]\n");
731    #endif
732                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
733          }          }
734    
# Line 626  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 743  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
743          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
744                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
745                      + physpage_ofs);                      + physpage_ofs);
746    
747                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
748                  if (ppp->physaddr == physaddr)                  if (ppp->physaddr == physaddr)
749                          break;                          break;
750    
751                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
752                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
753          }          }
# Line 637  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 756  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
756              new "default" empty translation page.  */              new "default" empty translation page.  */
757    
758          if (ppp == NULL) {          if (ppp == NULL) {
759                  /*  fatal("CREATING page %lli (physaddr 0x%llx), table index "                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
760                      "%i\n", (long long)pagenr, (long long)physaddr,                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,
761                      (int)table_index);  */                      (int)table_index);  */
762                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
763                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
# Line 653  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 772  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
772  #ifdef MODE32  #ifdef MODE32
773          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
774                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
775    #else
776            if (l3->host_load[x3] != NULL)
777                    l3->phys_page[x3] = ppp;
778  #endif  #endif
779    
780  #ifdef DYNTRANS_ALPHA          /*
781          if (vph_p->host_load[b] != NULL)           *  If there are no translations yet on this page, then mark it
782                  vph_p->phys_page[b] = ppp;           *  as non-writable. If there are already translations, then it
783  #endif           *  should already have been marked as non-writable.
784             */
785  #ifdef MODE32          if (ppp->translations == 0) {
786          /*  Small optimization: only mark the physical page as non-writable                  cpu->invalidate_translation_caches(cpu, physaddr,
787              if it did not contain translations. (Because if it does contain                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
788              translations, it is already non-writable.)  */          }
         if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &  
             (1 << (pagenr & 31)))  
 #endif  
         cpu->invalidate_translation_caches(cpu, physaddr,  
             JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);  
789    
790          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
791    
792          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 +
793              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
794    
795          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
796              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
797              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
798  }  }
799    
800    
# Line 711  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 828  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
828          if (ppp != NULL)          if (ppp != NULL)
829                  goto have_it;                  goto have_it;
830  #else  #else
831  #ifdef DYNTRANS_ALPHA          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
832          uint32_t a, b;          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
833          int kernel = 0;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
834          struct alpha_vph_page *vph_p;          uint32_t x1, x2, x3;
835          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          struct DYNTRANS_L2_64_TABLE *l2;
836          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          struct DYNTRANS_L3_64_TABLE *l3;
837          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {  
838                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
839                  kernel = 1;          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
840          } else          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
841                  vph_p = cpu->cd.alpha.vph_table0[a];          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
842          if (vph_p != cpu->cd.alpha.vph_default_page) {          l3 = l2->l3[x2];
843                  ppp = vph_p->phys_page[b];          ppp = l3->phys_page[x3];
844                  if (ppp != NULL)          if (ppp != NULL)
845                          goto have_it;                  goto have_it;
         }  
 #else  
         fatal("X1: cached_pc=%016llx\n", (long long)cached_pc);  
         /*  Temporary, to avoid a compiler warning:  */  
         ppp = NULL;  
         fatal("Neither alpha nor 32-bit? 1\n");  
         exit(1);  
 #endif  
846  #endif  #endif
847    
848          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
849          return;          return;
850    
851          /*  Quick return path:  */          /*  Quick return path:  */
 #if defined(MODE32) || defined(DYNTRANS_ALPHA)  
852  have_it:  have_it:
853          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
854          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 +
855              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
856    
857          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
858              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
859              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
 #endif  
860  }  }
861  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
862    
863    
864    
865    #ifdef DYNTRANS_INIT_TABLES
866    
867    /*  forward declaration of to_be_translated and end_of_page:  */
868    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
869    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
870    #ifdef DYNTRANS_DUALMODE_32
871    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
872    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
873    #endif
874    
875    #ifdef DYNTRANS_DELAYSLOT
876    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
877    #ifdef DYNTRANS_DUALMODE_32
878    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
879    #endif
880    #endif
881    
882    /*
883     *  XXX_init_tables():
884     *
885     *  Initializes the default translation page (for newly allocated pages), and
886     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
887     */
888    void DYNTRANS_INIT_TABLES(struct cpu *cpu)
889    {
890    #ifndef MODE32
891            struct DYNTRANS_L2_64_TABLE *dummy_l2;
892            struct DYNTRANS_L3_64_TABLE *dummy_l3;
893            int x1, x2;
894    #endif
895            int i;
896            struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
897                struct DYNTRANS_TC_PHYSPAGE));
898    
899            if (ppp == NULL) {
900                    fprintf(stderr, "out of memory\n");
901                    exit(1);
902            }
903    
904            ppp->next_ofs = 0;
905            ppp->flags = 0;
906            ppp->translations = 0;
907            /*  ppp->physaddr is filled in by the page allocator  */
908    
909            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
910                    ppp->ics[i].f =
911    #ifdef DYNTRANS_DUALMODE_32
912                        cpu->is_32bit? instr32(to_be_translated) :
913    #endif
914                        instr(to_be_translated);
915    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
916                    ppp->ics[i].arg[0] = 0;
917    #endif
918            }
919    
920            /*  End-of-page:  */
921            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
922    #ifdef DYNTRANS_DUALMODE_32
923                cpu->is_32bit? instr32(end_of_page) :
924    #endif
925                instr(end_of_page);
926    
927    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
928            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;
929    #endif
930    
931            /*  End-of-page-2, for delay-slot architectures:  */
932    #ifdef DYNTRANS_DELAYSLOT
933            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
934    #ifdef DYNTRANS_DUALMODE_32
935                cpu->is_32bit? instr32(end_of_page2) :
936    #endif
937                instr(end_of_page2);
938    #endif
939    
940            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
941    
942    
943            /*  Prepare 64-bit virtual address translation tables:  */
944    #ifndef MODE32
945            if (cpu->is_32bit)
946                    return;
947    
948            dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
949            dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
950    
951            cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
952            cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
953    
954            for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
955                    cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
956    
957            for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
958                    dummy_l2->l3[x2] = dummy_l3;
959    #endif
960    }
961    #endif  /*  DYNTRANS_INIT_TABLES  */
962    
963    
964    
965  #ifdef DYNTRANS_INVAL_ENTRY  #ifdef DYNTRANS_INVAL_ENTRY
966  /*  /*
967   *  XXX_invalidate_tlb_entry():   *  XXX_invalidate_tlb_entry():
# Line 785  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 992  static void DYNTRANS_INVALIDATE_TLB_ENTR
992                      (int)vaddr_page);  */                      (int)vaddr_page);  */
993                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
994          } else {          } else {
995                    int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
996                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
997                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
998                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
999                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1000                    if (tlbi > 0)
1001                            cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1002                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1003          }          }
1004  #else  #else
1005          /*  2-level:  */          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1006  #ifdef DYNTRANS_ALPHA          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1007          struct alpha_vph_page *vph_p;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1008          uint32_t a, b;          uint32_t x1, x2, x3;
1009          int kernel = 0;          struct DYNTRANS_L2_64_TABLE *l2;
1010            struct DYNTRANS_L3_64_TABLE *l3;
1011          a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
1012          b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1013          if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1014                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))& mask3;
                 kernel = 1;  
         } else  
                 vph_p = cpu->cd.alpha.vph_table0[a];  
1015    
1016          if (vph_p == cpu->cd.alpha.vph_default_page) {          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1017                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n");          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1018                  exit(1);                  return;
1019          }  
1020            l3 = l2->l3[x2];
1021            if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1022                    return;
1023    
1024          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
1025                  vph_p->host_store[b] = NULL;                  l3->host_store[x3] = NULL;
1026                  return;                  return;
1027          }          }
1028          vph_p->host_load[b] = NULL;  
1029          vph_p->host_store[b] = NULL;  #ifdef BUGHUNT
1030          vph_p->phys_addr[b] = 0;  
1031          vph_p->phys_page[b] = NULL;  {
1032          vph_p->refcount --;          /*  Consistency check, for debugging:  */
1033          if (vph_p->refcount < 0) {          int x1, x1b; // x2, x3;
1034                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n");          struct DYNTRANS_L2_64_TABLE *l2;
1035            //struct DYNTRANS_L3_64_TABLE *l3;
1036    
1037            for (x1 = 0; x1 <= mask1; x1 ++) {
1038                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1039                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1040                            continue;
1041                    /*  Make sure that this l2 isn't used more than 1 time!  */
1042                    for (x1b = 0; x1b <= mask1; x1b ++)
1043                            if (x1 != x1b &&
1044                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1045                                    fatal("L2 reuse: %p\n", l2);
1046                                    exit(1);
1047                            }
1048            }
1049    }
1050    
1051    /*  Count how many pages are actually in use:  */
1052    {
1053            int n=0, i;
1054            for (i=0; i<=mask3; i++)
1055                    if (l3->vaddr_to_tlbindex[i])
1056                            n++;
1057            if (n != l3->refcount) {
1058                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1059                    exit(1);
1060            }
1061    
1062            n = 0;
1063            for (i=0; i<=mask3; i++)
1064                    if (l3->host_load[i] != NULL)
1065                            n++;
1066            if (n != l3->refcount) {
1067                    printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1068                  exit(1);                  exit(1);
1069          }          }
1070          if (vph_p->refcount == 0) {  }
1071                  vph_p->next = cpu->cd.alpha.vph_next_free_page;  #endif
1072                  cpu->cd.alpha.vph_next_free_page = vph_p;  
1073                  if (kernel)          l3->host_load[x3] = NULL;
1074                          cpu->cd.alpha.vph_table0_kernel[a] =          l3->host_store[x3] = NULL;
1075                              cpu->cd.alpha.vph_default_page;          l3->phys_addr[x3] = 0;
1076                  else          l3->phys_page[x3] = NULL;
1077                          cpu->cd.alpha.vph_table0[a] =          if (l3->vaddr_to_tlbindex[x3] != 0) {
1078                              cpu->cd.alpha.vph_default_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1079          }                      l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1080  #else   /*  !DYNTRANS_ALPHA  */                  l3->refcount --;
1081          fatal("Not yet for non-1-level, non-Alpha\n");          }
1082  #endif  /*  !DYNTRANS_ALPHA  */          l3->vaddr_to_tlbindex[x3] = 0;
1083    
1084            if (l3->refcount < 0) {
1085                    fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1086                    exit(1);
1087            }
1088    
1089            if (l3->refcount == 0) {
1090                    l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1091                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1092                    l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1093    
1094    #ifdef BUGHUNT
1095    /*  Make sure that we're placing a CLEAN page on the
1096        freelist:  */
1097    {
1098            int i;
1099            for (i=0; i<=mask3; i++)
1100                    if (l3->host_load[i] != NULL) {
1101                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1102                            exit(1);
1103                    }
1104    }
1105    #endif
1106                    l2->refcount --;
1107                    if (l2->refcount < 0) {
1108                            fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1109                            exit(1);
1110                    }
1111                    if (l2->refcount == 0) {
1112                            l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1113                            cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1114                            cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1115                                cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1116                    }
1117            }
1118  #endif  #endif
1119  }  }
1120  #endif  #endif
# Line 966  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1244  void DYNTRANS_INVALIDATE_TC_CODE(struct
1244                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1245    
1246                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
   
 #ifdef MODE32  
                 /*  If this page isn't marked as having any translations,  
                     then return immediately.  */  
                 if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]  
                     & 1 << (pagenr & 31)))  
                         return;  
                 /*  Remove the mark:  */  
                 cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=  
                     ~ (1 << (pagenr & 31));  
 #endif  
   
1247                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1248    
1249                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
# Line 990  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1256  void DYNTRANS_INVALIDATE_TC_CODE(struct
1256                          prev_ppp = ppp;                          prev_ppp = ppp;
1257                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1258                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1259    
1260                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1261                              then we're done:  */                              then we're done:  */
1262                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1263                                  break;                                  break;
1264    
1265                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1266                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1267                  }                  }
# Line 1001  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1269  void DYNTRANS_INVALIDATE_TC_CODE(struct
1269                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1270                          ppp = NULL;                          ppp = NULL;
1271    
1272  #if 1  #if 0
1273                  /*                  /*
1274                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1275                   *                   *
# Line 1023  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1291  void DYNTRANS_INVALIDATE_TC_CODE(struct
1291                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1292                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1293                   */                   */
1294                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1295                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1296                              template page?  */                                  urk Should be same type as ppp->translations */
1297                          int i;                          int i, j, n, m;
1298                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1299                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1300    
1301                            for (i=0; i<n; i++) {
1302                                    if (x & 1) {
1303                                            for (j=0; j<m; j++)
1304                                                    ppp->ics[i*m + j].f =
1305  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1306                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1307                                                        instr32(to_be_translated) :
1308  #endif  #endif
1309                                      instr(to_be_translated);                                                      instr(to_be_translated);
1310                                    }
1311    
1312                                    x >>= 1;
1313                            }
1314    
1315                            ppp->flags &= ~COMBINATIONS;
1316                            ppp->translations = 0;
1317                  }                  }
1318  #endif  #endif
1319          }          }
1320    
1321          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1322          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;          for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
              r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {  
1323                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1324                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1325                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1053  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1333  void DYNTRANS_INVALIDATE_TC_CODE(struct
1333                                  uint32_t index =                                  uint32_t index =
1334                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1335                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
                                 /*  Remove the mark:  */  
                                 index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);  
                                 cpu->cd.DYNTRANS_ARCH.phystranslation[  
                                     index >> 5] &= ~ (1 << (index & 31));  
1336  #else  #else
1337                                  /*  2-level:  */                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1338  #ifdef DYNTRANS_ALPHA                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1339                                  struct alpha_vph_page *vph_p;                                  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1340                                  uint32_t a, b;                                  uint32_t x1, x2, x3;
1341                                  int kernel = 0;                                  struct DYNTRANS_L2_64_TABLE *l2;
1342                                    struct DYNTRANS_L3_64_TABLE *l3;
1343                                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT)  
1344                                      & (ALPHA_LEVEL0 - 1);                                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1345                                  b = (vaddr_page >> ALPHA_LEVEL1_SHIFT)                                  x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1346                                      & (ALPHA_LEVEL1 - 1);                                      DYNTRANS_L2N)) & mask2;
1347                                  if ((vaddr_page >> ALPHA_TOPSHIFT) ==                                  x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1348                                      ALPHA_TOP_KERNEL) {                                      DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1349                                          vph_p = cpu->cd.alpha.                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1350                                              vph_table0_kernel[a];                                  l3 = l2->l3[x2];
1351                                          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  */  
                                 fatal("Not yet for non-1-level, non-Alpha\n");  
 #endif  /*  !DYNTRANS_ALPHA  */  
1352  #endif  #endif
1353                          }                          }
1354                  }                  }
# Line 1100  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1370  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1370  #ifndef MODE32  #ifndef MODE32
1371          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1372  #endif  #endif
1373          int found, r, lowest_index, start, end, useraccess = 0;          int found, r, lowest_index, useraccess = 0;
1374    
 #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  
1375  #ifdef MODE32  #ifdef MODE32
1376          uint32_t index;          uint32_t index;
1377          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
# Line 1118  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1380  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1380              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1381              (int)paddr_page);  */              (int)paddr_page);  */
1382  #else   /*  !MODE32  */  #else   /*  !MODE32  */
1383          fatal("Neither 32-bit nor Alpha? 2\n");          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1384          exit(1);          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1385  #endif          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1386            uint32_t x1, x2, x3;
1387            struct DYNTRANS_L2_64_TABLE *l2;
1388            struct DYNTRANS_L3_64_TABLE *l3;
1389    
1390            /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1391                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1392                (uint64_t)paddr_page);  */
1393  #endif  #endif
1394    
1395            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1396            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1397    
1398          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1399                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1400                  useraccess = 1;                  useraccess = 1;
1401          }          }
1402    
         start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  
 #if 1  
         /*  Half of the TLB used for data, half for code:  */  
         if (writeflag & TLB_CODE) {  
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
 #endif  
   
1403          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1404          lowest_index = start;          lowest_index = 0;
1405    
1406  #ifdef MODE32  #ifdef MODE32
1407          /*          /*
# Line 1156  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1416  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1416              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1417          if (found < 0) {          if (found < 0) {
1418                  static unsigned int x = 0;                  static unsigned int x = 0;
1419                  lowest_index = (x % (end-start)) + start;                  lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
                 x ++;  
1420          }          }
1421  #else  #else
1422          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1423          found = -1;          found = -1;
1424          for (r=start; r<end; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1425                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1426                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
1427                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 1201  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1460  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1460  #endif  #endif
1461    
1462                  /*  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  
1463  #ifdef MODE32  #ifdef MODE32
1464                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1465                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
# Line 1250  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1473  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1473                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1474                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1475  #endif  #endif
1476  #endif  /*  32  */  #else   /* !MODE32  */
1477  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1478                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1479                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1480                        & mask3;
1481    
1482                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1483                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1484                            if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1485                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1486                                        cpu->cd.DYNTRANS_ARCH.next_free_l2;
1487                                    cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1488                            } else {
1489                                    int i;
1490                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1491                                        malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1492                                    l2->refcount = 0;
1493                                    for (i=0; i<(1 << DYNTRANS_L2N); i++)
1494                                            l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1495                                                l3_64_dummy;
1496                            }
1497                            if (l2->refcount != 0) {
1498                                    fatal("Huh? l2 Refcount problem.\n");
1499                                    exit(1);
1500                            }
1501                    }
1502                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1503                            fatal("INTERNAL ERROR L2 reuse\n");
1504                            exit(1);
1505                    }
1506                    l3 = l2->l3[x2];
1507                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1508                            if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1509                                    l3 = l2->l3[x2] =
1510                                        cpu->cd.DYNTRANS_ARCH.next_free_l3;
1511                                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1512                            } else {
1513                                    l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1514                                        struct DYNTRANS_L3_64_TABLE));
1515                            }
1516                            if (l3->refcount != 0) {
1517                                    fatal("Huh? l3 Refcount problem.\n");
1518                                    exit(1);
1519                            }
1520                            l2->refcount ++;
1521                    }
1522                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1523                            fatal("INTERNAL ERROR L3 reuse\n");
1524                            exit(1);
1525                    }
1526    
1527                    l3->host_load[x3] = host_page;
1528                    l3->host_store[x3] = writeflag? host_page : NULL;
1529                    l3->phys_addr[x3] = paddr_page;
1530                    l3->phys_page[x3] = NULL;
1531                    l3->vaddr_to_tlbindex[x3] = r + 1;
1532                    l3->refcount ++;
1533    
1534    #ifdef BUGHUNT
1535    /*  Count how many pages are actually in use:  */
1536    {
1537            int n=0, i;
1538            for (i=0; i<=mask3; i++)
1539                    if (l3->vaddr_to_tlbindex[i])
1540                            n++;
1541            if (n != l3->refcount) {
1542                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1543                    exit(1);
1544            }
1545    
1546            n = 0;
1547            for (i=0; i<=mask3; i++)
1548                    if (l3->host_load[i] != NULL)
1549                            n++;
1550            if (n != l3->refcount) {
1551                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1552                    exit(1);
1553            }
1554    }
1555    #endif
1556    
1557    #endif  /* !MODE32  */
1558          } else {          } else {
1559                  /*                  /*
1560                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
# Line 1267  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1570  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1570                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1571                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
1572                          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 & MEM_WRITE)  
                                 vph_p->host_store[b] = host_page;  
                         if (writeflag & MEM_DOWNGRADE)  
                                 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  
1573  #ifdef MODE32  #ifdef MODE32
1574                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1575                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
# Line 1310  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1592  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1592                              writeflag? host_page : NULL;                              writeflag? host_page : NULL;
1593                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1594                  }                  }
1595  #endif  /*  32  */  #else   /*  !MODE32  */
1596  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1597                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1598                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1599                        & mask3;
1600                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1601                    l3 = l2->l3[x2];
1602                    if (l3->phys_addr[x3] == paddr_page) {
1603                            if (writeflag & MEM_WRITE)
1604                                    l3->host_store[x3] = host_page;
1605                            if (writeflag & MEM_DOWNGRADE)
1606                                    l3->host_store[x3] = NULL;
1607                    } else {
1608                            /*  Change the entire physical/host mapping:  */
1609    printf("HOST LOAD 2 set to %p\n", host_page);
1610                            l3->host_load[x3] = host_page;
1611                            l3->host_store[x3] = writeflag? host_page : NULL;
1612                            l3->phys_addr[x3] = paddr_page;
1613                    }
1614    
1615    #ifdef BUGHUNT
1616    /*  Count how many pages are actually in use:  */
1617    {
1618            int n=0, i;
1619            for (i=0; i<=mask3; i++)
1620                    if (l3->vaddr_to_tlbindex[i])
1621                            n++;
1622            if (n != l3->refcount) {
1623                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1624                    exit(1);
1625            }
1626    
1627            n = 0;
1628            for (i=0; i<=mask3; i++)
1629                    if (l3->host_load[i] != NULL)
1630                            n++;
1631            if (n != l3->refcount) {
1632                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1633                    printf("Entry r = %i\n", r);
1634                    printf("Valid = %i\n",
1635    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1636                    exit(1);
1637            }
1638    }
1639    #endif
1640    
1641    #endif  /*  !MODE32  */
1642          }          }
1643  }  }
1644  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */
# Line 1325  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1652  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1652           *  Check for breakpoints.           *  Check for breakpoints.
1653           */           */
1654          if (!single_step_breakpoint) {          if (!single_step_breakpoint) {
1655  #ifdef MODE32                  MODE_uint_t curpc = cpu->pc;
                 uint32_t curpc = cpu->pc;  
 #else  
                 uint64_t curpc = cpu->pc;  
 #endif  
1656                  int i;                  int i;
1657                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->n_breakpoints; i++)
1658                          if (curpc ==                          if (curpc == (MODE_uint_t)
 #ifdef MODE32  
                             (uint32_t)  
 #endif  
1659                              cpu->machine->breakpoint_addr[i]) {                              cpu->machine->breakpoint_addr[i]) {
1660                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1661                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1662                                          quiet_mode = 0;                                          quiet_mode = 0;
1663                                          DISASSEMBLE(cpu, ib, 1, 0, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1664                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1665                                  }                                  }
1666                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1667                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1668                                      (long long)cpu->pc);                                      (uint64_t)cpu->pc);
1669  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1670                                  if (cpu->cd.DYNTRANS_ARCH.delay_slot !=                                  if (cpu->delay_slot != NOT_DELAYED)
                                     NOT_DELAYED)  
1671                                          fatal("ERROR! Breakpoint in a delay"                                          fatal("ERROR! Breakpoint in a delay"
1672                                              " slot! Not yet supported.\n");                                              " slot! Not yet supported.\n");
1673  #endif  #endif
1674                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1675                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1676                                  goto stop_running_translated;                                  goto stop_running_translated;
1677                          }                          }
1678          }          }
# Line 1365  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1684  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1684    
1685  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1686          /*          /*
1687           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1688           *  Mark the page as containing a translation.           *  the page as containing a translation at this part of the page.
          *  
          *  (Special case for 32-bit mode: set the corresponding bit in the  
          *  phystranslation[] array.)  
1689           */           */
 #ifdef MODE32  
         if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {  
                 uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);  
                 cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=  
                     (1 << (index & 31));  
         }  
 #endif  
         cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;  
   
   
 #ifdef DYNTRANS_BACKEND  
         /*  
          *  "Empty"/simple native dyntrans backend stuff:  
          *  
          *  1) If no translation is currently being done, but the translated  
          *     instruction was simple enough, then let's start making a new  
          *     native translation block.  
          *  
          *  2) If a native translation block is currently being constructed,  
          *     but this instruction wasn't simple enough, then end the block  
          *     (without including this instruction).  
          *  
          *  3) If a native translation block is currently being constructed,  
          *     and this is a simple instruction, then add it.  
          */  
         if (simple && cpu->translation_context.p == NULL &&  
             dyntrans_backend_enable) {  
                 size_t s = 0;  
   
                 if (cpu->translation_context.translation_buffer == NULL) {  
                         cpu->translation_context.translation_buffer =  
                             zeroed_alloc(DTB_TRANSLATION_SIZE_MAX +  
                             DTB_TRANSLATION_SIZE_MARGIN);  
                 }  
1690    
1691                  cpu->translation_context.p =          /*  Make sure cur_physpage is in synch:  */
1692                      cpu->translation_context.translation_buffer;          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1693                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
                 cpu->translation_context.ic_page =  
                     cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
                 cpu->translation_context.start_instr_call_index =  
                     ((size_t)ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)  
                     / (sizeof(*ic));  
   
                 dtb_function_prologue(&cpu->translation_context, &s);  
                 cpu->translation_context.p += s;  
                 cpu->translation_context.n_simple = 0;  
         }  
   
         /*  If this is not a continuation of a simple translation, then  
             stop now!  */  
         if (cpu->translation_context.ic_page != cpu->cd.DYNTRANS_ARCH.  
             cur_ic_page || ic != &cpu->cd.DYNTRANS_ARCH.cur_ic_page[  
             cpu->translation_context.start_instr_call_index +  
             cpu->translation_context.n_simple])  
                 simple = 0;  
   
         if (cpu->translation_context.p != NULL && !simple) {  
                 size_t s = 0, total;  
   
                 if (cpu->translation_context.n_simple > 1) {  
                         dtb_generate_ptr_inc(cpu, &cpu->translation_context,  
                             &s, &cpu->cd.DYNTRANS_ARCH.next_ic,  
                             (cpu->translation_context.n_simple - 1) *  
                             sizeof(*(cpu->cd.DYNTRANS_ARCH.next_ic)));  
                         cpu->translation_context.p += s;  
                 }  
   
                 dtb_function_epilogue(&cpu->translation_context, &s);  
                 cpu->translation_context.p += s;  
1694    
1695                  cpu_dtb_do_fixups(cpu);          {
1696  #if 0                  int x = addr & (DYNTRANS_PAGESIZE - 1);
1697  {                  int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1698  int i;                      sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1699  unsigned char *addr = cpu->translation_context.translation_buffer;                  x /= addr_per_translation_range;
 printf("index = %i\n", cpu->translation_context.start_instr_call_index);  
 quiet_mode = 0;  
 for (i=0; i<4*32; i+=4)  
         alpha_cpu_disassemble_instr(cpu, (unsigned char *)addr + i,  
         0, i, 0);  
 }  
 #endif  
                 total = (size_t)cpu->translation_context.p -  
                     (size_t)cpu->translation_context.translation_buffer;  
1700    
1701                  /*  Copy the translated block to the translation cache:  */                  cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
                 /*  Align first:  */  
                 cpu->translation_cache_cur_ofs --;  
                 cpu->translation_cache_cur_ofs |= 31;  
                 cpu->translation_cache_cur_ofs ++;  
   
                 memcpy(cpu->translation_cache + cpu->translation_cache_cur_ofs,  
                     cpu->translation_context.translation_buffer, total);  
   
                 /*  Set the ic pointer:  */  
                 ((struct DYNTRANS_IC *)cpu->translation_context.ic_page)  
                     [cpu->translation_context.start_instr_call_index].f =  
                     (void *)  
                     (cpu->translation_cache + cpu->translation_cache_cur_ofs);  
   
                 /*  Align cur_ofs afterwards as well, just to be safe.  */  
                 cpu->translation_cache_cur_ofs += total;  
                 cpu->translation_cache_cur_ofs --;  
                 cpu->translation_cache_cur_ofs |= 31;  
                 cpu->translation_cache_cur_ofs ++;  
   
                 /*  Set the "combined instruction" flag for this page:  */  
                 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)  
                     cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
                 cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= COMBINATIONS;  
   
                 dtb_host_cacheinvalidate(0,0); /* p , size ... ); */  
   
                 cpu->translation_context.p = NULL;  
         }  
         if (cpu->translation_context.p != NULL) {  
                 size_t s = 0;  
                 dtb_generate_fcall(cpu, &cpu->translation_context,  
                     &s, (size_t)ic->f, (size_t)ic);  
                 cpu->translation_context.p += s;  
                 cpu->translation_context.n_simple ++;  
1702          }          }
 #endif  /*  DYNTRANS_BACKEND  */  
   
1703    
1704          /*          /*
1705           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
1706           *  be converted into a single function call.           *  be converted into a single function call.
1707           *           *
1708           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1709           *  instruction combination.           *  instruction combination. For architectures with delay slots,
1710             *  we also ignore combinations if the delay slot is across a page
1711             *  boundary.
1712           */           */
1713          if (!single_step && !cpu->machine->instruction_trace) {          if (!single_step && !cpu->machine->instruction_trace
1714    #ifdef DYNTRANS_DELAYSLOT
1715                && !in_crosspage_delayslot
1716    #endif
1717                ) {
1718                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1719                      cpu->machine->speed_tricks)                      cpu->machine->allow_instruction_combinations)
1720                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1721                              addr & (DYNTRANS_PAGESIZE - 1));                              addr & (DYNTRANS_PAGESIZE - 1));
1722                  cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          }
1723    
1724            cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1725    
1726            /*  An additional check, to catch some bugs:  */
1727            if (ic->f == (
1728    #ifdef DYNTRANS_DUALMODE_32
1729                cpu->is_32bit? instr32(to_be_translated) :
1730    #endif
1731                instr(to_be_translated))) {
1732                    fatal("INTERNAL ERROR: ic->f not set!\n");
1733                    goto bad;
1734            }
1735            if (ic->f == NULL) {
1736                    fatal("INTERNAL ERROR: ic->f == NULL!\n");
1737                    goto bad;
1738          }          }
1739    
1740          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1741          if (single_step_breakpoint) {          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1742    #ifdef DYNTRANS_DELAYSLOT
1743                || in_crosspage_delayslot
1744    #endif
1745                ) {
1746                  /*                  /*
1747                   *  Special case when single-stepping: Execute the translated                   *  Special case when single-stepping: Execute the translated
1748                   *  instruction, but then replace it with a "to be translated"                   *  instruction, but then replace it with a "to be translated"
1749                   *  directly afterwards.                   *  directly afterwards.
1750                   */                   */
1751                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
1752    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1753                    cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1754    #endif
1755                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1756                  ic->f =                  ic->f =
1757  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1758                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
1759  #endif  #endif
1760                      instr(to_be_translated);                      instr(to_be_translated);
1761          } else  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1762                    ic->arg[0] = 0;
1763    #endif
1764            } else {
1765    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1766                    cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1767    
1768                    /*  Additional check, for variable length ISAs:  */
1769                    if (ic->arg[0] == 0) {
1770                            fatal("INTERNAL ERROR: instr len = 0!\n");
1771                            goto bad;
1772                    }
1773    #endif
1774    
1775                    /*  Finally finally :-), execute the instruction:  */
1776                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1777            }
1778    
1779          return;          return;
1780    
# Line 1541  bad:   /* Line 1788  bad:   /*
1788    
1789          if (cpu->machine->instruction_trace)          if (cpu->machine->instruction_trace)
1790  #ifdef MODE32  #ifdef MODE32
1791                  fatal(" at 0x%x\n", (int)cpu->pc);                  fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1792  #else  #else
1793                  fatal(" at 0x%llx\n", (long long)cpu->pc);                  fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1794  #endif  #endif
1795          else {          else {
1796                  fatal(":\n");                  fatal(":\n");
1797                  DISASSEMBLE(cpu, ib, 1, 0, 0);                  DISASSEMBLE(cpu, ib, 1, 0);
1798          }          }
1799    
1800          cpu->running = 0;          cpu->running = 0;

Legend:
Removed from v.22  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26