/[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 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# 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.120 2006/08/12 11:43:12 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
32    
33    
34  #ifdef  DYNTRANS_CPU_RUN_INSTR  #ifndef STATIC_STUFF
35  #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;  
   
 #if 0  
         /*  Use the physical address:  */  
         cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)  
             cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
         a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;  
 #else  
         /*  Use the PC (virtual address):  */  
         a = cpu->pc;  
 #endif  
47    
48          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<          buf[0] = '\0';
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
49    
50          /*          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
51           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
52           */                          strlcat(buf, " ", sizeof(buf));
53  a &= 0x03ffffff;  
54  {                  switch (ch) {
55          static long long *array = NULL;                  case 'i':
56          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
57          static int n = 0;                              "%p", (void *)ic->f);
58          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
59          if (array == NULL)                  case 'p':
60                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
61          if (array_16kpage_in_use == NULL)                          /*  (low_pc must be within the page!)  */
62                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                          if (low_pc < 0 ||
63          a &= (16384*1024-1);                              low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
64          array[a] ++;                                  strlcat(buf, "-", sizeof(buf));
65          array_16kpage_in_use[a / 16384] = 1;                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
66          n++;                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
67          if ((n & 0x3fffffff) == 0) {                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
68                  FILE *f = fopen("statistics.out", "w");                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
69                  int i, j;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
70                  printf("Saving statistics... "); fflush(stdout);                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
71                  for (i=0; i<1024; i++)                          if (cpu->is_32bit)
72                          if (array_16kpage_in_use[i]) {                                  snprintf(buf + strlen(buf), sizeof(buf),
73                                  for (j=0; j<16384; j++)                                      "0x%016"PRIx32, (uint32_t)a);
74                                          if (array[i*16384 + j] > 0)                          else
75                                                  fprintf(f, "%lli\t"                                  snprintf(buf + strlen(buf), sizeof(buf),
76                                                      "0x%016"PRIx64"\n",                                      "0x%016"PRIx64, (uint64_t)a);
77                                                      (uint64_t)array[i*16384+j],                          break;
78                                                      (uint64_t)((i*16384+j) <<                  case 'v':
79                                              DYNTRANS_INSTR_ALIGNMENT_SHIFT));                          /*  Virtual program counter address:  */
80                          }                          /*  (low_pc inside the page, or in a delay slot)  */
81                  fclose(f);                          if (low_pc < 0 ||
82                  printf("n=0x%08x\n", n);                              low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE + 2)
83                                    strlcat(buf, "-", sizeof(buf));
84                            a = cpu->pc;
85                            a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
86                                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
87                            a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
88                            if (cpu->is_32bit)
89                                    snprintf(buf + strlen(buf), sizeof(buf),
90                                        "0x%016"PRIx32, (uint32_t)a);
91                            else
92                                    snprintf(buf + strlen(buf), sizeof(buf),
93                                        "0x%016"PRIx64, (uint64_t)a);
94                            break;
95                    }
96                    i++;
97          }          }
98    
99            fprintf(cpu->machine->statistics_file, "%s\n", buf);
100  }  }
 }  
 #endif  /*  PC statistics  */  
