/[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 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 32 by dpavlin, Mon Oct 8 16:20:58 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.132 2006/10/27 13:12:20 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
32    
33    
34  #ifdef  DYNTRANS_CPU_RUN_INSTR  #ifndef STATIC_STUFF
35  #if 1   /*  IC statistics:  */  #define STATIC_STUFF
36    /*
37     *  gather_statistics():
38     */
39  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
40  {  {
41            char ch, buf[60];
42          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
43          static long long n = 0;          int i = 0;
         static FILE *f = NULL;  
   
         n++;  
         if (n < 100000000)  
                 return;  
   
         if (f == NULL) {  
                 f = fopen("instruction_call_statistics.raw", "w");  
                 if (f == NULL) {  
                         fatal("Unable to open statistics file for output.\n");  
                         exit(1);  
                 }  
         }  
         fwrite(&ic->f, 1, sizeof(void *), f);  
 }  
 #else   /*  PC statistics:  */  
 static void gather_statistics(struct cpu *cpu)  
 {  
44          uint64_t a;          uint64_t a;
45          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
46              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
         if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
                 return;  
47    
48  #if 0          if (cpu->machine->statistics_file == NULL) {
49          /*  Use the physical address:  */                  fatal("statistics gathering with no filename set is"
50          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)                      " meaningless\n");
51              cpu->cd.DYNTRANS_ARCH.cur_ic_page;                  return;
52          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;          }
 #else  
         /*  Use the PC (virtual address):  */  
         a = cpu->pc;  
 #endif  
53    
54          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<          buf[0] = '\0';
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
55    
56          /*          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
57           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
58           */                          strlcat(buf, " ", sizeof(buf));
59  a &= 0x03ffffff;  
60  {                  switch (ch) {
61          static long long *array = NULL;                  case 'i':
62          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
63          static int n = 0;                              "%p", (void *)ic->f);
64          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
65          if (array == NULL)                  case 'p':
66                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
67          if (array_16kpage_in_use == NULL)                          /*  (low_pc must be within the page!)  */
68                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                          if (low_pc < 0 ||
69          a &= (16384*1024-1);                              low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
70          array[a] ++;                                  strlcat(buf, "-", sizeof(buf));
71          array_16kpage_in_use[a / 16384] = 1;                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
72          n++;                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
73          if ((n & 0x3fffffff) == 0) {                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
74                  FILE *f = fopen("statistics.out", "w");                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
75                  int i, j;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
76                  printf("Saving statistics... "); fflush(stdout);                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77                  for (i=0; i<1024; i++)                          if (cpu->is_32bit)
78                          if (array_16kpage_in_use[i]) {                                  snprintf(buf + strlen(buf), sizeof(buf),
79                                  for (j=0; j<16384; j++)                                      "0x%016"PRIx32, (uint32_t)a);
80                                          if (array[i*16384 + j] > 0)                          else
81                                                  fprintf(f, "%lli\t"                                  snprintf(buf + strlen(buf), sizeof(buf),
82                                                      "0x%016"PRIx64"\n",                                      "0x%016"PRIx64, (uint64_t)a);
83                                                      (uint64_t)array[i*16384+j],                          break;
84                                                      (uint64_t)((i*16384+j) <<                  case 'v':
85                                              DYNTRANS_INSTR_ALIGNMENT_SHIFT));                          /*  Virtual program counter address:  */
86                          }                          /*  (low_pc inside the page, or in a delay slot)  */
87                  fclose(f);                          if (low_pc < 0 ||
88                  printf("n=0x%08x\n", n);                              low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE + 2)
89                                    strlcat(buf, "-", sizeof(buf));
90                            a = cpu->pc;
91                            a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
92                                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
93                            a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
94                            if (cpu->is_32bit)
95                                    snprintf(buf + strlen(buf), sizeof(buf),
96                                        "0x%016"PRIx32, (uint32_t)a);
97                            else
98                                    snprintf(buf + strlen(buf), sizeof(buf),
99                                        "0x%016"PRIx64, (uint64_t)a);
100                            break;
101                    }
102                    i++;
103          }          }
104    
105            fprintf(cpu->machine->statistics_file, "%s\n", buf);
106  }  }
 }  
 #endif  /*  PC statistics  */  
