/[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 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.99 2006/06/23 20:43:44 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.165 2007/06/15 21:43:53 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);
47          if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
48            if (cpu->machine->statistics_file == NULL) {
49                    fatal("statistics gathering with no filename set is"
50                        " meaningless\n");
51                  return;                  return;
52            }
53    
54  #if 0          /*  low_pc must be within the page!  */
55          /*  Use the physical address:  */          if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
56          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)                  return;
             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  
57    
58          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<          buf[0] = '\0';
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
59    
60          /*          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
61           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
62           */                          strlcat(buf, " ", sizeof(buf));
63  a &= 0x03ffffff;  
64  {                  switch (ch) {
65          static long long *array = NULL;                  case 'i':
66          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
67          static int n = 0;                              "%p", (void *)ic->f);
68          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
69          if (array == NULL)                  case 'p':
70                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
71          if (array_16kpage_in_use == NULL)                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
72                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
73          a &= (16384*1024-1);                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
74          array[a] ++;                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
75          array_16kpage_in_use[a / 16384] = 1;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
76          n++;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77          if ((n & 0x3fffffff) == 0) {                          if (cpu->is_32bit)
78                  FILE *f = fopen("statistics.out", "w");                                  snprintf(buf + strlen(buf), sizeof(buf),
79                  int i, j;                                      "0x%08"PRIx32, (uint32_t)a);
80                  printf("Saving statistics... "); fflush(stdout);                          else
81                  for (i=0; i<1024; i++)                                  snprintf(buf + strlen(buf), sizeof(buf),
82                          if (array_16kpage_in_use[i]) {                                      "0x%016"PRIx64, (uint64_t)a);
83                                  for (j=0; j<16384; j++)                          break;
84                                          if (array[i*16384 + j] > 0)                  case 'v':
85                                                  fprintf(f, "%lli\t"                          /*  Virtual program counter address:  */
86                                                      "0x%016"PRIx64"\n",                          a = cpu->pc;
87                                                      (uint64_t)array[i*16384+j],                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
88                                                      (uint64_t)((i*16384+j) <<                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
89                                              DYNTRANS_INSTR_ALIGNMENT_SHIFT));                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
90                          }                          if (cpu->is_32bit)
91                  fclose(f);                                  snprintf(buf + strlen(buf), sizeof(buf),
92                  printf("n=0x%08x\n", n);                                      "0x%08"PRIx32, (uint32_t)a);
93                            else
94                                    snprintf(buf + strlen(buf), sizeof(buf),
95                                        "0x%016"PRIx64, (uint64_t)a);
96                            break;
97                    }
98                    i++;
99          }          }
100    
101            fprintf(cpu->machine->statistics_file, "%s\n", buf);
102  }  }
 }  
 #endif  /*  PC statistics  */  
103    
104    
105  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
106    
107    
108  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  #if 1
 #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  
                         cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \  
                         ic->f(cpu, ic);  
 #else  
109    
110  /*  The normal instruction execution core:  */  /*  The normal instruction execution core:  */
111  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
112    
113    #else
114    
115  /*  For heavy debugging:  */  /*  For heavy debugging:  */
116  /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
117                  {       \                  {       \
118                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
119                              (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \                              (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
# Line 136  a &= 0x03ffffff; Line 122  a &= 0x03ffffff;
122                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
123                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
124                  } \                  } \
125                  ic->f(cpu, ic);  */                  ic->f(cpu, ic);
126    
127    #endif
128    
129  /*  static long long nr_of_I_calls = 0;  */  /*  static long long nr_of_I_calls = 0;  */
130    
# Line 169  a &= 0x03ffffff; Line 157  a &= 0x03ffffff;
157          }                                               \          }                                               \
158          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
159  */  */
160  #endif  #endif  /*  STATIC STUFF  */
161    
162    
163    
164    #ifdef  DYNTRANS_RUN_INSTR
165  /*  /*
166   *  XXX_cpu_run_instr():   *  XXX_run_instr():
167   *   *
168   *  Execute one or more instructions on a specific CPU, using dyntrans.   *  Execute one or more instructions on a specific CPU, using dyntrans.
169     *  (For dualmode archs, this function is included twice.)
170   *   *
171   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
172   *  0 if no instructions were executed.   *  0 if no instructions were executed.
173   */   */
174  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
175  {  {
176          /*          MODE_uint_t cached_pc;
          *  TODO:  Statistics stuff!  
          */  
         int show_opcode_statistics = 0;  
   
 #ifdef DYNTRANS_DUALMODE_32  
         uint64_t cached_pc;  
 #else  
         uint32_t cached_pc;  
 #endif  
177          int low_pc, n_instrs;          int low_pc, n_instrs;
178    
179            /*  Ugly... fix this some day.  */
180  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
181          if (cpu->is_32bit)  #ifdef MODE32
182                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
183          else  #else
184            DYNTRANS_PC_TO_POINTERS(cpu);
185  #endif  #endif
186    #else
187          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
188    #endif
189    
190          /*          /*
191           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
# Line 238  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 224  int DYNTRANS_CPU_RUN_INSTR(struct emul *
224  #endif  #endif
225  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
226          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) {
227                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
228                            ppc_exception(cpu, PPC_EXCEPTION_DEC);
229                  cpu->cd.ppc.dec_intr_pending = 0;                  cpu->cd.ppc.dec_intr_pending = 0;
230          }          }
231          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
232                  ppc_exception(cpu, PPC_EXCEPTION_EI);                  ppc_exception(cpu, PPC_EXCEPTION_EI);
233  #endif  #endif
234    #ifdef DYNTRANS_SH
235            if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
236                && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
237                < cpu->cd.sh.int_level)
238                    sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0);
239    #endif
240    
241          cached_pc = cpu->pc;          cached_pc = cpu->pc;
242    
243          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
         cpu->running_translated = 1;  
244    
245          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
246              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
# Line 264  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 256  int DYNTRANS_CPU_RUN_INSTR(struct emul *
256                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
257                  }                  }
258                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
259  #ifdef DYNTRANS_X86                          /*  TODO/Note: This must be large enough to hold
260                          unsigned char instr[17];                              any instruction for any ISA:  */
261                          cpu->cd.x86.cursegment = X86_S_CS;                          unsigned char instr[1 <<
262                          cpu->cd.x86.seg_override = 0;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT];
 #else  
 #ifdef DYNTRANS_M68K  
                         unsigned char instr[16];        /*  TODO: 16?  */  
 #else  
                         unsigned char instr[4];         /*  General case...  */  
 #endif  
 #endif  
   
263                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
264                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
265                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
266                                      "the instruction\n");                                      "the instruction\n");
267                          } else {                          } else {
268                                  cpu_disassemble_instr(cpu->machine, cpu,  #ifdef DYNTRANS_DELAYSLOT
269                                      instr, 1, 0);                                  int len =
270    #endif
271                                        cpu_disassemble_instr(
272                                        cpu->machine, cpu, instr, 1, 0);
273  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
274                                  /*  Show the instruction in the delay slot,                                  /*  Show the instruction in the delay slot,
275                                      if any:  */                                      if any:  */
# Line 293  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 280  int DYNTRANS_CPU_RUN_INSTR(struct emul *
280                                      instr)) {                                      instr)) {
281                                          int saved_delayslot = cpu->delay_slot;                                          int saved_delayslot = cpu->delay_slot;
282                                          cpu->memory_rw(cpu, cpu->mem, cached_pc                                          cpu->memory_rw(cpu, cpu->mem, cached_pc
283                                              + sizeof(instr), &instr[0],                                              + len, &instr[0],
284                                              sizeof(instr), MEM_READ,                                              sizeof(instr), MEM_READ,
285                                              CACHE_INSTRUCTION);                                              CACHE_INSTRUCTION);
286                                          cpu->delay_slot = DELAYED;                                          cpu->delay_slot = DELAYED;
287                                          cpu->pc += sizeof(instr);                                          cpu->pc += len;
288                                          cpu_disassemble_instr(cpu->machine,                                          cpu_disassemble_instr(cpu->machine,
289                                              cpu, instr, 1, 0);                                              cpu, instr, 1, 0);
290                                          cpu->delay_slot = saved_delayslot;                                          cpu->delay_slot = saved_delayslot;
291                                          cpu->pc -= sizeof(instr);                                          cpu->pc -= len;
292                                  }                                  }
293  #endif  #endif
294                          }                          }
295                  }                  }
296    
297                  /*  When single-stepping, multiple instruction calls cannot                  if (cpu->machine->statistics_enabled)
                     be combined into one. This clears all translations:  */  
                 if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {  
                         int i;  
                         for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {  
                                 cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =  
 #ifdef DYNTRANS_DUALMODE_32  
                                     cpu->is_32bit?  
                                         instr32(to_be_translated) :  
 #endif  
                                         instr(to_be_translated);  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                                 cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].  
                                     arg[0] = 0;  
 #endif  
                         }  
                         fatal("[ Note: The translation of physical page 0x%"  
                             PRIx64" contained combinations of instructions; "  
                             "these are now flushed because we are single-"  
                             "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.  
                             cur_physpage->physaddr);  
                         cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=  
                             ~(COMBINATIONS | TRANSLATIONS);  
                 }  
   
                 if (show_opcode_statistics)  