101    
102    
103  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
# Line 170  a &= 0x03ffffff; Line 156  a &= 0x03ffffff;
156          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
157  */  */
158  #endif  #endif
159    #endif  /*  STATIC STUFF  */
160    
161    
162    
163    #ifdef  DYNTRANS_RUN_INSTR
164  /*  /*
165   *  XXX_cpu_run_instr():   *  XXX_run_instr():
166   *   *
167   *  Execute one or more instructions on a specific CPU, using dyntrans.   *  Execute one or more instructions on a specific CPU, using dyntrans.
168     *  (For dualmode archs, this function is included twice.)
169   *   *
170   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
171   *  0 if no instructions were executed.   *  0 if no instructions were executed.
172   */   */
173  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
174  {  {
175          /*          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  
176          int low_pc, n_instrs;          int low_pc, n_instrs;
177    
178            /*  Ugly... fix this some day.  */
179  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
180          if (cpu->is_32bit)  #ifdef MODE32
181                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
182          else  #else
183            DYNTRANS_PC_TO_POINTERS(cpu);
184  #endif  #endif
185    #else
186          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
187    #endif
188    
189          /*          /*
190           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
# Line 238  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 223  int DYNTRANS_CPU_RUN_INSTR(struct emul *
223  #endif  #endif
224  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
225          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
226                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
227                            ppc_exception(cpu, PPC_EXCEPTION_DEC);
228                  cpu->cd.ppc.dec_intr_pending = 0;                  cpu->cd.ppc.dec_intr_pending = 0;
229          }          }
230          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)
# Line 248  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 234  int DYNTRANS_CPU_RUN_INSTR(struct emul *
234          cached_pc = cpu->pc;          cached_pc = cpu->pc;
235    
236          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
         cpu->running_translated = 1;  
237    
238          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
239              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
# Line 278  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 263  int DYNTRANS_CPU_RUN_INSTR(struct emul *
263    
264                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
265                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
266                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
267                                      "the instruction\n");                                      "the instruction\n");
268                          } else {                          } else {
269                                  cpu_disassemble_instr(cpu->machine, cpu,                                  cpu_disassemble_instr(cpu->machine, cpu,
# Line 307  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 292  int DYNTRANS_CPU_RUN_INSTR(struct emul *
292                          }                          }
293                  }                  }
294    
295                  /*  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)  
296                          S;                          S;
297    
298                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
# Line 356  while (cycles-- > 0) Line 316  while (cycles-- > 0)
316          cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);          cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);
317  /* printf("B\n"); */  /* printf("B\n"); */
318    
319                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
320                              n_instrs + cpu->n_translated_instrs >=                              N_SAFE_DYNTRANS_LIMIT)
                             N_SAFE_DYNTRANS_LIMIT / 2)  
321                                  break;                                  break;
322                  }                  }
323          } else if (show_opcode_statistics) {          } else if (cpu->machine->statistics_enabled) {
324                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
325                  n_instrs = 0;                  n_instrs = 0;
326                  for (;;) {                  for (;;) {
# Line 374  while (cycles-- > 0) Line 333  while (cycles-- > 0)
333    
334                          n_instrs += 24;                          n_instrs += 24;
335    
336                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
337                              n_instrs + cpu->n_translated_instrs >=                              N_SAFE_DYNTRANS_LIMIT)
                             N_SAFE_DYNTRANS_LIMIT / 2)  
338                                  break;                                  break;
339                  }                  }
340          } else {          } else {
341                  /*  Execute multiple instructions:  */                  /*  Execute multiple instructions:  */
342                  n_instrs = 0;                  int n = 0;
343                  for (;;) {                  for (;;) {
344                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
345    
# Line 393  while (cycles-- > 0) Line 351  while (cycles-- > 0)
351    
352                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
353    
354                          n_instrs += 60;                          n += 60;
355    
356                          if (!cpu->running_translated ||                          if (n + cpu->n_translated_instrs >=
357                              n_instrs + cpu->n_translated_instrs >=                              N_SAFE_DYNTRANS_LIMIT)
                             N_SAFE_DYNTRANS_LIMIT / 2)  
358                                  break;                                  break;
359                  }                  }
360                    n_instrs = n;
361          }          }
362    
363          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 458  while (cycles-- > 0) Line 416  while (cycles-- > 0)
416          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
417          return n_instrs;          return n_instrs;
418  }  }
419  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
420    
421    
422    
# Line 505  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 463  void DYNTRANS_FUNCTION_TRACE(struct cpu
463           */           */
464          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
465                  int64_t d;                  int64_t d;
466  #ifdef DYNTRANS_X86  #if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER)
467                  d = 0;          /*  TODO  */                  d = 0;          /*  TODO  */
468  #else  #else
469                  /*  Args in registers:  */                  /*  Args in registers:  */
# Line 575  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 533  void DYNTRANS_FUNCTION_TRACE(struct cpu
533    
534    
535  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
   
 /*  forward declaration of to_be_translated and end_of_page:  */  
 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
   
 #ifdef DYNTRANS_DELAYSLOT  
 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
 #endif  
   
536  /*  /*
537   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
538   *   *
# Line 601  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 543  static void DYNTRANS_TC_ALLOCATE_DEFAULT
543          uint64_t physaddr)          uint64_t physaddr)
544  {  {
545          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
546    
         /*  Create the physpage header:  */  
