/[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 27 by dpavlin, Mon Oct 8 16:20:10 2007 UTC revision 28 by dpavlin, Mon Oct 8 16:20:26 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.113 2006/07/21 20:09:15 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
32    
33    
34  #ifdef  DYNTRANS_CPU_RUN_INSTR  #ifndef STATIC_STUFF
35  #if 1   /*  IC statistics:  */  #define STATIC_STUFF
36    /*
37     *  gather_statistics():
38     */
39  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
40  {  {
41            char ch, buf[60];
42          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
43          static long long n = 0;          int i = 0;
         static FILE *f = NULL;  
   
         n++;  
         if (n < 100000000)  
                 return;  
   
         if (f == NULL) {  
                 f = fopen("instruction_call_statistics.raw", "w");  
                 if (f == NULL) {  
                         fatal("Unable to open statistics file for output.\n");  
                         exit(1);  
                 }  
         }  
         fwrite(&ic->f, 1, sizeof(void *), f);  
 }  
 #else   /*  PC statistics:  */  
 static void gather_statistics(struct cpu *cpu)  
 {  
44          uint64_t a;          uint64_t a;
45          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
46              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
         if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
                 return;  
   
 #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 MODE32  
         uint32_t cached_pc;  
 #else  
         uint64_t cached_pc;  
 #endif  
176          int low_pc, n_instrs;          int low_pc, n_instrs;
177    
178            /*  Ugly... fix this some day.  */
179  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
180          if (cpu->is_32bit)  #ifdef MODE32
181                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
182          else  #else
183            DYNTRANS_PC_TO_POINTERS(cpu);
184  #endif  #endif
185    #else
186          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
187    #endif
188    
189          /*          /*
190           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
# 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 323  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 308  int DYNTRANS_CPU_RUN_INSTR(struct emul *
308                                      arg[0] = 0;                                      arg[0] = 0;
309  #endif  #endif
310                          }                          }
311    
312                          fatal("[ Note: The translation of physical page 0x%"                          fatal("[ Note: The translation of physical page 0x%"
313                              PRIx64" contained combinations of instructions; "                              PRIx64" contained combinations of instructions; "
314                              "these are now flushed because we are single-"                              "these are now flushed because we are single-"
315                              "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.                              "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.
316                              cur_physpage->physaddr);                              cur_physpage->physaddr);
317    
318                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=
319                              ~(COMBINATIONS | TRANSLATIONS);                              ~COMBINATIONS;
320                            cpu->cd.DYNTRANS_ARCH.cur_physpage->translations = 0;
321                  }                  }
322    
323                  if (show_opcode_statistics)                  if (cpu->machine->statistics_enabled)
324                          S;                          S;
325    
326                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
# Line 361  while (cycles-- > 0) Line 349  while (cycles-- > 0)
349                              N_SAFE_DYNTRANS_LIMIT)                              N_SAFE_DYNTRANS_LIMIT)
350                                  break;                                  break;
351                  }                  }
352          } else if (show_opcode_statistics) {          } else if (cpu->machine->statistics_enabled) {
353                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
354                  n_instrs = 0;                  n_instrs = 0;
355                  for (;;) {                  for (;;) {
# Line 458  while (cycles-- > 0) Line 446  while (cycles-- > 0)
446          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
447          return n_instrs;          return n_instrs;
448  }  }
449  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
450    
451    
452    
# Line 505  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 493  void DYNTRANS_FUNCTION_TRACE(struct cpu
493           */           */
494          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
495                  int64_t d;                  int64_t d;
496  #ifdef DYNTRANS_X86  #if defined(DYNTRANS_X86) || defined(DYNTRANS_TRANSPUTER)
497                  d = 0;          /*  TODO  */                  d = 0;          /*  TODO  */
498  #else  #else
499                  /*  Args in registers:  */                  /*  Args in registers:  */
# Line 669  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 657  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
657                          ok = 1;                          ok = 1;
658                  }                  }
659                  if (!ok) {                  if (!ok) {
660                            /*
661                             *  The PC is now set to the exception handler.
662                             *  Try to find the paddr in the translation arrays,
663                             *  or if that fails, call translate_v2p for the
664                             *  exception handler.
665                             */
666                          /*  fatal("TODO: instruction vaddr=>paddr translation "                          /*  fatal("TODO: instruction vaddr=>paddr translation "
667                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
668                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
669    
670                          ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,                          /*  If there was an exception, the PC has changed.
671                              FLAG_INSTR);                              Update cached_pc:  */
672                            cached_pc = cpu->pc;
673    
674    #ifdef MODE32
675                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
676                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
677                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
678                                    ok = 1;
679                            }
680    #else
681                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
682                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
683                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
684                                & mask3;
685                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
686                            l3 = l2->l3[x2];
687                            if (l3->host_load[x3] != NULL) {
688                                    paddr = l3->phys_addr[x3];
689                                    ok = 1;
690                            }
691    #endif
692    
693                            if (!ok) {
694                                    ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
695                                        FLAG_INSTR);
696                            }
697    
698                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
699                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
# Line 687  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 706  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
706                          }                          }
707                  }                  }
708    
                 /*  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  
   
709                  physaddr = paddr;                  physaddr = paddr;
710          }          }
711    
712            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
713    
714  #ifdef MODE32  #ifdef MODE32
715          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
716  #else  #else
717          if (l3->host_load[x3] == NULL) {          if (l3->host_load[x3] == NULL) {
718  #endif  #endif
719                    int q = DYNTRANS_PAGESIZE - 1;
720                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
721                      physaddr, MEM_READ);                      physaddr, MEM_READ);
722                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
723                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
724                              host_page, 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  
725                  }                  }
726          }          }
727    
# Line 732  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 732  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
732                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
733          }          }
734    
         physaddr &= ~(DYNTRANS_PAGESIZE - 1);  
   
735          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
736          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
737    
# Line 779  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 777  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
777                  l3->phys_page[x3] = ppp;                  l3->phys_page[x3] = ppp;
778  #endif  #endif
779    
780  #ifdef MODE32          /*
781          /*  Small optimization: only mark the physical page as non-writable           *  If there are no translations yet on this page, then mark it
782              if it did not contain translations. (Because if it does contain           *  as non-writable. If there are already translations, then it
783              translations, it is already non-writable.)  */           *  should already have been marked as non-writable.
784          if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &           */
785              (1 << (pagenr & 31)))          if (ppp->translations == 0) {
786  #endif                  cpu->invalidate_translation_caches(cpu, physaddr,
787          cpu->invalidate_translation_caches(cpu, physaddr,                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
788              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);          }
789    
790          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
791    
# Line 904  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 902  void DYNTRANS_INIT_TABLES(struct cpu *cp
902          }          }
903    
904          ppp->next_ofs = 0;          ppp->next_ofs = 0;
905            ppp->flags = 0;
906            ppp->translations = 0;
907          /*  ppp->physaddr is filled in by the page allocator  */          /*  ppp->physaddr is filled in by the page allocator  */
908    
909          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 1025  static void DYNTRANS_INVALIDATE_TLB_ENTR
1025                  l3->host_store[x3] = NULL;                  l3->host_store[x3] = NULL;
1026                  return;                  return;
1027          }          }
1028    
1029    #ifdef BUGHUNT
1030    
1031    {
1032            /*  Consistency check, for debugging:  */
1033            int x1, x1b; // x2, x3;
1034            struct DYNTRANS_L2_64_TABLE *l2;
1035            //struct DYNTRANS_L3_64_TABLE *l3;
1036    
1037            for (x1 = 0; x1 <= mask1; x1 ++) {
1038                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1039                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1040                            continue;
1041                    /*  Make sure that this l2 isn't used more than 1 time!  */
1042                    for (x1b = 0; x1b <= mask1; x1b ++)
1043                            if (x1 != x1b &&
1044                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1045                                    fatal("L2 reuse: %p\n", l2);
1046                                    exit(1);
1047                            }
1048            }
1049    }
1050    
1051    /*  Count how many pages are actually in use:  */
1052    {
1053            int n=0, i;
1054            for (i=0; i<=mask3; i++)
1055                    if (l3->vaddr_to_tlbindex[i])
1056                            n++;
1057            if (n != l3->refcount) {
1058                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1059                    exit(1);
1060            }
1061    
1062            n = 0;
1063            for (i=0; i<=mask3; i++)
1064                    if (l3->host_load[i] != NULL)
1065                            n++;
1066            if (n != l3->refcount) {
1067                    printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1068                    exit(1);
1069            }
1070    }
1071    #endif
1072    
1073          l3->host_load[x3] = NULL;          l3->host_load[x3] = NULL;
1074          l3->host_store[x3] = NULL;          l3->host_store[x3] = NULL;
1075          l3->phys_addr[x3] = 0;          l3->phys_addr[x3] = 0;
1076          l3->phys_page[x3] = NULL;          l3->phys_page[x3] = NULL;
1077          l3->refcount --;          if (l3->vaddr_to_tlbindex[x3] != 0) {
1078                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1079                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1080                    l3->refcount --;
1081            }
1082            l3->vaddr_to_tlbindex[x3] = 0;
1083    
1084          if (l3->refcount < 0) {          if (l3->refcount < 0) {
1085                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1086                  exit(1);                  exit(1);
1087          }          }
1088    
1089          if (l3->refcount == 0) {          if (l3->refcount == 0) {
1090                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1091                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1092                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1093    
1094    #ifdef BUGHUNT
1095    /*  Make sure that we're placing a CLEAN page on the
1096        freelist:  */
1097    {
1098            int i;
1099            for (i=0; i<=mask3; i++)
1100                    if (l3->host_load[i] != NULL) {
1101                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1102                            exit(1);
1103                    }
1104    }
1105    #endif
1106                  l2->refcount --;                  l2->refcount --;
1107                  if (l2->refcount < 0) {                  if (l2->refcount < 0) {
1108                          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 1244  void DYNTRANS_INVALIDATE_TC_CODE(struct
1244                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1245    
1246                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
   
 #ifdef MODE32  
                 /*  If this page isn't marked as having any translations,  
                     then return immediately.  */  
                 if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]  
                     & 1 << (pagenr & 31)))  
                         return;  
                 /*  Remove the mark:  */  
                 cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=  
                     ~ (1 << (pagenr & 31));  
 #endif  
   
1247                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1248    
1249                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
# Line 1217  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1269  void DYNTRANS_INVALIDATE_TC_CODE(struct
1269                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1270                          ppp = NULL;                          ppp = NULL;
1271    
1272  #if 1  #if 0
1273                  /*                  /*
1274                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1275                   *                   *
# Line 1239  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1291  void DYNTRANS_INVALIDATE_TC_CODE(struct
1291                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1292                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1293                   */                   */
1294                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1295                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1296                              template page?  */                                  urk Should be same type as ppp->translations */
1297                          int i;                          int i, j, n, m;
1298                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1299                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1300    
1301                            for (i=0; i<n; i++) {
1302                                    if (x & 1) {
1303                                            for (j=0; j<m; j++)
1304                                                    ppp->ics[i*m + j].f =
1305  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1306                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1307                                                        instr32(to_be_translated) :
1308  #endif  #endif
1309                                      instr(to_be_translated);                                                      instr(to_be_translated);
1310                                    }
1311    
1312                                    x >>= 1;
1313                            }
1314    
1315                            ppp->flags &= ~COMBINATIONS;
1316                            ppp->translations = 0;
1317                  }                  }
1318  #endif  #endif
1319          }          }
# Line 1268  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1333  void DYNTRANS_INVALIDATE_TC_CODE(struct
1333                                  uint32_t index =                                  uint32_t index =
1334                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1335                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
                                 /*  Remove the mark:  */  
                                 index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);  
                                 cpu->cd.DYNTRANS_ARCH.phystranslation[  
                                     index >> 5] &= ~ (1 << (index & 31));  