298                          S;                          S;
299    
300                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
301                  I;                  I;
302    
303                  n_instrs = 1;                  n_instrs = 1;
304          } else if (cpu->machine->cycle_accurate) {          } else if (cpu->machine->statistics_enabled) {
                 /*  Executing multiple instructions, and call devices'  
                     tick functions:  */  
                 n_instrs = 0;  
                 for (;;) {  
                         struct DYNTRANS_IC *ic;  
 /*  TODO: continue here  */  
 int64_t cycles = cpu->cd.avr.extra_cycles;  
                         I;  
                         n_instrs += 1;  
 cycles = cpu->cd.avr.extra_cycles - cycles + 1;  
 /*  The instruction took 'cycles' cycles.  */  
 /* printf("A\n"); */  
 while (cycles-- > 0)  
         cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);  
 /* printf("B\n"); */  
   
                         if (!cpu->running_translated ||  
                             n_instrs + cpu->n_translated_instrs >=  
                             N_SAFE_DYNTRANS_LIMIT / 2)  
                                 break;  
                 }  
         } else if (show_opcode_statistics) {  
305                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
306                  n_instrs = 0;                  n_instrs = 0;
307                  for (;;) {                  for (;;) {
# Line 374  while (cycles-- > 0) Line 314  while (cycles-- > 0)
314    
315                          n_instrs += 24;                          n_instrs += 24;
316    
317                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
318                              n_instrs + cpu->n_translated_instrs >=                              N_SAFE_DYNTRANS_LIMIT)
                             N_SAFE_DYNTRANS_LIMIT / 2)  
319                                  break;                                  break;
320                  }                  }
321          } else {          } else {
322                  /*  Execute multiple instructions:  */                  /*
323                     *  Execute multiple instructions:
324                     *
325                     *  (This is the core dyntrans loop.)
326                     */
327                  n_instrs = 0;                  n_instrs = 0;
328                    cpu->sampling = 1;
329    
330                  for (;;) {                  for (;;) {
331                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
332    
# Line 393  while (cycles-- > 0) Line 338  while (cycles-- > 0)
338    
339                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
340    
341                          n_instrs += 60;                          I; I; I; I; I;   I; I; I; I; I;
342                            I; I; I; I; I;   I; I; I; I; I;
343                            I; I; I; I; I;   I; I; I; I; I;
344                            I; I; I; I; I;   I; I; I; I; I;
345                            I; I; I; I; I;   I; I; I; I; I;
346    
347                            I; I; I; I; I;   I; I; I; I; I;
348    
349                          if (!cpu->running_translated ||                          cpu->n_translated_instrs += 120;
350                              n_instrs + cpu->n_translated_instrs >=                          if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)
                             N_SAFE_DYNTRANS_LIMIT / 2)  
351                                  break;                                  break;
352                  }                  }
353    
354                    cpu->sampling = 0;
355          }          }
356    
357          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 436  while (cycles-- > 0) Line 388  while (cycles-- > 0)
388                      (int32_t) (old + n_instrs);                      (int32_t) (old + n_instrs);
389                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
390                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
391                  if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)  
392                          cpu_interrupt(cpu, 7);                  if (cpu->cd.mips.compare_register_set) {
393    #if 1
394    /*  Not yet.  TODO  */
395                            if (cpu->machine->emulated_hz > 0) {
396                                    if (cpu->cd.mips.compare_interrupts_pending > 0)
397                                            INTERRUPT_ASSERT(
398                                                cpu->cd.mips.irq_compare);
399                            } else
400    #endif
401                            {
402                                    if (diff1 > 0 && diff2 <= 0)
403                                            INTERRUPT_ASSERT(
404                                                cpu->cd.mips.irq_compare);
405                            }
406                    }
407          }          }
408  #endif  #endif
409  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
# Line 455  while (cycles-- > 0) Line 421  while (cycles-- > 0)
421          }          }
422  #endif  #endif
423    
424            cpu->ninstrs += n_instrs;
425    
426            /*
427             *  Check if there are enough samples to decide whether or not to
428             *  perform native code generation:
429             */
430            if (cpu->sampling_curindex == N_PADDR_SAMPLES) {
431                    /*  TODO: Check against known blocks, etc.  */
432    
433                    cpu->sampling_curindex = 0;
434            }
435    
436          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
437          return n_instrs;          return n_instrs;
438  }  }
439  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
440    
441    
442    
# Line 472  while (cycles-- > 0) Line 450  while (cycles-- > 0)
450   */   */
451  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)
452  {  {
453            int show_symbolic_function_name = 1;
454          char strbuf[50];          char strbuf[50];
455          char *symbol;          char *symbol;
456          uint64_t ot;          uint64_t ot;
# Line 479  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 458  void DYNTRANS_FUNCTION_TRACE(struct cpu
458  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
459              6              6
460  #else  #else
461  #ifdef DYNTRANS_SH  #if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K)
462              8              8   /*  Both for 32-bit and 64-bit SuperH, and M88K  */
463  #else  #else
464              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
465  #endif  #endif
# Line 492  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 471  void DYNTRANS_FUNCTION_TRACE(struct cpu
471                  n_args_to_print = n_args;                  n_args_to_print = n_args;
472          }          }
473    
474    #ifdef DYNTRANS_M88K
475            /*  Special hack for M88K userspace:  */
476            if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
477                    show_symbolic_function_name = 0;
478    #endif
479    
480          /*          /*
481           *  TODO: The type of each argument should be taken from the symbol           *  TODO: The type of each argument should be taken from the symbol
482           *  table, in some way.           *  table, in some way.
# Line 504  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 489  void DYNTRANS_FUNCTION_TRACE(struct cpu
489           *  than were passed in register.           *  than were passed in register.
490           */           */
491          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
492                  int64_t d;                  int64_t d = cpu->cd.DYNTRANS_ARCH.
 #ifdef DYNTRANS_X86  
                 d = 0;          /*  TODO  */  
 #else  
                 /*  Args in registers:  */  
                 d = cpu->cd.DYNTRANS_ARCH.  