547          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
548              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
549    
550          /*  TODO: Is this faster than copying an entire template page?  */          /*  Copy the entire template page first:  */
551          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
552                  ppp->ics[i].f =              struct DYNTRANS_TC_PHYSPAGE));
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 ppp->ics[i].arg[0] = 0;  
 #endif  
         }  
   
         /*  End-of-page:  */  
         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);  
553    
554  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
         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  
555    
556          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
557    
558          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
559          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
560          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
561  }  }
562  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 707  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 619  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
619    
620          if (!ok) {          if (!ok) {
621                  uint64_t paddr;                  uint64_t paddr;
622                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
623                          ok = cpu->translate_address(cpu, cached_pc,                          uint64_t vaddr =
624                              &paddr, FLAG_INSTR);  #if defined(MODE32) && defined(DYNTRANS_MIPS)
625                  else {                          /*  32-bit MIPS is _sign_ extend, not zero.  */
626                                (int32_t)
627    #endif
628                                cached_pc;
629                            ok = cpu->translate_v2p(
630                                cpu, vaddr, &paddr, FLAG_INSTR);
631                    } else {
632                          paddr = cached_pc;                          paddr = cached_pc;
633                          ok = 1;                          ok = 1;
634                  }                  }
635                  if (!ok) {                  if (!ok) {
636                            /*
637                             *  The PC is now set to the exception handler.
638                             *  Try to find the paddr in the translation arrays,
639                             *  or if that fails, call translate_v2p for the
640                             *  exception handler.
641                             */
642                          /*  fatal("TODO: instruction vaddr=>paddr translation "                          /*  fatal("TODO: instruction vaddr=>paddr translation "
643                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
644                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
645    
646                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          /*  If there was an exception, the PC has changed.
647                              FLAG_INSTR);                              Update cached_pc:  */
648                            cached_pc = cpu->pc;
649    
650    #ifdef MODE32
651                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
652                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
653                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
654                                    ok = 1;
655                            }
656    #else
657                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
658                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
659                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
660                                & mask3;
661                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
662                            l3 = l2->l3[x2];
663                            if (l3->host_load[x3] != NULL) {
664                                    paddr = l3->phys_addr[x3];
665                                    ok = 1;
666                            }
667    #endif
668    
669                            if (!ok) {
670                                    ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
671                                        FLAG_INSTR);
672                            }
673    
674                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
675                              "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 682  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
682                          }                          }
683                  }                  }
684    
                 /*  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  
   
685                  physaddr = paddr;                  physaddr = paddr;
686          }          }
687    
688            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
689    
690  #ifdef MODE32  #ifdef MODE32
691          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
692  #else  #else
693          if (l3->host_load[x3] == NULL) {          if (l3->host_load[x3] == NULL) {
694  #endif  #endif
695                    int q = DYNTRANS_PAGESIZE - 1;
696                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
697                      physaddr, MEM_READ);                      physaddr, MEM_READ);
698                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
699                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
700                              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  
701                  }                  }
702          }          }
703    
704          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
705                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
706                    fatal("[ dyntrans: resetting the translation cache ]\n");
707    #endif
708                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
709          }          }
710    
# Line 787  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 719  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
719          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
720                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
721                      + physpage_ofs);                      + physpage_ofs);
722    
723                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
724                  if (DYNTRANS_ADDR_TO_PAGENR(ppp->physaddr) == pagenr)                  if (ppp->physaddr == physaddr)
725                          break;                          break;
726    
727                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
728                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
729          }          }
# Line 819  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 753  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
753                  l3->phys_page[x3] = ppp;                  l3->phys_page[x3] = ppp;
754  #endif  #endif
755    
756  #ifdef MODE32          /*
757          /*  Small optimization: only mark the physical page as non-writable           *  If there are no translations yet on this page, then mark it
758              if it did not contain translations. (Because if it does contain           *  as non-writable. If there are already translations, then it
759              translations, it is already non-writable.)  */           *  should already have been marked as non-writable.
760          if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &           */
761              (1 << (pagenr & 31)))          if (ppp->translations == 0) {
762  #endif                  cpu->invalidate_translation_caches(cpu, physaddr,
763          cpu->invalidate_translation_caches(cpu, physaddr,                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
764              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);          }
765    
766          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
767    
# Line 904  have_it: Line 838  have_it:
838    
839    
840    
841  #ifdef DYNTRANS_INIT_64BIT_DUMMY_TABLES  #ifdef DYNTRANS_INIT_TABLES
842    
843    /*  forward declaration of to_be_translated and end_of_page:  */
844    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
845    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
846    #ifdef DYNTRANS_DUALMODE_32
847    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
848    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
849    #endif
850    
851    #ifdef DYNTRANS_DELAYSLOT
852    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
853    #ifdef DYNTRANS_DUALMODE_32
854    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
855    #endif
856    #endif
857    
858  /*  /*
859   *  XXX_init_64bit_dummy_tables():   *  XXX_init_tables():
860   *   *
861   *  Initializes 64-bit dummy tables and pointers.   *  Initializes the default translation page (for newly allocated pages), and
862     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
863   */   */
864  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(struct cpu *cpu)  void DYNTRANS_INIT_TABLES(struct cpu *cpu)
865  {  {
866    #ifndef MODE32
867          struct DYNTRANS_L2_64_TABLE *dummy_l2;          struct DYNTRANS_L2_64_TABLE *dummy_l2;
868          struct DYNTRANS_L3_64_TABLE *dummy_l3;          struct DYNTRANS_L3_64_TABLE *dummy_l3;
869          int x1, x2;          int x1, x2;
870    #endif
871            int i;
872            struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
873                struct DYNTRANS_TC_PHYSPAGE));
874    
875            if (ppp == NULL) {
876                    fprintf(stderr, "out of memory\n");
877                    exit(1);
878            }
879    
880            ppp->next_ofs = 0;
881            ppp->translations = 0;
882            /*  ppp->physaddr is filled in by the page allocator  */
883    
884            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
885                    ppp->ics[i].f =
886    #ifdef DYNTRANS_DUALMODE_32
887                        cpu->is_32bit? instr32(to_be_translated) :
888    #endif
889                        instr(to_be_translated);
890    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
891                    ppp->ics[i].arg[0] = 0;
892    #endif
893            }
894    
895            /*  End-of-page:  */
896            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
897    #ifdef DYNTRANS_DUALMODE_32
898                cpu->is_32bit? instr32(end_of_page) :
899    #endif
900                instr(end_of_page);
901    
902    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
903            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;
904    #endif
905    
906            /*  End-of-page-2, for delay-slot architectures:  */
907    #ifdef DYNTRANS_DELAYSLOT
908            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
909    #ifdef DYNTRANS_DUALMODE_32
910                cpu->is_32bit? instr32(end_of_page2) :
911    #endif
912                instr(end_of_page2);
913    #endif
914    
915            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
916    
917    
918            /*  Prepare 64-bit virtual address translation tables:  */
919    #ifndef MODE32
920          if (cpu->is_32bit)          if (cpu->is_32bit)
921                  return;                  return;
922    
# Line 930  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st Line 931  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st
931    
932          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
933                  dummy_l2->l3[x2] = dummy_l3;                  dummy_l2->l3[x2] = dummy_l3;
934    #endif
935  }  }
936  #endif  /*  DYNTRANS_INIT_64BIT_DUMMY_TABLES  */  #endif  /*  DYNTRANS_INIT_TABLES  */
937    
938    
939    
# Line 998  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1000  static void DYNTRANS_INVALIDATE_TLB_ENTR
1000                  l3->host_store[x3] = NULL;                  l3->host_store[x3] = NULL;
1001                  return;                  return;
1002          }          }
1003    
1004    #ifdef BUGHUNT
1005    
1006    {
1007            /*  Consistency check, for debugging:  */
1008            int x1, x1b; // x2, x3;
1009            struct DYNTRANS_L2_64_TABLE *l2;
1010            //struct DYNTRANS_L3_64_TABLE *l3;
1011    
1012            for (x1 = 0; x1 <= mask1; x1 ++) {
1013                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1014                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1015                            continue;
1016                    /*  Make sure that this l2 isn't used more than 1 time!  */
1017                    for (x1b = 0; x1b <= mask1; x1b ++)
1018                            if (x1 != x1b &&
1019                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1020                                    fatal("L2 reuse: %p\n", l2);
1021                                    exit(1);
1022                            }
1023            }
1024    }
1025    
1026    /*  Count how many pages are actually in use:  */
1027    {
1028            int n=0, i;
1029            for (i=0; i<=mask3; i++)
1030                    if (l3->vaddr_to_tlbindex[i])
1031                            n++;
1032            if (n != l3->refcount) {
1033                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1034                    exit(1);
1035            }
1036    
1037            n = 0;
1038            for (i=0; i<=mask3; i++)
1039                    if (l3->host_load[i] != NULL)
1040                            n++;
1041            if (n != l3->refcount) {
1042                    printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1043                    exit(1);
1044            }
1045    }
1046    #endif
1047    
1048          l3->host_load[x3] = NULL;          l3->host_load[x3] = NULL;
1049          l3->host_store[x3] = NULL;          l3->host_store[x3] = NULL;
1050          l3->phys_addr[x3] = 0;          l3->phys_addr[x3] = 0;
1051          l3->phys_page[x3] = NULL;          l3->phys_page[x3] = NULL;
1052          l3->refcount --;          if (l3->vaddr_to_tlbindex[x3] != 0) {
1053                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1054                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1055                    l3->refcount --;
1056            }
1057            l3->vaddr_to_tlbindex[x3] = 0;
1058    
1059          if (l3->refcount < 0) {          if (l3->refcount < 0) {
1060                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1061                  exit(1);                  exit(1);
1062          }          }
1063    
1064          if (l3->refcount == 0) {          if (l3->refcount == 0) {
1065                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1066                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1067                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1068    
1069    #ifdef BUGHUNT
1070    /*  Make sure that we're placing a CLEAN page on the
1071        freelist:  */
1072    {
1073            int i;
1074            for (i=0; i<=mask3; i++)
1075                    if (l3->host_load[i] != NULL) {
1076                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1077                            exit(1);
1078                    }
1079    }
1080    #endif
1081                  l2->refcount --;                  l2->refcount --;
1082                  if (l2->refcount < 0) {                  if (l2->refcount < 0) {
1083                          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 1219  void DYNTRANS_INVALIDATE_TC_CODE(struct
1219                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1220    
1221                  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  
   
1222                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1223    
1224                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
# Line 1177  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1231  void DYNTRANS_INVALIDATE_TC_CODE(struct
1231                          prev_ppp = ppp;                          prev_ppp = ppp;
1232                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1233                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1234    
1235                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1236                              then we're done:  */                              then we're done:  */
1237                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1238                                  break;                                  break;
1239    
1240                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1241                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1242                  }                  }
# Line 1188  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1244  void DYNTRANS_INVALIDATE_TC_CODE(struct
1244                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1245                          ppp = NULL;                          ppp = NULL;
1246    
1247  #if 1  #if 0
1248                  /*                  /*
1249                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1250                   *                   *
# Line 1210  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1266  void DYNTRANS_INVALIDATE_TC_CODE(struct
1266                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1267                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1268                   */                   */
1269                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1270                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1271                              template page?  */                                  urk Should be same type as ppp->translations */
1272                          int i;                          int i, j, n, m;
1273                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1274                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1275    
1276                            for (i=0; i<n; i++) {
1277                                    if (x & 1) {
1278                                            for (j=0; j<m; j++)
1279                                                    ppp->ics[i*m + j].f =
1280  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1281                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1282                                                        instr32(to_be_translated) :
1283  #endif  #endif
1284                                      instr(to_be_translated);                                                      instr(to_be_translated);
1285                                    }
1286    
1287                                    x >>= 1;
1288                            }
1289    
1290                            ppp->translations = 0;
1291                  }                  }
1292  #endif  #endif
1293          }          }
1294    
1295          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1296          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 ++) {  
1297                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1298                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1299                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1240  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1307  void DYNTRANS_INVALIDATE_TC_CODE(struct
1307                                  uint32_t index =                                  uint32_t index =
1308                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1309                                  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));  
1310  #else  #else
1311                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1312                                  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 1341  void DYNTRANS_INVALIDATE_TC_CODE(struct
1341  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1342          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1343  {  {
1344  #ifndef MODE32          int found, r, lowest_index, useraccess = 0;
         int64_t lowest, highest = -1;  
 #endif  
         int found, r, lowest_index, start, end, useraccess = 0;  
1345    
1346  #ifdef MODE32  #ifdef MODE32
1347          uint32_t index;          uint32_t index;
# Line 1297  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1357  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1357          uint32_t x1, x2, x3;          uint32_t x1, x2, x3;
1358          struct DYNTRANS_L2_64_TABLE *l2;          struct DYNTRANS_L2_64_TABLE *l2;
1359          struct DYNTRANS_L3_64_TABLE *l3;          struct DYNTRANS_L3_64_TABLE *l3;
1360          /*  fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"  
1361              " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,          /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1362                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1363              (uint64_t)paddr_page);  */              (uint64_t)paddr_page);  */
1364  #endif  #endif
1365    
1366            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1367            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1368    
1369          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1370                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1371                  useraccess = 1;                  useraccess = 1;
1372          }          }
1373    
         start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  
 #if 1  
         /*  Half of the TLB used for data, half for code:  */  
         if (writeflag & TLB_CODE) {  
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
 #endif  
   
1374          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1375          lowest_index = start;          lowest_index = 0;
1376    
1377  #ifdef MODE32  #ifdef MODE32
1378          /*          /*
# Line 1333  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1385  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1385           */           */
1386          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1387              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 ++;  
         }  