107    
108    
109  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
# Line 170  a &= 0x03ffffff; Line 162  a &= 0x03ffffff;
162          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
163  */  */
164  #endif  #endif
165    #endif  /*  STATIC STUFF  */
166    
167    
168    
169    #ifdef  DYNTRANS_RUN_INSTR
170  /*  /*
171   *  XXX_cpu_run_instr():   *  XXX_run_instr():
172   *   *
173   *  Execute one or more instructions on a specific CPU, using dyntrans.   *  Execute one or more instructions on a specific CPU, using dyntrans.
174     *  (For dualmode archs, this function is included twice.)
175   *   *
176   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
177   *  0 if no instructions were executed.   *  0 if no instructions were executed.
178   */   */
179  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
180  {  {
181          /*          MODE_uint_t cached_pc;
          *  TODO:  Statistics stuff!  
          */  
         int show_opcode_statistics = 0;  
   
 #ifdef MODE32  
         uint32_t cached_pc;  
 #else  
         uint64_t cached_pc;  
 #endif  
182          int low_pc, n_instrs;          int low_pc, n_instrs;
183    
184            /*  Ugly... fix this some day.  */
185  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
186          if (cpu->is_32bit)  #ifdef MODE32
187                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
188          else  #else
189            DYNTRANS_PC_TO_POINTERS(cpu);
190  #endif  #endif
191    #else
192          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
193    #endif
194    
195          /*          /*
196           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
# Line 238  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 229  int DYNTRANS_CPU_RUN_INSTR(struct emul *
229  #endif  #endif
230  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
231          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) {
232                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
233                            ppc_exception(cpu, PPC_EXCEPTION_DEC);
234                  cpu->cd.ppc.dec_intr_pending = 0;                  cpu->cd.ppc.dec_intr_pending = 0;
235          }          }
236          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)
237                  ppc_exception(cpu, PPC_EXCEPTION_EI);                  ppc_exception(cpu, PPC_EXCEPTION_EI);
238  #endif  #endif
239    #ifdef DYNTRANS_SH
240            if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
241                && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
242                < cpu->cd.sh.int_level)
243                    sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0);
244    #endif
245    
246          cached_pc = cpu->pc;          cached_pc = cpu->pc;
247    
248          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
         cpu->running_translated = 1;  
249    
250          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
251              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
# Line 264  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 261  int DYNTRANS_CPU_RUN_INSTR(struct emul *
261                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
262                  }                  }
263                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
264                            /*  TODO/Note: This must be large enough to hold
265                                any instruction for any ISA:  */
266                            unsigned char instr[1 <<
267                                DYNTRANS_INSTR_ALIGNMENT_SHIFT];
268  #ifdef DYNTRANS_X86  #ifdef DYNTRANS_X86
                         unsigned char instr[17];  
269                          cpu->cd.x86.cursegment = X86_S_CS;                          cpu->cd.x86.cursegment = X86_S_CS;
270                          cpu->cd.x86.seg_override = 0;                          cpu->cd.x86.seg_override = 0;
 #else  
 #ifdef DYNTRANS_M68K  
                         unsigned char instr[16];        /*  TODO: 16?  */  
 #else  
                         unsigned char instr[4];         /*  General case...  */  
271  #endif  #endif
 #endif  
   
272                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
273                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
274                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
275                                      "the instruction\n");                                      "the instruction\n");
276                          } else {                          } else {
277                                  cpu_disassemble_instr(cpu->machine, cpu,  #ifdef DYNTRANS_DELAYSLOT
278                                      instr, 1, 0);                                  int len =
279    #endif
280                                        cpu_disassemble_instr(
281                                        cpu->machine, cpu, instr, 1, 0);
282  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
283                                  /*  Show the instruction in the delay slot,                                  /*  Show the instruction in the delay slot,
284                                      if any:  */                                      if any:  */
# Line 293  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 289  int DYNTRANS_CPU_RUN_INSTR(struct emul *
289                                      instr)) {                                      instr)) {
290                                          int saved_delayslot = cpu->delay_slot;                                          int saved_delayslot = cpu->delay_slot;
291                                          cpu->memory_rw(cpu, cpu->mem, cached_pc                                          cpu->memory_rw(cpu, cpu->mem, cached_pc
292                                              + sizeof(instr), &instr[0],                                              + len, &instr[0],
293                                              sizeof(instr), MEM_READ,                                              sizeof(instr), MEM_READ,
294                                              CACHE_INSTRUCTION);                                              CACHE_INSTRUCTION);
295                                          cpu->delay_slot = DELAYED;                                          cpu->delay_slot = DELAYED;
296                                          cpu->pc += sizeof(instr);                                          cpu->pc += len;
297                                          cpu_disassemble_instr(cpu->machine,                                          cpu_disassemble_instr(cpu->machine,
298                                              cpu, instr, 1, 0);                                              cpu, instr, 1, 0);
299                                          cpu->delay_slot = saved_delayslot;                                          cpu->delay_slot = saved_delayslot;
300                                          cpu->pc -= sizeof(instr);                                          cpu->pc -= len;
301                                  }                                  }
302  #endif  #endif
303                          }                          }
304                  }                  }
305    
306                  /*  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)  
307                          S;                          S;
308    
309                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
# Line 356  while (cycles-- > 0) Line 327  while (cycles-- > 0)
327          cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);          cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);
328  /* printf("B\n"); */  /* printf("B\n"); */
329    
330                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
                             n_instrs + cpu->n_translated_instrs >=  