493  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
494                      r[ALPHA_A0                      r[ALPHA_A0
495  #endif  #endif
# Line 521  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 501  void DYNTRANS_FUNCTION_TRACE(struct cpu
501                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
502                      r[24                      r[24
503  #endif  #endif
 #ifdef DYNTRANS_HPPA  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_I960  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_IA64  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_M68K  
                     d[0         /*  TODO  */  
 #endif  
504  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
505                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
506  #endif  #endif
507    #ifdef DYNTRANS_M88K
508                        r[2         /*  r2..r9  */
509    #endif
510  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
511                      gpr[3                      gpr[3
512  #endif  #endif
513  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
514                      r[2                      r[4         /*  NetBSD seems to use 4? But 2 seems
515                                            to be used by other code? TODO  */
516  #endif  #endif
517  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
518                      r[24                      r[8         /*  o0..o5  */
519  #endif  #endif
520                      + x];                      + x];
521  #endif  
522                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
523    
524                  if (d > -256 && d < 256)                  if (d > -256 && d < 256)
# Line 554  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 526  void DYNTRANS_FUNCTION_TRACE(struct cpu
526                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))
527                          fatal("\"%s\"", memory_conv_to_string(cpu,                          fatal("\"%s\"", memory_conv_to_string(cpu,
528                              cpu->mem, d, strbuf, sizeof(strbuf)));                              cpu->mem, d, strbuf, sizeof(strbuf)));
529                  else if (symbol != NULL && ot == 0)                  else if (symbol != NULL && ot == 0 &&
530                        show_symbolic_function_name)
531                          fatal("&%s", symbol);                          fatal("&%s", symbol);
532                  else {                  else {
533                          if (cpu->is_32bit)                          if (cpu->is_32bit)
# Line 574  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 547  void DYNTRANS_FUNCTION_TRACE(struct cpu
547    
548    
549    
550  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TIMER_SAMPLE_TICK
551    /*
552     *  XXX_timer_sample_tick():
553     *
554     *  Gathers statistics about which translation blocks are being executed.
555     *  This can then be used to calculate if it is worth the effort to perform
556     *  native code generation (which is assumed to have a large overhead, but
557     *  will result in faster code).
558     */
559    void DYNTRANS_TIMER_SAMPLE_TICK(struct timer *timer, void *extra)
560    {
561            struct cpu *cpu = extra;
562            struct DYNTRANS_IC *next_ic;
563            size_t low_pc;
564            uint64_t paddr;
565    
566  /*  forward declaration of to_be_translated and end_of_page:  */          /*
567  static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);           *  Don't sample if:
568  static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);           *
569  #ifdef DYNTRANS_DUALMODE_32           *  1)  Sampling is not enabled. It should only be enabled during
570  static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);           *      the core dyntrans loop.
571  static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);           *  2)  Enough samples have already been gathered.
572  #endif           */
573    
574  #ifdef DYNTRANS_DELAYSLOT          if (!cpu->sampling || cpu->sampling_curindex == N_PADDR_SAMPLES)
575  static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);                  return;
576  #ifdef DYNTRANS_DUALMODE_32  
577  static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);          /*  Get the physical address of the program counter:  */
578  #endif  
579  #endif          next_ic = cpu->cd.DYNTRANS_ARCH.next_ic;
580            low_pc = ((size_t)next_ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)
581                / sizeof(struct DYNTRANS_IC);
582    
583            /*  Not possible to represent as a physical address? Then abort.  */
584            if (low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
585                    return;
586    
587            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
588                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
589            paddr = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
590            paddr &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
591                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
592            paddr += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
593    
594            /*  ... and finally add the sample to the sampling array:  */
595            cpu->sampling_paddr[cpu->sampling_curindex ++] = paddr;
596    }
597    #endif  /*  DYNTRANS_TIMER_SAMPLE_TICK  */
598    
599    
600    
601    #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
602  /*  /*
603   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
604   *   *
# Line 601  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 609  static void DYNTRANS_TC_ALLOCATE_DEFAULT
609          uint64_t physaddr)          uint64_t physaddr)
610  {  {
611          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
612    
         /*  Create the physpage header:  */  
613          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
614              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
615    
616          /*  TODO: Is this faster than copying an entire template page?  */          /*  Copy the entire template page first:  */
617          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
618                  ppp->ics[i].f =              struct DYNTRANS_TC_PHYSPAGE));
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 ppp->ics[i].arg[0] = 0;  
 #endif  
         }  
619    
620          /*  End-of-page:  */          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =  
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page) :  
 #endif  
             instr(end_of_page);  
   
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;  
 #endif  
   
         /*  End-of-page-2, for delay-slot architectures:  */  
 #ifdef DYNTRANS_DELAYSLOT  
         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  
621    
622          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
623    
624          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
625          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
626          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
627  }  }
628  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 707  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 685  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
685    
686          if (!ok) {          if (!ok) {
687                  uint64_t paddr;                  uint64_t paddr;
688                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
689                          ok = cpu->translate_address(cpu, cached_pc,                          uint64_t vaddr =
690                              &paddr, FLAG_INSTR);  #if defined(MODE32) && defined(DYNTRANS_MIPS)
691                  else {                          /*  32-bit MIPS is _sign_ extend, not zero.  */
692                                (int32_t)
693    #endif
694                                cached_pc;
695                            ok = cpu->translate_v2p(
696                                cpu, vaddr, &paddr, FLAG_INSTR);
697                    } else {
698                          paddr = cached_pc;                          paddr = cached_pc;
699                          ok = 1;                          ok = 1;
700                  }                  }
701                  if (!ok) {                  if (!ok) {
702                            /*
703                             *  The PC is now set to the exception handler.
704                             *  Try to find the paddr in the translation arrays,
705                             *  or if that fails, call translate_v2p for the
706                             *  exception handler.
707                             */
708                          /*  fatal("TODO: instruction vaddr=>paddr translation "                          /*  fatal("TODO: instruction vaddr=>paddr translation "
709                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
710                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
711    
712                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          /*  If there was an exception, the PC has changed.
713                              FLAG_INSTR);                              Update cached_pc:  */
714                            cached_pc = cpu->pc;
715    
716    #ifdef MODE32
717                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
718                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
719                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
720                                    ok = 1;
721                            }
722    #else
723                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
724                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
725                                & mask2;
726                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
727                                - DYNTRANS_L3N)) & mask3;
728                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
729                            l3 = l2->l3[x2];
730                            if (l3->host_load[x3] != NULL) {
731                                    paddr = l3->phys_addr[x3];
732                                    ok = 1;
733                            }
734    #endif
735    
736                            if (!ok) {
737                                    ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
738                                        FLAG_INSTR);
739                            }
740    
741                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
742                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
# Line 733  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 749  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
749                          }                          }
750                  }                  }
751    
                 /*  If there was an exception, the PC can have changed.  
                     Update cached_pc:  */  
                 cached_pc = cpu->pc;  
   
 #ifdef MODE32  
                 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
 #else  
                 x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;  
                 x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;  
                 x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))  
                     & mask3;  
 #endif  
   