1388  #else  #else
1389          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1390          found = -1;          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1391          for (r=start; r<end; r++) {          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1392                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {              & mask3;
1393                          lowest = cpu->cd.DYNTRANS_ARCH.  
1394                              vph_tlb_entry[r].timestamp;          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1395                          lowest_index = r;          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1396                  }                  found = -1;
1397                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)          else {
1398                          highest = cpu->cd.DYNTRANS_ARCH.                  l3 = l2->l3[x2];
1399                              vph_tlb_entry[r].timestamp;                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1400                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&                          found = -1;
1401                      cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==                  else
1402                      vaddr_page) {                          found = (int)l3->vaddr_to_tlbindex[x3] - 1;
                         found = r;  
                         break;  
                 }  
1403          }          }
1404  #endif  #endif
1405    
1406          if (found < 0) {          if (found < 0) {
1407                    static unsigned int x = 0;
1408                    lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1409            }
1410    
1411            if (found < 0) {
1412                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting the oldest one:  */
1413                  r = lowest_index;                  r = lowest_index;
1414                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
# Line 1375  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1424  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1424                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1425                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1426                      writeflag & MEM_WRITE;                      writeflag & MEM_WRITE;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1427    
1428                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
1429  #ifdef MODE32  #ifdef MODE32
# Line 1394  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1440  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1440                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1441  #endif  #endif
1442  #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;  
1443                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1444                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1445                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {                          if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
# Line 1408  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1450  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1450                                  int i;                                  int i;
1451                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1452                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1453                                    l2->refcount = 0;
1454                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1455                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1456                                              l3_64_dummy;                                              l3_64_dummy;
1457                          }                          }
1458                            if (l2->refcount != 0) {
1459                                    fatal("Huh? l2 Refcount problem.\n");
1460                                    exit(1);
1461                            }
1462                    }
1463                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1464                            fatal("INTERNAL ERROR L2 reuse\n");
1465                            exit(1);
1466                  }                  }
1467                  l3 = l2->l3[x2];                  l3 = l2->l3[x2];
1468                  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 1474  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1474                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1475                                      struct DYNTRANS_L3_64_TABLE));                                      struct DYNTRANS_L3_64_TABLE));
1476                          }                          }
1477                            if (l3->refcount != 0) {
1478                                    fatal("Huh? l3 Refcount problem.\n");
1479                                    exit(1);
1480                            }
1481                          l2->refcount ++;                          l2->refcount ++;
1482                  }                  }
1483                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1484                            fatal("INTERNAL ERROR L3 reuse\n");
1485                            exit(1);
1486                    }
1487    
1488                  l3->host_load[x3] = host_page;                  l3->host_load[x3] = host_page;
1489                  l3->host_store[x3] = writeflag? host_page : NULL;                  l3->host_store[x3] = writeflag? host_page : NULL;
1490                  l3->phys_addr[x3] = paddr_page;                  l3->phys_addr[x3] = paddr_page;
1491                  l3->phys_page[x3] = NULL;                  l3->phys_page[x3] = NULL;
1492                  l3->vaddr_to_tlbindex[x3] = r + 1;                  l3->vaddr_to_tlbindex[x3] = r + 1;
1493                  l3->refcount ++;                  l3->refcount ++;
1494    
1495    #ifdef BUGHUNT
1496    /*  Count how many pages are actually in use:  */
1497    {
1498            int n=0, i;
1499            for (i=0; i<=mask3; i++)
1500                    if (l3->vaddr_to_tlbindex[i])
1501                            n++;
1502            if (n != l3->refcount) {
1503                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1504                    exit(1);
1505            }
1506    
1507            n = 0;
1508            for (i=0; i<=mask3; i++)
1509                    if (l3->host_load[i] != NULL)
1510                            n++;
1511            if (n != l3->refcount) {
1512                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1513                    exit(1);
1514            }
1515    }
1516    #endif
1517    
1518  #endif  /* !MODE32  */  #endif  /* !MODE32  */
1519          } else {          } else {
1520                  /*                  /*
# Line 1440  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1524  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1524                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1525                   */                   */
1526                  r = found;                  r = found;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1527                  if (writeflag & MEM_WRITE)                  if (writeflag & MEM_WRITE)
1528                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1529                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
# Line 1483  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1564  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1564                                  l3->host_store[x3] = NULL;                                  l3->host_store[x3] = NULL;
1565                  } else {                  } else {
1566                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
1567    printf("HOST LOAD 2 set to %p\n", host_page);
1568                          l3->host_load[x3] = host_page;                          l3->host_load[x3] = host_page;
1569                          l3->host_store[x3] = writeflag? host_page : NULL;                          l3->host_store[x3] = writeflag? host_page : NULL;
1570                          l3->phys_addr[x3] = paddr_page;                          l3->phys_addr[x3] = paddr_page;
1571                  }                  }
1572    
1573    #ifdef BUGHUNT
1574    /*  Count how many pages are actually in use:  */
1575    {
1576            int n=0, i;
1577            for (i=0; i<=mask3; i++)
1578                    if (l3->vaddr_to_tlbindex[i])
1579                            n++;
1580            if (n != l3->refcount) {
1581                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1582                    exit(1);
1583            }
1584    
1585            n = 0;
1586            for (i=0; i<=mask3; i++)
1587                    if (l3->host_load[i] != NULL)
1588                            n++;
1589            if (n != l3->refcount) {
1590                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1591                    printf("Entry r = %i\n", r);
1592                    printf("Valid = %i\n",
1593    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1594                    exit(1);
1595            }
1596    }
1597    #endif
1598    
1599  #endif  /*  !MODE32  */  #endif  /*  !MODE32  */
1600          }          }
1601  }  }
# Line 1521  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1630  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1630                                              " slot! Not yet supported.\n");                                              " slot! Not yet supported.\n");
1631  #endif  #endif
1632                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1633                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1634                                  goto stop_running_translated;                                  goto stop_running_translated;
1635                          }                          }
1636          }          }
# Line 1533  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1642  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1642    
1643  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1644          /*          /*
1645           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1646           *  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.)  
1647           */           */
1648    
1649          /*  Make sure cur_physpage is in synch:  */          /*  Make sure cur_physpage is in synch:  */
1650          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1651              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;  
1652    
1653            {
1654                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1655                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1656                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1657                    x /= addr_per_translation_range;
1658    
1659                    cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
1660            }
1661    
1662          /*          /*
1663           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
# Line 1565  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1672  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1672  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1673              && !in_crosspage_delayslot              && !in_crosspage_delayslot
1674  #endif  #endif
1675              ) {              && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1676                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&              && cpu->machine->allow_instruction_combinations) {
1677                      cpu->machine->speed_tricks)                  cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1678                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                      addr & (DYNTRANS_PAGESIZE - 1));
                             addr & (DYNTRANS_PAGESIZE - 1));  
1679          }          }
1680    
1681          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
# Line 1649  bad:   /* Line 1755  bad:   /*
1755          }          }
1756    
1757          cpu->running = 0;          cpu->running = 0;
1758          cpu->dead = 1;  
1759            /*  Note: Single-stepping can jump here.  */
1760  stop_running_translated:  stop_running_translated:
1761    
1762          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1763          cpu->running_translated = 0;  
1764          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1765          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1766    
1767          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1768          ic->f(cpu, ic);          ic->f(cpu, ic);
1769    
1770  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */
1771    

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

  ViewVC Help
Powered by ViewVC 1.1.26