331                              N_SAFE_DYNTRANS_LIMIT)                              N_SAFE_DYNTRANS_LIMIT)
332                                  break;                                  break;
333                  }                  }
334          } else if (show_opcode_statistics) {          } else if (cpu->machine->statistics_enabled) {
335                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
336                  n_instrs = 0;                  n_instrs = 0;
337                  for (;;) {                  for (;;) {
# Line 374  while (cycles-- > 0) Line 344  while (cycles-- > 0)
344    
345                          n_instrs += 24;                          n_instrs += 24;
346    
347                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
                             n_instrs + cpu->n_translated_instrs >=  
348                              N_SAFE_DYNTRANS_LIMIT)                              N_SAFE_DYNTRANS_LIMIT)
349                                  break;                                  break;
350                  }                  }
351          } else {          } else {
352                  /*  Execute multiple instructions:  */                  /*  Execute multiple instructions:  */
353                  n_instrs = 0;                  int n = 0;
354                  for (;;) {                  for (;;) {
355                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
356    
# Line 393  while (cycles-- > 0) Line 362  while (cycles-- > 0)
362    
363                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
364    
365                          n_instrs += 60;                          n += 60;
366    
367                          if (!cpu->running_translated ||                          if (n + cpu->n_translated_instrs >=
                             n_instrs + cpu->n_translated_instrs >=  
368                              N_SAFE_DYNTRANS_LIMIT)                              N_SAFE_DYNTRANS_LIMIT)
369                                  break;                                  break;
370                  }                  }
371                    n_instrs = n;
372          }          }
373    
374          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 436  while (cycles-- > 0) Line 405  while (cycles-- > 0)
405                      (int32_t) (old + n_instrs);                      (int32_t) (old + n_instrs);
406                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -                  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
407                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];                      cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
408                  if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)  
409                          cpu_interrupt(cpu, 7);                  if (cpu->cd.mips.compare_register_set) {
410    #if 1
411    /*  Not yet.  TODO  */
412                            if (cpu->machine->emulated_hz > 0) {
413                                    if (cpu->cd.mips.compare_interrupts_pending > 0)
414                                            cpu_interrupt(cpu, 7);
415                            } else
416    #endif
417                            {
418                                    if (diff1 > 0 && diff2 <= 0)
419                                            cpu_interrupt(cpu, 7);
420                            }
421                    }
422          }          }
423  #endif  #endif
424  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
# Line 458  while (cycles-- > 0) Line 439  while (cycles-- > 0)
439          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
440          return n_instrs;          return n_instrs;
441  }  }
442  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
443    
444    
445    
# Line 480  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 461  void DYNTRANS_FUNCTION_TRACE(struct cpu
461              6              6
462  #else  #else
463  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
464              8              8   /*  Both for 32-bit and 64-bit SuperH  */
465  #else  #else
466              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
467  #endif  #endif
# Line 505  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 486  void DYNTRANS_FUNCTION_TRACE(struct cpu
486           */           */
487          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
488                  int64_t d;                  int64_t d;
489  #ifdef DYNTRANS_X86  #if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER)
490                  d = 0;          /*  TODO  */                  d = 0;          /*  TODO  */
491  #else  #else
492                  /*  Args in registers:  */                  /*  Args in registers:  */
# Line 521  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 502  void DYNTRANS_FUNCTION_TRACE(struct cpu
502                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
503                      r[24                      r[24
504  #endif  #endif
505    #ifdef DYNTRANS_AVR32
506                        r[0         /*  TODO  */
507    #endif
508  #ifdef DYNTRANS_HPPA  #ifdef DYNTRANS_HPPA
509                      r[0         /*  TODO  */                      r[0         /*  TODO  */
510  #endif  #endif
# Line 539  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 523  void DYNTRANS_FUNCTION_TRACE(struct cpu
523  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
524                      gpr[3                      gpr[3
525  #endif  #endif
526    #ifdef DYNTRANS_RCA180X
527                        r[0         /*  TODO  */
528    #endif
529  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
530                      r[2                      r[4         /*  NetBSD seems to use 4? But 2 seems
531                                            to be used by other code? TODO  */
532  #endif  #endif
533  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
534                      r[24                      r[8         /*  o0..o5  */
535  #endif  #endif
536                      + x];                      + x];
537  #endif  #endif
# Line 662  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 650  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
650          if (!ok) {          if (!ok) {
651                  uint64_t paddr;                  uint64_t paddr;
652                  if (cpu->translate_v2p != NULL) {                  if (cpu->translate_v2p != NULL) {
653                            uint64_t vaddr =
654    #if defined(MODE32) && defined(DYNTRANS_MIPS)
655                            /*  32-bit MIPS is _sign_ extend, not zero.  */
656                                (int32_t)
657    #endif
658                                cached_pc;
659                          ok = cpu->translate_v2p(                          ok = cpu->translate_v2p(
660                              cpu, cached_pc, &paddr, FLAG_INSTR);                              cpu, vaddr, &paddr, FLAG_INSTR);
661                  } else {                  } else {
662                          paddr = cached_pc;                          paddr = cached_pc;
663                          ok = 1;                          ok = 1;
664                  }                  }
665                  if (!ok) {                  if (!ok) {
666                            /*
667                             *  The PC is now set to the exception handler.
668                             *  Try to find the paddr in the translation arrays,
669                             *  or if that fails, call translate_v2p for the
670                             *  exception handler.
671                             */
672                          /*  fatal("TODO: instruction vaddr=>paddr translation "                          /*  fatal("TODO: instruction vaddr=>paddr translation "
673                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
674                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
675    
676                          ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,                          /*  If there was an exception, the PC has changed.
677                              FLAG_INSTR);                              Update cached_pc:  */
678                            cached_pc = cpu->pc;
679    
680    #ifdef MODE32
681                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
682                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
683                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
684                                    ok = 1;
685                            }
686    #else
687                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
688                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
689                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
690                                & mask3;
691                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
692                            l3 = l2->l3[x2];
693                            if (l3->host_load[x3] != NULL) {
694                                    paddr = l3->phys_addr[x3];
695                                    ok = 1;
696                            }
697    #endif
698    
699                            if (!ok) {
700                                    ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
701                                        FLAG_INSTR);
702                            }
703    
704                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
705                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
# Line 687  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 712  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
712                          }                          }
713                  }                  }
714    
                 /*  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  
   
715                  physaddr = paddr;                  physaddr = paddr;
716          }          }
717    
718            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
719    
720  #ifdef MODE32  #ifdef MODE32
721          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
722  #else  #else
723          if (l3->host_load[x3] == NULL) {          if (l3->host_load[x3] == NULL) {
724  #endif  #endif
725                    int q = DYNTRANS_PAGESIZE - 1;
726                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
727                      physaddr, MEM_READ);                      physaddr, MEM_READ);
728                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
729                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
730                              host_page, 0, 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  
731                  }                  }
732          }          }
733    
# Line 732  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 738  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
738                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
739          }          }
740    
         physaddr &= ~(DYNTRANS_PAGESIZE - 1);  
   
741          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
742          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
743    
# Line 779  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 783  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
783                  l3->phys_page[x3] = ppp;                  l3->phys_page[x3] = ppp;
784  #endif  #endif
785    
786  #ifdef MODE32          /*
787          /*  Small optimization: only mark the physical page as non-writable           *  If there are no translations yet on this page, then mark it
788              if it did not contain translations. (Because if it does contain           *  as non-writable. If there are already translations, then it
789              translations, it is already non-writable.)  */           *  should already have been marked as non-writable.
790          if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &           */
791              (1 << (pagenr & 31)))          if (ppp->translations == 0) {
792  #endif                  cpu->invalidate_translation_caches(cpu, physaddr,
793          cpu->invalidate_translation_caches(cpu, physaddr,                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
794              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);          }
795    
796          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
797    
# Line 904  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 908  void DYNTRANS_INIT_TABLES(struct cpu *cp
908          }          }
909    
910          ppp->next_ofs = 0;          ppp->next_ofs = 0;
911            ppp->translations = 0;
912          /*  ppp->physaddr is filled in by the page allocator  */          /*  ppp->physaddr is filled in by the page allocator  */
913    
914          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
# Line 1025  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1030  static void DYNTRANS_INVALIDATE_TLB_ENTR
1030                  l3->host_store[x3] = NULL;                  l3->host_store[x3] = NULL;
1031                  return;                  return;
1032          }          }
1033    
1034    #ifdef BUGHUNT
1035    
1036    {
1037            /*  Consistency check, for debugging:  */
1038            int x1, x1b; // x2, x3;
1039            struct DYNTRANS_L2_64_TABLE *l2;
1040            //struct DYNTRANS_L3_64_TABLE *l3;
1041    
1042            for (x1 = 0; x1 <= mask1; x1 ++) {
1043                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1044                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1045                            continue;
1046                    /*  Make sure that this l2 isn't used more than 1 time!  */
1047                    for (x1b = 0; x1b <= mask1; x1b ++)
1048                            if (x1 != x1b &&
1049                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1050                                    fatal("L2 reuse: %p\n", l2);
1051                                    exit(1);
1052                            }
1053            }
1054    }
1055    
1056    /*  Count how many pages are actually in use:  */
1057    {
1058            int n=0, i;
1059            for (i=0; i<=mask3; i++)
1060                    if (l3->vaddr_to_tlbindex[i])
1061                            n++;
1062            if (n != l3->refcount) {
1063                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1064                    exit(1);
1065            }
1066    
1067            n = 0;
1068            for (i=0; i<=mask3; i++)
1069                    if (l3->host_load[i] != NULL)
1070                            n++;
1071            if (n != l3->refcount) {
1072                    printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1073                    exit(1);
1074            }
1075    }
1076    #endif
1077    
1078          l3->host_load[x3] = NULL;          l3->host_load[x3] = NULL;
1079          l3->host_store[x3] = NULL;          l3->host_store[x3] = NULL;
1080          l3->phys_addr[x3] = 0;          l3->phys_addr[x3] = 0;
1081          l3->phys_page[x3] = NULL;          l3->phys_page[x3] = NULL;
1082          l3->refcount --;          if (l3->vaddr_to_tlbindex[x3] != 0) {
1083                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1084                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1085                    l3->refcount --;
1086            }
1087            l3->vaddr_to_tlbindex[x3] = 0;
1088    
1089          if (l3->refcount < 0) {          if (l3->refcount < 0) {
1090                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1091                  exit(1);                  exit(1);
1092          }          }
1093    
1094          if (l3->refcount == 0) {          if (l3->refcount == 0) {
1095                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1096                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1097                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1098    
1099    #ifdef BUGHUNT
1100    /*  Make sure that we're placing a CLEAN page on the
1101        freelist:  */
1102    {
1103            int i;
1104            for (i=0; i<=mask3; i++)
1105                    if (l3->host_load[i] != NULL) {
1106                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1107                            exit(1);
1108                    }
1109    }
1110    #endif
1111                  l2->refcount --;                  l2->refcount --;
1112                  if (l2->refcount < 0) {                  if (l2->refcount < 0) {
1113                          fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");                          fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
# Line 1180  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1249  void DYNTRANS_INVALIDATE_TC_CODE(struct
1249                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1250    
1251                  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  
   
1252                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1253    
1254                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
# Line 1217  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1274  void DYNTRANS_INVALIDATE_TC_CODE(struct
1274                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1275                          ppp = NULL;                          ppp = NULL;
1276    
1277  #if 1  #if 0
1278                  /*                  /*
1279                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1280                   *                   *
# Line 1239  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1296  void DYNTRANS_INVALIDATE_TC_CODE(struct
1296                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1297                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1298                   */                   */
1299                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1300                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1301                              template page?  */                                  urk Should be same type as ppp->translations */
1302                          int i;                          int i, j, n, m;
1303                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1304                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1305    
1306                            for (i=0; i<n; i++) {
1307                                    if (x & 1) {
1308                                            for (j=0; j<m; j++)
1309                                                    ppp->ics[i*m + j].f =
1310  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1311                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1312                                                        instr32(to_be_translated) :
1313  #endif  #endif
1314                                      instr(to_be_translated);                                                      instr(to_be_translated);
1315                                    }
1316    
1317                                    x >>= 1;
1318                            }
1319    
1320                            ppp->translations = 0;
1321                  }                  }
1322  #endif  #endif
1323          }          }
# Line 1268  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1337  void DYNTRANS_INVALIDATE_TC_CODE(struct
1337                                  uint32_t index =                                  uint32_t index =
1338                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1339                                  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));  
1340  #else  #else
1341                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1342                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
# Line 1306  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1371  void DYNTRANS_INVALIDATE_TC_CODE(struct
1371  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1372          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1373  {  {
1374  #ifndef MODE32          int found, r, useraccess = 0;
         int64_t lowest, highest = -1;  
 #endif  
         int found, r, lowest_index, useraccess = 0;  
1375    
1376  #ifdef MODE32  #ifdef MODE32
1377          uint32_t index;          uint32_t index;
# Line 1325  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1387  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1387          uint32_t x1, x2, x3;          uint32_t x1, x2, x3;
1388          struct DYNTRANS_L2_64_TABLE *l2;          struct DYNTRANS_L2_64_TABLE *l2;
1389          struct DYNTRANS_L3_64_TABLE *l3;          struct DYNTRANS_L3_64_TABLE *l3;
1390          /*  fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"  
1391              " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,          /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1392                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1393              (uint64_t)paddr_page);  */              (uint64_t)paddr_page);  */
1394  #endif  #endif
1395    
# Line 1339  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1402  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1402          }          }
1403    
1404          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
         lowest_index = 0;  
1405    
1406  #ifdef MODE32  #ifdef MODE32
1407          /*          /*
# Line 1352  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1414  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1414           */           */
1415          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1416              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++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
1417  #else  #else
1418          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1419          found = -1;          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1420          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1421                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {              & mask3;
1422                          lowest = cpu->cd.DYNTRANS_ARCH.  
1423                              vph_tlb_entry[r].timestamp;          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1424                          lowest_index = r;          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1425                  }                  found = -1;
1426                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)          else {
1427                          highest = cpu->cd.DYNTRANS_ARCH.                  l3 = l2->l3[x2];
1428                              vph_tlb_entry[r].timestamp;                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1429                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&                          found = -1;
1430                      cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==                  else
1431                      vaddr_page) {                          found = (int)l3->vaddr_to_tlbindex[x3] - 1;
                         found = r;  
                         break;  
                 }  
1432          }          }
1433  #endif  #endif
1434    
1435          if (found < 0) {          if (found < 0) {
1436                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting a "random" entry:  */
1437                  r = lowest_index;                  static unsigned int x = 0;
1438                    r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1439    
1440                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1441                          /*  This one has to be invalidated first:  */                          /*  This one has to be invalidated first:  */
1442                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
# Line 1393  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1450  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1450                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1451                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1452                      writeflag & MEM_WRITE;                      writeflag & MEM_WRITE;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1453    
1454                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
1455  #ifdef MODE32  #ifdef MODE32
# Line 1412  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1466  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1466                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1467  #endif  #endif
1468  #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;  
1469                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1470                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1471                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
# Line 1426  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1476  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1476                                  int i;                                  int i;
1477                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1478                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1479                                    l2->refcount = 0;
1480                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1481                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1482                                              l3_64_dummy;                                              l3_64_dummy;
1483                          }                          }
1484                            if (l2->refcount != 0) {
1485                                    fatal("Huh? l2 Refcount problem.\n");
1486                                    exit(1);
1487                            }
1488                    }
1489                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1490                            fatal("INTERNAL ERROR L2 reuse\n");
1491                            exit(1);
1492                  }                  }
1493                  l3 = l2->l3[x2];                  l3 = l2->l3[x2];
1494                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
# Line 1441  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1500  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1500                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1501                                      struct DYNTRANS_L3_64_TABLE));                                      struct DYNTRANS_L3_64_TABLE));
1502                          }                          }
1503                            if (l3->refcount != 0) {
1504                                    fatal("Huh? l3 Refcount problem.\n");
1505                                    exit(1);
1506                            }
1507                          l2->refcount ++;                          l2->refcount ++;
1508                  }                  }
1509                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1510                            fatal("INTERNAL ERROR L3 reuse\n");
1511                            exit(1);
1512                    }
1513    
1514                  l3->host_load[x3] = host_page;                  l3->host_load[x3] = host_page;
1515                  l3->host_store[x3] = writeflag? host_page : NULL;                  l3->host_store[x3] = writeflag? host_page : NULL;
1516                  l3->phys_addr[x3] = paddr_page;                  l3->phys_addr[x3] = paddr_page;
1517                  l3->phys_page[x3] = NULL;                  l3->phys_page[x3] = NULL;
1518                  l3->vaddr_to_tlbindex[x3] = r + 1;                  l3->vaddr_to_tlbindex[x3] = r + 1;
1519                  l3->refcount ++;                  l3->refcount ++;
1520    
1521    #ifdef BUGHUNT
1522    /*  Count how many pages are actually in use:  */
1523    {
1524            int n=0, i;
1525            for (i=0; i<=mask3; i++)
1526                    if (l3->vaddr_to_tlbindex[i])
1527                            n++;
1528            if (n != l3->refcount) {
1529                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1530                    exit(1);
1531            }
1532    
1533            n = 0;
1534            for (i=0; i<=mask3; i++)
1535                    if (l3->host_load[i] != NULL)
1536                            n++;
1537            if (n != l3->refcount) {
1538                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1539                    exit(1);
1540            }
1541    }
1542    #endif
1543    
1544  #endif  /* !MODE32  */  #endif  /* !MODE32  */
1545          } else {          } else {
1546                  /*                  /*
# Line 1458  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1550  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1550                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1551                   */                   */
1552                  r = found;                  r = found;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1553                  if (writeflag & MEM_WRITE)                  if (writeflag & MEM_WRITE)
1554                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1555                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
# Line 1501  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1590  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1590                                  l3->host_store[x3] = NULL;                                  l3->host_store[x3] = NULL;
1591                  } else {                  } else {
1592                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
1593    printf("HOST LOAD 2 set to %p\n", host_page);
1594                          l3->host_load[x3] = host_page;                          l3->host_load[x3] = host_page;
1595                          l3->host_store[x3] = writeflag? host_page : NULL;                          l3->host_store[x3] = writeflag? host_page : NULL;
1596                          l3->phys_addr[x3] = paddr_page;                          l3->phys_addr[x3] = paddr_page;
1597                  }                  }
1598    
1599    #ifdef BUGHUNT
1600    /*  Count how many pages are actually in use:  */
1601    {
1602            int n=0, i;
1603            for (i=0; i<=mask3; i++)
1604                    if (l3->vaddr_to_tlbindex[i])
1605                            n++;
1606            if (n != l3->refcount) {
1607                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1608                    exit(1);
1609            }
1610    
1611            n = 0;
1612            for (i=0; i<=mask3; i++)
1613                    if (l3->host_load[i] != NULL)
1614                            n++;
1615            if (n != l3->refcount) {
1616                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1617                    printf("Entry r = %i\n", r);
1618                    printf("Valid = %i\n",
1619    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1620                    exit(1);
1621            }
1622    }
1623    #endif
1624    
1625  #endif  /*  !MODE32  */  #endif  /*  !MODE32  */
1626          }          }
1627  }  }
# Line 1551  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1668  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1668    
1669  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1670          /*          /*
1671           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1672           *  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.)  
1673           */           */
1674    
1675          /*  Make sure cur_physpage is in synch:  */          /*  Make sure cur_physpage is in synch:  */
1676          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1677              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;  
1678    
1679            {
1680                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1681                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1682                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1683                    x /= addr_per_translation_range;
1684    
1685                    cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
1686            }
1687    
1688          /*          /*
1689           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
# Line 1583  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1698  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1698  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1699              && !in_crosspage_delayslot              && !in_crosspage_delayslot
1700  #endif  #endif
1701              ) {              && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1702                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&              && cpu->machine->allow_instruction_combinations) {
1703                      cpu->machine->speed_tricks)                  cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1704                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                      addr & (DYNTRANS_PAGESIZE - 1));
                             addr & (DYNTRANS_PAGESIZE - 1));  
1705          }          }
1706    
1707          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
# Line 1667  bad:   /* Line 1781  bad:   /*
1781          }          }
1782    
1783          cpu->running = 0;          cpu->running = 0;
1784          cpu->dead = 1;  
1785            /*  Note: Single-stepping can jump here.  */
1786  stop_running_translated:  stop_running_translated:
1787    
1788          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1789          cpu->running_translated = 0;  
1790          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1791          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1792    
1793          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1794          ic->f(cpu, ic);          ic->f(cpu, ic);
1795    
1796  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */
1797    

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

  ViewVC Help
Powered by ViewVC 1.1.26