752                  physaddr = paddr;                  physaddr = paddr;
753          }          }
754    
755            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
756    
757  #ifdef MODE32  #ifdef MODE32
758          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
759  #else  #else
760          if (l3->host_load[x3] == NULL) {          if (l3->host_load[x3] == NULL) {
761  #endif  #endif
762                    int q = DYNTRANS_PAGESIZE - 1;
763                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
764                      physaddr, MEM_READ);                      physaddr, MEM_READ);
765                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
766                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
767                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr);
 #ifndef MODE32  
                         /*  Recalculate l2 and l3, since they might have  
                             changed now:  */  
                         l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];  
                         l3 = l2->l3[x2];  
 #endif  
768                  }                  }
769          }          }
770    
771          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) {
772                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
773                    fatal("[ dyntrans: resetting the translation cache ]\n");
774    #endif
775                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
776          }          }
777    
# Line 787  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 786  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
786          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
787                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
788                      + physpage_ofs);                      + physpage_ofs);
789    
790                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
791                  if (DYNTRANS_ADDR_TO_PAGENR(ppp->physaddr) == pagenr)                  if (ppp->physaddr == physaddr)
792                          break;                          break;
793    
794                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
795                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
796          }          }
797    
798          /*  If the offset is 0 (or ppp is NULL), then we need to create a          /*
799              new "default" empty translation page.  */           *  If the offset is 0, then no translation exists yet for this
800             *  physical address. Let's create a new page, and add it first in
801             *  the chain.
802             */
803            if (physpage_ofs == 0) {
804                    uint32_t previous_first_page_in_chain;
805    
         if (ppp == NULL) {  
806                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
807                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,
808                      (int)table_index);  */                      (int)table_index);  */
809    
810                    previous_first_page_in_chain = *physpage_entryp;
811    
812                    /*  Insert the new page first in the chain:  */
813                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
814                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
815    
# Line 809  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 818  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
818    
819                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
820                      + physpage_ofs);                      + physpage_ofs);
821    
822                    /*  Point to the other pages in the same chain:  */
823                    ppp->next_ofs = previous_first_page_in_chain;
824          }          }
825    
826            /*  Here, ppp points to a valid physical page struct.  */
827    
828  #ifdef MODE32  #ifdef MODE32
829          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
830                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
# Line 819  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 833  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
833                  l3->phys_page[x3] = ppp;                  l3->phys_page[x3] = ppp;
834  #endif  #endif
835    
836  #ifdef MODE32          /*
837          /*  Small optimization: only mark the physical page as non-writable           *  If there are no translations yet on this page, then mark it
838              if it did not contain translations. (Because if it does contain           *  as non-writable. If there are already translations, then it
839              translations, it is already non-writable.)  */           *  should already have been marked as non-writable.
840          if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &           */
841              (1 << (pagenr & 31)))          if (ppp->translations == 0) {
842  #endif                  cpu->invalidate_translation_caches(cpu, physaddr,
843          cpu->invalidate_translation_caches(cpu, physaddr,                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
844              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);          }
845    
846          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
847    
# Line 904  have_it: Line 918  have_it:
918    
919    
920    
921  #ifdef DYNTRANS_INIT_64BIT_DUMMY_TABLES  #ifdef DYNTRANS_INIT_TABLES
922    
923    /*  forward declaration of to_be_translated and end_of_page:  */
924    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
925    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
926    #ifdef DYNTRANS_DUALMODE_32
927    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
928    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
929    #endif
930    
931    #ifdef DYNTRANS_DELAYSLOT
932    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
933    #ifdef DYNTRANS_DUALMODE_32
934    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
935    #endif
936    #endif
937    
938  /*  /*
939   *  XXX_init_64bit_dummy_tables():   *  XXX_init_tables():
940   *   *
941   *  Initializes 64-bit dummy tables and pointers.   *  Initializes the default translation page (for newly allocated pages), and
942     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
943   */   */
944  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(struct cpu *cpu)  void DYNTRANS_INIT_TABLES(struct cpu *cpu)
945  {  {
946    #ifndef MODE32
947          struct DYNTRANS_L2_64_TABLE *dummy_l2;          struct DYNTRANS_L2_64_TABLE *dummy_l2;
948          struct DYNTRANS_L3_64_TABLE *dummy_l3;          struct DYNTRANS_L3_64_TABLE *dummy_l3;
949          int x1, x2;          int x1, x2;
950    #endif
951            int i;
952            struct DYNTRANS_TC_PHYSPAGE *ppp;
953    
954            CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
955    
956            ppp->next_ofs = 0;
957            ppp->translations = 0;
958            /*  ppp->physaddr is filled in by the page allocator  */
959    
960            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
961                    ppp->ics[i].f =
962    #ifdef DYNTRANS_DUALMODE_32
963                        cpu->is_32bit? instr32(to_be_translated) :
964    #endif
965                        instr(to_be_translated);
966            }
967    
968            /*  End-of-page:  */
969            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
970    #ifdef DYNTRANS_DUALMODE_32
971                cpu->is_32bit? instr32(end_of_page) :
972    #endif
973                instr(end_of_page);
974    
975            /*  End-of-page-2, for delay-slot architectures:  */
976    #ifdef DYNTRANS_DELAYSLOT
977            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
978    #ifdef DYNTRANS_DUALMODE_32
979                cpu->is_32bit? instr32(end_of_page2) :
980    #endif
981                instr(end_of_page2);
982    #endif
983    
984            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
985    
986    
987            /*  Prepare 64-bit virtual address translation tables:  */
988    #ifndef MODE32
989          if (cpu->is_32bit)          if (cpu->is_32bit)
990                  return;                  return;
991    
# Line 930  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st Line 1000  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st
1000    
1001          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
1002                  dummy_l2->l3[x2] = dummy_l3;                  dummy_l2->l3[x2] = dummy_l3;
1003    #endif
1004  }  }
1005  #endif  /*  DYNTRANS_INIT_64BIT_DUMMY_TABLES  */  #endif  /*  DYNTRANS_INIT_TABLES  */
1006    
1007    
1008    
# Line 998  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1069  static void DYNTRANS_INVALIDATE_TLB_ENTR
1069                  l3->host_store[x3] = NULL;                  l3->host_store[x3] = NULL;
1070                  return;                  return;
1071          }          }
1072    
1073    #ifdef BUGHUNT
1074    
1075    {
1076            /*  Consistency check, for debugging:  */
1077            int x1, x1b; // x2, x3;
1078            struct DYNTRANS_L2_64_TABLE *l2;
1079            //struct DYNTRANS_L3_64_TABLE *l3;
1080    
1081            for (x1 = 0; x1 <= mask1; x1 ++) {
1082                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1083                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1084                            continue;
1085                    /*  Make sure that this l2 isn't used more than 1 time!  */
1086                    for (x1b = 0; x1b <= mask1; x1b ++)
1087                            if (x1 != x1b &&
1088                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1089                                    fatal("L2 reuse: %p\n", l2);
1090                                    exit(1);
1091                            }
1092            }
1093    }
1094    
1095    /*  Count how many pages are actually in use:  */
1096    {
1097            int n=0, i;
1098            for (i=0; i<=mask3; i++)
1099                    if (l3->vaddr_to_tlbindex[i])
1100                            n++;
1101            if (n != l3->refcount) {
1102                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1103                    exit(1);
1104            }
1105    
1106            n = 0;
1107            for (i=0; i<=mask3; i++)
1108                    if (l3->host_load[i] != NULL)
1109                            n++;
1110            if (n != l3->refcount) {
1111                    printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1112                    exit(1);
1113            }
1114    }
1115    #endif
1116    
1117          l3->host_load[x3] = NULL;          l3->host_load[x3] = NULL;
1118          l3->host_store[x3] = NULL;          l3->host_store[x3] = NULL;
1119          l3->phys_addr[x3] = 0;          l3->phys_addr[x3] = 0;
1120          l3->phys_page[x3] = NULL;          l3->phys_page[x3] = NULL;
1121          l3->refcount --;          if (l3->vaddr_to_tlbindex[x3] != 0) {
1122                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1123                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1124                    l3->refcount --;
1125            }
1126            l3->vaddr_to_tlbindex[x3] = 0;
1127    
1128          if (l3->refcount < 0) {          if (l3->refcount < 0) {
1129                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1130                  exit(1);                  exit(1);
1131          }          }
1132    
1133          if (l3->refcount == 0) {          if (l3->refcount == 0) {
1134                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1135                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1136                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1137    
1138    #ifdef BUGHUNT
1139    /*  Make sure that we're placing a CLEAN page on the
1140        freelist:  */
1141    {
1142            int i;
1143            for (i=0; i<=mask3; i++)
1144                    if (l3->host_load[i] != NULL) {
1145                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1146                            exit(1);
1147                    }
1148    }
1149    #endif
1150                  l2->refcount --;                  l2->refcount --;
1151                  if (l2->refcount < 0) {                  if (l2->refcount < 0) {
1152                          fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");                          fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
# Line 1153  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1288  void DYNTRANS_INVALIDATE_TC_CODE(struct
1288                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1289    
1290                  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  
   
1291                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1292    
1293                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
1294                      translation_cache)[table_index]);                      translation_cache)[table_index]);
1295                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
1296    
1297                    /*  Return immediately if there is no code translation
1298                        for this page.  */
1299                    if (physpage_ofs == 0)
1300                            return;
1301    
1302                  prev_ppp = ppp = NULL;                  prev_ppp = ppp = NULL;
1303    
1304                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
# Line 1177  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1306  void DYNTRANS_INVALIDATE_TC_CODE(struct
1306                          prev_ppp = ppp;                          prev_ppp = ppp;
1307                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1308                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1309    
1310                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1311                              then we're done:  */                              then we're done:  */
1312                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1313                                  break;                                  break;
1314    
1315                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1316                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1317                  }                  }
1318    
1319                    /*  If there is no translation, there is no need to go
1320                        on and try to remove it from the vph_tlb_entry array:  */
1321                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1322                          ppp = NULL;                          return;
1323    
1324  #if 1  #if 0
1325                  /*                  /*
1326                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1327                   *                   *
# Line 1210  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1343  void DYNTRANS_INVALIDATE_TC_CODE(struct
1343                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1344                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1345                   */                   */
1346                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1347                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1348                              template page?  */                                  urk Should be same type as ppp->translations */
1349                          int i;                          int i, j, n, m;
1350                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1351                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1352    
1353                            for (i=0; i<n; i++) {
1354                                    if (x & 1) {
1355                                            for (j=0; j<m; j++)
1356                                                    ppp->ics[i*m + j].f =
1357  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1358                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1359                                                        instr32(to_be_translated) :
1360  #endif  #endif
1361                                      instr(to_be_translated);                                                      instr(to_be_translated);
1362                                    }
1363    
1364                                    x >>= 1;
1365                            }
1366    
1367                            ppp->translations = 0;
1368                  }                  }
1369  #endif  #endif
1370          }          }
1371    
1372          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1373          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 ++) {  
1374                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1375                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1376                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1240  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1384  void DYNTRANS_INVALIDATE_TC_CODE(struct
1384                                  uint32_t index =                                  uint32_t index =
1385                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1386                                  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));  
1387  #else  #else
1388                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1389                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
# Line 1278  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1418  void DYNTRANS_INVALIDATE_TC_CODE(struct
1418  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1419          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1420  {  {
1421  #ifndef MODE32          int found, r, useraccess = 0;
         int64_t lowest, highest = -1;  
 #endif  
         int found, r, lowest_index, start, end, useraccess = 0;  
1422    
1423  #ifdef MODE32  #ifdef MODE32
1424          uint32_t index;          uint32_t index;
1425          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
1426          paddr_page &= 0xffffffffULL;  
1427            if (paddr_page > 0xffffffffULL) {
1428                    fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1429                        " p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag,
1430                        paddr_page);
1431                    exit(1);
1432            }
1433    
1434          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1435              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1436              (int)paddr_page);  */              (int)paddr_page);  */
# Line 1297  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1441  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1441          uint32_t x1, x2, x3;          uint32_t x1, x2, x3;
1442          struct DYNTRANS_L2_64_TABLE *l2;          struct DYNTRANS_L2_64_TABLE *l2;
1443          struct DYNTRANS_L3_64_TABLE *l3;          struct DYNTRANS_L3_64_TABLE *l3;
1444          /*  fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"  
1445              " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,          /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1446                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1447              (uint64_t)paddr_page);  */              (uint64_t)paddr_page);  */
1448  #endif  #endif
1449    
1450            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1451            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1452    
1453          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1454                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1455                  useraccess = 1;                  useraccess = 1;
1456          }          }
1457    
1458          start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  #ifdef DYNTRANS_M88K
1459  #if 1          /*  TODO  */
1460          /*  Half of the TLB used for data, half for code:  */          if (useraccess)
1461          if (writeflag & TLB_CODE) {                  return;
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
1462  #endif  #endif
1463    
1464          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
         lowest_index = start;  
1465    
1466  #ifdef MODE32  #ifdef MODE32
1467          /*          /*
# Line 1333  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1474  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1474           */           */
1475          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1476              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
         if (found < 0) {  
                 static unsigned int x = 0;  
                 lowest_index = (x % (end-start)) + start;  
                 x ++;  
         }  
1477  #else  #else
1478          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1479          found = -1;          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1480          for (r=start; r<end; r++) {          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1481                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {              & mask3;
1482                          lowest = cpu->cd.DYNTRANS_ARCH.  
1483                              vph_tlb_entry[r].timestamp;          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1484                          lowest_index = r;          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1485                  }                  found = -1;
1486                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)          else {
1487                          highest = cpu->cd.DYNTRANS_ARCH.                  l3 = l2->l3[x2];
1488                              vph_tlb_entry[r].timestamp;                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1489                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&                          found = -1;
1490                      cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==                  else
1491                      vaddr_page) {                          found = (int)l3->vaddr_to_tlbindex[x3] - 1;
                         found = r;  
                         break;  
                 }  
1492          }          }
1493  #endif  #endif
1494    
1495          if (found < 0) {          if (found < 0) {
1496                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting a "random" entry:  */
1497                  r = lowest_index;                  static unsigned int x = 0;
1498                    r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1499    
1500                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1501                          /*  This one has to be invalidated first:  */                          /*  This one has to be invalidated first:  */
1502                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
# Line 1375  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1510  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1510                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1511                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1512                      writeflag & MEM_WRITE;                      writeflag & MEM_WRITE;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1513    
1514                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
1515  #ifdef MODE32  #ifdef MODE32
# Line 1394  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1526  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1526                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1527  #endif  #endif
1528  #else   /* !MODE32  */  #else   /* !MODE32  */
                 x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;  
                 x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;  
                 x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))  
                     & mask3;  