1336  #else  #else
1337                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1338                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
# Line 1325  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1386  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1386          uint32_t x1, x2, x3;          uint32_t x1, x2, x3;
1387          struct DYNTRANS_L2_64_TABLE *l2;          struct DYNTRANS_L2_64_TABLE *l2;
1388          struct DYNTRANS_L3_64_TABLE *l3;          struct DYNTRANS_L3_64_TABLE *l3;
1389          /*  fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"  
1390              " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,          /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1391                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1392              (uint64_t)paddr_page);  */              (uint64_t)paddr_page);  */
1393  #endif  #endif
1394    
# Line 1416  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1478  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1478                  x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;                  x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1479                  x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))                  x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1480                      & mask3;                      & mask3;
1481    
1482                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1483                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {                  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1484                          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 1489  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1489                                  int i;                                  int i;
1490                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1491                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1492                                    l2->refcount = 0;
1493                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1494                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1495                                              l3_64_dummy;                                              l3_64_dummy;
1496                          }                          }
1497                            if (l2->refcount != 0) {
1498                                    fatal("Huh? l2 Refcount problem.\n");
1499                                    exit(1);
1500                            }
1501                    }
1502                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1503                            fatal("INTERNAL ERROR L2 reuse\n");
1504                            exit(1);
1505                  }                  }
1506                  l3 = l2->l3[x2];                  l3 = l2->l3[x2];
1507                  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 1513  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1513                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(                                  l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1514                                      struct DYNTRANS_L3_64_TABLE));                                      struct DYNTRANS_L3_64_TABLE));
1515                          }                          }
1516                            if (l3->refcount != 0) {
1517                                    fatal("Huh? l3 Refcount problem.\n");
1518                                    exit(1);
1519                            }
1520                          l2->refcount ++;                          l2->refcount ++;
1521                  }                  }
1522                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1523                            fatal("INTERNAL ERROR L3 reuse\n");
1524                            exit(1);
1525                    }
1526    
1527                  l3->host_load[x3] = host_page;                  l3->host_load[x3] = host_page;
1528                  l3->host_store[x3] = writeflag? host_page : NULL;                  l3->host_store[x3] = writeflag? host_page : NULL;
1529                  l3->phys_addr[x3] = paddr_page;                  l3->phys_addr[x3] = paddr_page;
1530                  l3->phys_page[x3] = NULL;                  l3->phys_page[x3] = NULL;
1531                  l3->vaddr_to_tlbindex[x3] = r + 1;                  l3->vaddr_to_tlbindex[x3] = r + 1;
1532                  l3->refcount ++;                  l3->refcount ++;
1533    
1534    #ifdef BUGHUNT
1535    /*  Count how many pages are actually in use:  */
1536    {
1537            int n=0, i;
1538            for (i=0; i<=mask3; i++)
1539                    if (l3->vaddr_to_tlbindex[i])
1540                            n++;
1541            if (n != l3->refcount) {
1542                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1543                    exit(1);
1544            }
1545    
1546            n = 0;
1547            for (i=0; i<=mask3; i++)
1548                    if (l3->host_load[i] != NULL)
1549                            n++;
1550            if (n != l3->refcount) {
1551                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1552                    exit(1);
1553            }
1554    }
1555    #endif
1556    
1557  #endif  /* !MODE32  */  #endif  /* !MODE32  */
1558          } else {          } else {
1559                  /*                  /*
# Line 1501  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1606  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1606                                  l3->host_store[x3] = NULL;                                  l3->host_store[x3] = NULL;
1607                  } else {                  } else {
1608                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
1609    printf("HOST LOAD 2 set to %p\n", host_page);
1610                          l3->host_load[x3] = host_page;                          l3->host_load[x3] = host_page;
1611                          l3->host_store[x3] = writeflag? host_page : NULL;                          l3->host_store[x3] = writeflag? host_page : NULL;
1612                          l3->phys_addr[x3] = paddr_page;                          l3->phys_addr[x3] = paddr_page;
1613                  }                  }
1614    
1615    #ifdef BUGHUNT
1616    /*  Count how many pages are actually in use:  */
1617    {
1618            int n=0, i;
1619            for (i=0; i<=mask3; i++)
1620                    if (l3->vaddr_to_tlbindex[i])
1621                            n++;
1622            if (n != l3->refcount) {
1623                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1624                    exit(1);
1625            }
1626    
1627            n = 0;
1628            for (i=0; i<=mask3; i++)
1629                    if (l3->host_load[i] != NULL)
1630                            n++;
1631            if (n != l3->refcount) {
1632                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1633                    printf("Entry r = %i\n", r);
1634                    printf("Valid = %i\n",
1635    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1636                    exit(1);
1637            }
1638    }
1639    #endif
1640    
1641  #endif  /*  !MODE32  */  #endif  /*  !MODE32  */
1642          }          }
1643  }  }
# Line 1551  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1684  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1684    
1685  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1686          /*          /*
1687           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1688           *  Mark the page as containing a translation.           *  the page as containing a translation at this part of the page.
          *  
          *  (Special case for 32-bit mode: set the corresponding bit in the  
          *  phystranslation[] array.)  
1689           */           */
1690    
1691          /*  Make sure cur_physpage is in synch:  */          /*  Make sure cur_physpage is in synch:  */
1692          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1693              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;  
1694    
1695            {
1696                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1697                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1698                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1699                    x /= addr_per_translation_range;
1700    
1701                    cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
1702            }
1703    
1704          /*          /*
1705           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
# Line 1585  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1716  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1716  #endif  #endif
1717              ) {              ) {
1718                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1719                      cpu->machine->speed_tricks)                      cpu->machine->allow_instruction_combinations)
1720                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1721                              addr & (DYNTRANS_PAGESIZE - 1));                              addr & (DYNTRANS_PAGESIZE - 1));
1722          }          }

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

  ViewVC Help
Powered by ViewVC 1.1.26