1529                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1530                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1531                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
# Line 1406  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1534  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1534                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1535                          } else {                          } else {
1536                                  int i;                                  int i;
1537                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  CHECK_ALLOCATION(l2 =
1538                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(
1539                                        sizeof(struct DYNTRANS_L2_64_TABLE)));
1540                                    l2->refcount = 0;
1541                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1542                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1543                                              l3_64_dummy;                                              l3_64_dummy;
1544                          }                          }
1545                            if (l2->refcount != 0) {
1546                                    fatal("Huh? l2 Refcount problem.\n");
1547                                    exit(1);
1548                            }
1549                    }
1550                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1551                            fatal("INTERNAL ERROR L2 reuse\n");
1552                            exit(1);
1553                  }                  }
1554                  l3 = l2->l3[x2];                  l3 = l2->l3[x2];
1555                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
# Line 1423  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1561  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1561                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1562                                      struct DYNTRANS_L3_64_TABLE));                                      struct DYNTRANS_L3_64_TABLE));
1563                          }                          }
1564                            if (l3->refcount != 0) {
1565                                    fatal("Huh? l3 Refcount problem.\n");
1566                                    exit(1);
1567                            }
1568                          l2->refcount ++;                          l2->refcount ++;
1569                  }                  }
1570                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1571                            fatal("INTERNAL ERROR L3 reuse\n");
1572                            exit(1);
1573                    }
1574    
1575                  l3->host_load[x3] = host_page;                  l3->host_load[x3] = host_page;
1576                  l3->host_store[x3] = writeflag? host_page : NULL;                  l3->host_store[x3] = writeflag? host_page : NULL;
1577                  l3->phys_addr[x3] = paddr_page;                  l3->phys_addr[x3] = paddr_page;
1578                  l3->phys_page[x3] = NULL;                  l3->phys_page[x3] = NULL;
1579                  l3->vaddr_to_tlbindex[x3] = r + 1;                  l3->vaddr_to_tlbindex[x3] = r + 1;
1580                  l3->refcount ++;                  l3->refcount ++;
1581    
1582    #ifdef BUGHUNT
1583    /*  Count how many pages are actually in use:  */
1584    {
1585            int n=0, i;
1586            for (i=0; i<=mask3; i++)
1587                    if (l3->vaddr_to_tlbindex[i])
1588                            n++;
1589            if (n != l3->refcount) {
1590                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1591                    exit(1);
1592            }
1593    
1594            n = 0;
1595            for (i=0; i<=mask3; i++)
1596                    if (l3->host_load[i] != NULL)
1597                            n++;
1598            if (n != l3->refcount) {
1599                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1600                    exit(1);
1601            }
1602    }
1603    #endif
1604    
1605  #endif  /* !MODE32  */  #endif  /* !MODE32  */
1606          } else {          } else {
1607                  /*                  /*
# Line 1440  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1611  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1611                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1612                   */                   */
1613                  r = found;                  r = found;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1614                  if (writeflag & MEM_WRITE)                  if (writeflag & MEM_WRITE)
1615                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1616                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
# Line 1483  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1651  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1651                                  l3->host_store[x3] = NULL;                                  l3->host_store[x3] = NULL;
1652                  } else {                  } else {
1653                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
1654    printf("HOST LOAD 2 set to %p\n", host_page);
1655                          l3->host_load[x3] = host_page;                          l3->host_load[x3] = host_page;
1656                          l3->host_store[x3] = writeflag? host_page : NULL;                          l3->host_store[x3] = writeflag? host_page : NULL;
1657                          l3->phys_addr[x3] = paddr_page;                          l3->phys_addr[x3] = paddr_page;
1658                  }                  }
1659    
1660    #ifdef BUGHUNT
1661    /*  Count how many pages are actually in use:  */
1662    {
1663            int n=0, i;
1664            for (i=0; i<=mask3; i++)
1665                    if (l3->vaddr_to_tlbindex[i])
1666                            n++;
1667            if (n != l3->refcount) {
1668                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1669                    exit(1);
1670            }
1671    
1672            n = 0;
1673            for (i=0; i<=mask3; i++)
1674                    if (l3->host_load[i] != NULL)
1675                            n++;
1676            if (n != l3->refcount) {
1677                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1678                    printf("Entry r = %i\n", r);
1679                    printf("Valid = %i\n",
1680    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1681                    exit(1);
1682            }
1683    }
1684    #endif
1685    
1686  #endif  /*  !MODE32  */  #endif  /*  !MODE32  */
1687          }          }
1688  }  }
# Line 1500  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1696  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1696          /*          /*
1697           *  Check for breakpoints.           *  Check for breakpoints.
1698           */           */
1699          if (!single_step_breakpoint) {          if (!single_step_breakpoint && !cpu->translation_readahead) {
1700                  MODE_uint_t curpc = cpu->pc;                  MODE_uint_t curpc = cpu->pc;
1701                  int i;                  int i;
1702                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->breakpoints.n; i++)
1703                          if (curpc == (MODE_uint_t)                          if (curpc == (MODE_uint_t)
1704                              cpu->machine->breakpoint_addr[i]) {                              cpu->machine->breakpoints.addr[i]) {
1705                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1706                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1707                                          quiet_mode = 0;                                          quiet_mode = 0;
1708                                          DISASSEMBLE(cpu, ib, 1, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1709                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1710                                  }                                  }
1711    #ifdef MODE32
1712                                    fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The "
1713                                        "instruction has not yet executed.)\n",
1714                                        (uint32_t)cpu->pc);
1715    #else
1716                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1717                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1718                                      (uint64_t)cpu->pc);                                      (uint64_t)cpu->pc);
1719    #endif
1720  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1721                                  if (cpu->delay_slot != NOT_DELAYED)                                  if (cpu->delay_slot != NOT_DELAYED)
1722                                          fatal("ERROR! Breakpoint in a delay"                                          fatal("ERROR! Breakpoint in a delay"
1723                                              " slot! Not yet supported.\n");                                              " slot! Not yet supported.\n");
1724  #endif  #endif
1725                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1726                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1727                                  goto stop_running_translated;                                  goto stop_running_translated;
1728                          }                          }
1729          }          }
# Line 1533  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1735  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1735    
1736  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1737          /*          /*
1738           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1739           *  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.)  
1740           */           */
1741    
1742          /*  Make sure cur_physpage is in synch:  */          /*  Make sure cur_physpage is in synch:  */
1743          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1744              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
 #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;  
1745    
1746            {
1747                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1748                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1749                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1750                    x /= addr_per_translation_range;
1751    
1752                    cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
1753            }
1754    
1755          /*          /*
1756           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
1757           *  be converted into a single function call.           *  be converted into a single function call.
1758           *           *
1759           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1760           *  instruction combination. For architectures with delay slots,           *  instruction combinations. For architectures with delay slots,
1761           *  we also ignore combinations if the delay slot is across a page           *  we also ignore combinations if the delay slot is across a page
1762           *  boundary.           *  boundary.
1763           */           */
# Line 1565  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1765  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1765  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1766              && !in_crosspage_delayslot              && !in_crosspage_delayslot
1767  #endif  #endif
1768              ) {              && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1769                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&              && cpu->machine->allow_instruction_combinations) {
1770                      cpu->machine->speed_tricks)                  cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1771                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                      addr & (DYNTRANS_PAGESIZE - 1));
                             addr & (DYNTRANS_PAGESIZE - 1));  
1772          }          }
1773    
1774          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
# Line 1589  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1788  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1788          }          }
1789    
1790          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1791    
1792            /*  (Except when doing read-ahead!)  */
1793            if (cpu->translation_readahead)
1794                    return;
1795    
1796            /*
1797             *  Special case when single-stepping: Execute the translated
1798             *  instruction, but then replace it with a "to be translated"
1799             *  directly afterwards.
1800             */
1801          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1802  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1803              || in_crosspage_delayslot              || in_crosspage_delayslot
1804  #endif  #endif
1805              ) {              ) {
                 /*  
                  *  Special case when single-stepping: Execute the translated  
                  *  instruction, but then replace it with a "to be translated"  
                  *  directly afterwards.  
                  */  
1806                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
 #endif  
1807                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1808                  ic->f =                  ic->f =
1809  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1810                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
1811  #endif  #endif
1812                      instr(to_be_translated);                      instr(to_be_translated);
1813  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
1814                  ic->arg[0] = 0;                  return;
1815            }
1816    
1817            /*  Translation read-ahead:  */
1818            if (!single_step && !cpu->machine->instruction_trace) {
1819                    /*  Do readahead:  */
1820                    int i = 1;
1821                    uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(cpu->pc);
1822                    uint64_t baseaddr = cpu->pc;
1823    
1824                    cpu->translation_readahead = MAX_DYNTRANS_READAHEAD;
1825    
1826                    while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1827                        (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1828                        cpu->translation_readahead > 0) {
1829                            void (*old_f)(struct cpu *,
1830                                struct DYNTRANS_IC *) = ic[i].f;
1831    
1832                            /*  Already translated? Then abort:  */
1833                            if (old_f != (
1834    #ifdef DYNTRANS_DUALMODE_32
1835                                cpu->is_32bit? instr32(to_be_translated) :
1836  #endif  #endif
1837          } else {                              instr(to_be_translated)))
1838  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                                  break;
1839                  cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
1840                            /*  Translate the instruction:  */
1841                            ic[i].f(cpu, ic+i);
1842    
1843                            /*  Translation failed? Then abort.  */
1844                            if (ic[i].f == old_f)
1845                                    break;
1846    
1847                  /*  Additional check, for variable length ISAs:  */                          cpu->translation_readahead --;
1848                  if (ic->arg[0] == 0) {                          ++i;
                         fatal("INTERNAL ERROR: instr len = 0!\n");  
                         goto bad;  
1849                  }                  }
 #endif  
1850    
1851                  /*  Finally finally :-), execute the instruction:  */                  cpu->translation_readahead = 0;
                 ic->f(cpu, ic);  
1852          }          }
1853    
1854    
1855            /*
1856             *  Finally finally :-), execute the instruction.
1857             *
1858             *  Note: The instruction might have changed during read-ahead, if
1859             *  instruction combinations are used.
1860             */
1861    
1862            ic->f(cpu, ic);
1863    
1864          return;          return;
1865    
1866    
# Line 1634  bad:   /* Line 1868  bad:   /*
1868           *  Nothing was translated. (Unimplemented or illegal instruction.)           *  Nothing was translated. (Unimplemented or illegal instruction.)
1869           */           */
1870    
1871            /*  Clear the translation, in case it was "half-way" done:  */
1872            ic->f =
1873    #ifdef DYNTRANS_DUALMODE_32
1874                cpu->is_32bit? instr32(to_be_translated) :
1875    #endif
1876                instr(to_be_translated);
1877    
1878            if (cpu->translation_readahead)
1879                    return;
1880    
1881          quiet_mode = 0;          quiet_mode = 0;
1882          fatal("to_be_translated(): TODO: unimplemented instruction");          fatal("to_be_translated(): TODO: unimplemented instruction");
1883    
# Line 1649  bad:   /* Line 1893  bad:   /*
1893          }          }
1894    
1895          cpu->running = 0;          cpu->running = 0;
1896          cpu->dead = 1;  
1897            /*  Note: Single-stepping can jump here.  */
1898  stop_running_translated:  stop_running_translated:
1899    
1900          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1901          cpu->running_translated = 0;  
1902          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1903          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1904    
1905    #ifdef DYNTRANS_DELAYSLOT
1906            /*  Special hack: If the bad instruction was in a delay slot,
1907                make sure that execution does not continue anyway:  */
1908            if (cpu->delay_slot)
1909                    cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT;
1910    #endif
1911    
1912          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1913          ic->f(cpu, ic);          ic->f(cpu, ic);
1914    
1915  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */
1916    

Legend:
Removed from v.24  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26