/[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 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.19 2005/10/07 22:10:51 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.41 2005/11/23 22:03:31 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  #ifdef  DYNTRANS_CPU_RUN_INSTR
35    static void gather_statistics(struct cpu *cpu)
36    {
37            uint64_t a;
38            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
39                cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
40            if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
41                    return;
42    
43    #if 0
44            /*  Use the physical address:  */
45            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
46                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
47            a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
48    #else
49            /*  Use the PC (virtual address):  */
50            a = cpu->pc;
51    #endif
52    
53            a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
54                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
55            a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
56    
57            /*
58             *  TODO: Everything below this line should be cleaned up :-)
59             */
60    a &= 0x03ffffff;
61    {
62            static long long *array = NULL;
63            static char *array_16kpage_in_use = NULL;
64            static int n = 0;
65            a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;
66            if (array == NULL)
67                    array = zeroed_alloc(sizeof(long long) * 16384*1024);
68            if (array_16kpage_in_use == NULL)
69                    array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);
70            a &= (16384*1024-1);
71            array[a] ++;
72            array_16kpage_in_use[a / 16384] = 1;
73            n++;
74            if ((n & 0x3fffffff) == 0) {
75                    FILE *f = fopen("statistics.out", "w");
76                    int i, j;
77                    printf("Saving statistics... "); fflush(stdout);
78                    for (i=0; i<1024; i++)
79                            if (array_16kpage_in_use[i]) {
80                                    for (j=0; j<16384; j++)
81                                            if (array[i*16384 + j] > 0)
82                                                    fprintf(f, "%lli\t0x%016llx\n",
83                                                        (long long)array[i*16384+j],
84                                                        (long long)((i*16384+j) <<
85                                    DYNTRANS_INSTR_ALIGNMENT_SHIFT));
86                            }
87                    fclose(f);
88                    printf("n=0x%08x\n", n);
89            }
90    }
91    }
92    
93    
94    #define S               gather_statistics(cpu)
95    
96    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
97    #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \
98                            cpu->cd.DYNTRANS_ARCH.next_ic += ic->len;       \
99                            ic->f(cpu, ic);
100    #else
101    #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
102    #endif
103    
104    
105  /*  /*
106   *  XXX_cpu_run_instr():   *  XXX_cpu_run_instr():
107   *   *
# Line 66  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 136  int DYNTRANS_CPU_RUN_INSTR(struct emul *
136          if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I))          if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I))
137                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
138  #endif  #endif
139    #ifdef DYNTRANS_PPC
140            if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
141                    ppc_exception(cpu, PPC_EXCEPTION_DEC);
142                    cpu->cd.ppc.dec_intr_pending = 0;
143            }
144            if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
145                    ppc_exception(cpu, PPC_EXCEPTION_EI);
146    #endif
147    
148          cached_pc = cpu->pc;          cached_pc = cpu->pc;
149    
150          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
151          cpu->running_translated = 1;          cpu->running_translated = 1;
152    
153            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
154                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
155    
156          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace) {
157                  /*                  /*
158                   *  Single-step:                   *  Single-step:
# Line 122  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 203  int DYNTRANS_CPU_RUN_INSTR(struct emul *
203                              ~(COMBINATIONS | TRANSLATIONS);                              ~(COMBINATIONS | TRANSLATIONS);
204                  }                  }
205    
206                    if (show_opcode_statistics)
207                            S;
208    
209                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
210                  ic->f(cpu, ic);                  ic->f(cpu, ic);
211                  n_instrs = 1;                  n_instrs = 1;
212          } else {          } else if (show_opcode_statistics) {
213                  /*  Execute multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
214                  n_instrs = 0;                  n_instrs = 0;
215                  for (;;) {                  for (;;) {
216                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
217    
218  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                          S; I; S; I; S; I; S; I; S; I; S; I;
219  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic; ic->f(cpu, ic);                          S; I; S; I; S; I; S; I; S; I; S; I;
220  #else                          S; I; S; I; S; I; S; I; S; I; S; I;
221  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);                          S; I; S; I; S; I; S; I; S; I; S; I;
 #endif  
222    
223                          I; I; I; I; I;   I; I; I; I; I;                          n_instrs += 24;
224                          I; I; I; I; I;   I; I; I; I; I;  
225                          I; I; I; I; I;   I; I; I; I; I;                          if (!cpu->running_translated ||
226                          I; I; I; I; I;   I; I; I; I; I;                              n_instrs + cpu->n_translated_instrs >= 16384)
227                          I; I; I; I; I;   I; I; I; I; I;                                  break;
228                    }
229            } else {
230                    /*  Execute multiple instructions:  */
231                    n_instrs = 0;
232                    for (;;) {
233                            struct DYNTRANS_IC *ic;
234    
235                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
236                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
# Line 150  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 239  int DYNTRANS_CPU_RUN_INSTR(struct emul *
239                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
240    
241                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
                         I; I; I; I; I;   I; I; I; I; I;  
242    
243                          n_instrs += 120;                          n_instrs += 60;
244    
245                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
246                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >= 16384)
# Line 160  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 248  int DYNTRANS_CPU_RUN_INSTR(struct emul *
248                  }                  }
249          }          }
250    
251            n_instrs += cpu->n_translated_instrs;
252    
253          /*          /*  Synchronize the program counter:  */
          *  Update the program counter and return the correct number of  
          *  executed instructions:  
          */  
254          low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
255              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
   
256          if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {          if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {
 #ifdef DYNTRANS_ARM  
                 cpu->cd.arm.r[ARM_PC] &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1)<<2);  
                 cpu->cd.arm.r[ARM_PC] += (low_pc << 2);  
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
 #else  
257                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
258                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
259                  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);                  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);
 #endif  
260          } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {          } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {
261                  /*  Switch to next page:  */                  /*  Switch to next page:  */
 #ifdef DYNTRANS_ARM  
                 cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);  
                 cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE << 2);  
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
 #else  
262                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
263                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
264                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
265                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
 #endif  
         } else {  
                 /*  debug("debug: Outside a page (This is actually ok)\n");  */  
266          }          }
267    
268          return n_instrs + cpu->n_translated_instrs;  #ifdef DYNTRANS_PPC
269            /*  Update the Decrementer and Time base registers:  */
270            {
271                    uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
272                    cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
273                    if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1)
274                            cpu->cd.ppc.dec_intr_pending = 1;
275    
276                    old = cpu->cd.ppc.spr[SPR_TBL];
277                    cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
278                    if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)
279                            cpu->cd.ppc.spr[SPR_TBU] ++;
280            }
281    #endif
282    
283            /*  Return the nr of instructions executed:  */
284            return n_instrs;
285  }  }
286  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */
287    
# Line 274  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 361  void DYNTRANS_FUNCTION_TRACE(struct cpu
361  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
362                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
363  #endif  #endif
364    #ifdef DYNTRANS_NEWMIPS
365                        r[0         /*  TODO  */
366    #endif
367  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
368                      gpr[3                      gpr[3
369  #endif  #endif
# Line 353  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 443  static void DYNTRANS_TC_ALLOCATE_DEFAULT
443              instr(end_of_page);              instr(end_of_page);
444    
445          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
446    
447            cpu->translation_cache_cur_ofs --;
448            cpu->translation_cache_cur_ofs |= 63;
449            cpu->translation_cache_cur_ofs ++;
450  }  }
451  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
452    
# Line 371  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 465  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
465  #else  #else
466          uint64_t          uint64_t
467  #endif  #endif
468              cached_pc, physaddr;              cached_pc, physaddr = 0;
469          uint32_t physpage_ofs;          uint32_t physpage_ofs;
470          int ok, pagenr, table_index;          int ok, pagenr, table_index;
471          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
# Line 380  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 474  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
474  #ifdef MODE32  #ifdef MODE32
475          int index;          int index;
476          cached_pc = cpu->pc;          cached_pc = cpu->pc;
477          index = cached_pc >> 12;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
478  #else  #else
479  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
480          uint32_t a, b;          uint32_t a, b;
# Line 437  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 531  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
531                          ok = 1;                          ok = 1;
532                  }                  }
533                  if (!ok) {                  if (!ok) {
534  /*                          /*  fatal("TODO: instruction vaddr=>paddr translation"
                         fatal("TODO: instruction vaddr=>paddr translation"  
535                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                              " failed. vaddr=0x%llx\n", (long long)cached_pc);
536  fatal("!! cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */
537  cpu->cd.arm.r[ARM_PC]);  
 */  
538                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,
539                              FLAG_INSTR);                              FLAG_INSTR);
540  /*  
541  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> paddr = 0x%x\n",                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
542          (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
543  fatal("!? cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */
544  cpu->cd.arm.r[ARM_PC]);  
 */  
545                          if (!ok) {                          if (!ok) {
546                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
547                                      " address of the exception handler?");                                      " address of the exception handler?");
# Line 458  cpu->cd.arm.r[ARM_PC]); Line 549  cpu->cd.arm.r[ARM_PC]);
549                          }                          }
550                  }                  }
551                  cached_pc = cpu->pc;                  cached_pc = cpu->pc;
552    #ifdef MODE32
553                    index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
554    #endif
555                  physaddr = paddr;                  physaddr = paddr;
556          }          }
557    
558          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE)  #ifdef MODE32
559            if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
560                    unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
561                        physaddr, MEM_READ);
562                    if (host_page != NULL) {
563                            int q = DYNTRANS_PAGESIZE - 1;
564                            host_page += (physaddr &
565                                ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
566                            cpu->update_translation_table(cpu, cached_pc & ~q,
567                                host_page, TLB_CODE, physaddr & ~q);
568                    }
569            }
570    #endif
571    
572            if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
573                    debug("[ dyntrans: resetting the translation cache ]\n");
574                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
575            }
576    
577          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
578          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
# Line 509  cpu->cd.arm.r[ARM_PC]); Line 619  cpu->cd.arm.r[ARM_PC]);
619                  vph_p->phys_page[b] = ppp;                  vph_p->phys_page[b] = ppp;
620  #endif  #endif
621    
622          cpu->invalidate_translation_caches_paddr(cpu, physaddr,  #ifdef MODE32
623              JUST_MARK_AS_NON_WRITABLE);          /*  Small optimization: only mark the physical page as non-writable
624                if it did not contain translations. (Because if it does contain
625                translations, it is already non-writable.)  */
626            if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &
627                (1 << (pagenr & 31)))
628    #endif
629            cpu->invalidate_translation_caches(cpu, physaddr,
630                JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
631    
         cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  
632          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
633    
634          cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +          cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
635              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
636    
# Line 549  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 666  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
666  #ifdef MODE32  #ifdef MODE32
667          int index;          int index;
668          cached_pc = cpu->pc;          cached_pc = cpu->pc;
669          index = cached_pc >> 12;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
670          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
671          if (ppp != NULL)          if (ppp != NULL)
672                  goto have_it;                  goto have_it;
# Line 572  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 689  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
689                          goto have_it;                          goto have_it;
690          }          }
691  #else  #else
692            /*  Temporary, to avoid a compiler warning:  */
693            cached_pc = 0;
694            ppp = NULL;
695  #ifdef DYNTRANS_IA64  #ifdef DYNTRANS_IA64
696          fatal("IA64 todo\n");          fatal("IA64 todo\n");
697  #else  #else
698          fatal("Neither alpha, ia64, nor 32-bit? 1\n");          fatal("Neither alpha, ia64, nor 32-bit? 1\n");
         { char *p = (char *) 0; *p = 0; }  
699          exit(1);          exit(1);
700  #endif  #endif
701  #endif  #endif
# Line 586  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 705  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
705          return;          return;
706    
707          /*  Quick return path:  */          /*  Quick return path:  */
708    #if defined(MODE32) || defined(DYNTRANS_ALPHA)
709  have_it:  have_it:
         cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  
710          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
711          cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +          cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
712              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
# Line 595  have_it: Line 714  have_it:
714          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "
715              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,
716              (long long)table_index, (long long)physpage_ofs);  */              (long long)table_index, (long long)physpage_ofs);  */
717    #endif
718  }  }
719  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
720    
# Line 610  have_it: Line 730  have_it:
730   *  is just downgraded to non-writable (ie the host store page is set to   *  is just downgraded to non-writable (ie the host store page is set to
731   *  NULL). Otherwise, the entire translation is removed.   *  NULL). Otherwise, the entire translation is removed.
732   */   */
733  void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,  static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
734  #ifdef MODE32  #ifdef MODE32
735          uint32_t          uint32_t
736  #else  #else
# Line 619  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 739  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
739          vaddr_page, int flags)          vaddr_page, int flags)
740  {  {
741  #ifdef MODE32  #ifdef MODE32
742          uint32_t index = vaddr_page >> 12;          uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
743    
744    #ifdef DYNTRANS_ARM
745            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
746    #endif
747    
748          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
749                  /*  printf("JUST MARKING NON-W: vaddr 0x%08x\n",                  /*  printf("JUST MARKING NON-W: vaddr 0x%08x\n",
# Line 630  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 754  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
754                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
755                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
756                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
757                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
758          }          }
759  #else  #else
760          /*  2-level:  */          /*  2-level:  */
# Line 686  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 811  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
811  #endif  #endif
812    
813    
814  #ifdef DYNTRANS_INVALIDATE_TC_PADDR  #ifdef DYNTRANS_INVALIDATE_TC
815  /*  /*
816   *  XXX_invalidate_translation_caches_paddr():   *  XXX_invalidate_translation_caches():
817   *   *
818   *  Invalidate all entries matching a specific physical address, a specific   *  Invalidate all entries matching a specific physical address, a specific
819   *  virtual address, or ALL entries.   *  virtual address, or ALL entries.
# Line 699  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 824  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
824   *  In the case when all translations are invalidated, paddr doesn't need   *  In the case when all translations are invalidated, paddr doesn't need
825   *  to be supplied.   *  to be supplied.
826   *   *
827   *  NOTE/TODO: Poorly choosen name for this function, as it can   *  NOTE/TODO: When invalidating a virtual address, it is only cleared from
828   *             invalidate based on virtual address as well.   *             the quick translation array, not from the linear
829     *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
830   */   */
831  void DYNTRANS_INVALIDATE_TC_PADDR(struct cpu *cpu, uint64_t paddr, int flags)  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t paddr, int flags)
832  {  {
833          int r;          int r;
834  #ifdef MODE32  #ifdef MODE32
# Line 712  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 838  void DYNTRANS_INVALIDATE_TC_PADDR(struct
838  #endif  #endif
839              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);
840    
841            /*  fatal("invalidate(): ");  */
842    
843            /*  Quick case for virtual addresses: see note above.  */
844            if (flags & INVALIDATE_VADDR) {
845                    /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */
846                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
847                    return;
848            }
849    
850            if (flags & INVALIDATE_ALL) {
851                    /*  fatal("all\n");  */
852                    for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
853                            if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
854                                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
855                                        DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
856                                        0);
857                                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
858                            }
859                    }
860                    return;
861            }
862    
863            /*  fatal("paddr 0x%08x\n", (int)addr_page);  */
864    
865          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
866                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (
867                      (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==                      (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==
868                      addr_page && flags & INVALIDATE_PADDR) ||                      addr_page && flags & INVALIDATE_PADDR) ||
                     (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==  
                     addr_page && flags & INVALIDATE_VADDR) ||  
869                      flags & INVALIDATE_ALL) ) {                      flags & INVALIDATE_ALL) ) {
870                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
871                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
# Line 731  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 879  void DYNTRANS_INVALIDATE_TC_PADDR(struct
879                  }                  }
880          }          }
881  }  }
882  #endif  /*  DYNTRANS_INVALIDATE_TC_PADDR  */  #endif  /*  DYNTRANS_INVALIDATE_TC  */
883    
884    
885    
# Line 745  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 893  void DYNTRANS_INVALIDATE_TC_PADDR(struct
893  void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)  void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)
894  {  {
895          int r;          int r;
896  #ifdef MODE_32  #ifdef MODE32
897          uint32_t          uint32_t
898  #else  #else
899          uint64_t          uint64_t
# Line 760  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 908  void DYNTRANS_INVALIDATE_TC_CODE(struct
908          if (flags & INVALIDATE_PADDR) {          if (flags & INVALIDATE_PADDR) {
909                  int pagenr, table_index;                  int pagenr, table_index;
910                  uint32_t physpage_ofs, *physpage_entryp;                  uint32_t physpage_ofs, *physpage_entryp;
911                  struct DYNTRANS_TC_PHYSPAGE *ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
912    
913                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
914    
915    #ifdef MODE32
916                    /*  If this page isn't marked as having any translations,
917                        then return immediately.  */
918                    if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]
919                        & 1 << (pagenr & 31)))
920                            return;
921                    /*  Remove the mark:  */
922                    cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=
923                        ~ (1 << (pagenr & 31));
924    #endif
925    
926                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
927    
928                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
929                      translation_cache)[table_index]);                      translation_cache)[table_index]);
930                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
931                  ppp = NULL;                  prev_ppp = ppp = NULL;
932    
933                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
934                  while (physpage_ofs != 0) {                  while (physpage_ofs != 0) {
935                            prev_ppp = ppp;
936                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
937                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
938                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
# Line 782  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 943  void DYNTRANS_INVALIDATE_TC_CODE(struct
943                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
944                  }                  }
945    
946                  /*  If the page was found, then we should invalidate all                  if (physpage_ofs == 0)
947                      code translations:  */                          ppp = NULL;
948    
949    #if 1
950                    /*
951                     *  "Bypass" the page, removing it from the code cache.
952                     *
953                     *  NOTE/TODO: This gives _TERRIBLE_ performance with self-
954                     *  modifying code, or when a single page is used for both
955                     *  code and (writable) data.
956                     */
957                    if (ppp != NULL) {
958                            if (prev_ppp != NULL)
959                                    prev_ppp->next_ofs = ppp->next_ofs;
960                            else
961                                    *physpage_entryp = ppp->next_ofs;
962                    }
963    #else
964                    /*
965                     *  Instead of removing the page from the code cache, each
966                     *  entry can be set to "to_be_translated". This is slow in
967                     *  the general case, but in the case of self-modifying code,
968                     *  it might be faster since we don't risk wasting cache
969                     *  memory as quickly (which would force unnecessary Restarts).
970                     */
971                  if (ppp != NULL) {                  if (ppp != NULL) {
972                          /*  TODO: Is this faster than copying an entire                          /*  TODO: Is this faster than copying an entire
973                              template page?  */                              template page?  */
# Line 795  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 979  void DYNTRANS_INVALIDATE_TC_CODE(struct
979  #endif  #endif
980                                      instr(to_be_translated);                                      instr(to_be_translated);
981                  }                  }
982    #endif
983          }          }
984    
985          /*  Invalidate entries in the VPH table:  */          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */
986          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;
987                 r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
988                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
989                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
990                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 809  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 995  void DYNTRANS_INVALIDATE_TC_CODE(struct
995                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||
996                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
997  #ifdef MODE32  #ifdef MODE32
998                                  uint32_t index = vaddr_page >> 12;                                  uint32_t index =
999                                        DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1000                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1001                                    /*  Remove the mark:  */
1002                                    index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);
1003                                    cpu->cd.DYNTRANS_ARCH.phystranslation[
1004                                        index >> 5] &= ~ (1 << (index & 31));
1005  #else  #else
1006                                  /*  2-level:  */                                  /*  2-level:  */
1007  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 856  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1047  void DYNTRANS_INVALIDATE_TC_CODE(struct
1047  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1048          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1049  {  {
1050    #ifndef MODE32
1051          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1052          int found, r, lowest_index;  #endif
1053            int found, r, lowest_index, start, end, useraccess = 0;
1054    
1055  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
1056          uint32_t a, b;          uint32_t a, b;
# Line 884  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1077  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1077  #endif  #endif
1078  #endif  #endif
1079    
1080            if (writeflag & MEMORY_USER_ACCESS) {
1081                    writeflag &= ~MEMORY_USER_ACCESS;
1082                    useraccess = 1;
1083            }
1084    
1085            start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;
1086    #if 1
1087            /*  Half of the TLB used for data, half for code:  */
1088            if (writeflag & TLB_CODE) {
1089                    writeflag &= ~TLB_CODE;
1090                    start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1091            }
1092    #else
1093            /*  Data and code entries are mixed.  */
1094            end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1095    #endif
1096    
1097          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1098          found = -1; lowest_index = 0;          lowest_index = start;
1099    
1100    #ifdef MODE32
1101            /*
1102             *  NOTE 1: vaddr_to_tlbindex is one more than the index, so that
1103             *          0 becomes -1, which means a miss.
1104             *
1105             *  NOTE 2: When a miss occurs, instead of scanning the entire tlb
1106             *          for the entry with the lowest time stamp, just choosing
1107             *          one at random will work as well.
1108             */
1109            found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1110                DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1111            if (found < 0) {
1112                    static unsigned int x = 0;
1113                    lowest_index = (x % (end-start)) + start;
1114                    x ++;
1115            }
1116    #else
1117          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1118          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          found = -1;
1119            for (r=start; r<end; r++) {
1120                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1121                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
1122                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 903  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1132  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1132                          break;                          break;
1133                  }                  }
1134          }          }
1135    #endif
1136    
1137          if (found < 0) {          if (found < 0) {
1138                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting the oldest one:  */
# Line 918  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1148  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1148                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;
1149                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;
1150                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1151                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = writeflag;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1152                        writeflag & MEM_WRITE;
1153    #ifndef MODE32
1154                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1155    #endif
1156    
1157                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
1158  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 959  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1192  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1192                  vph_p->phys_page[b] = NULL;                  vph_p->phys_page[b] = NULL;
1193  #else  #else
1194  #ifdef MODE32  #ifdef MODE32
1195                  index = vaddr_page >> 12;                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1196                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1197                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1198                      writeflag? host_page : NULL;                      writeflag? host_page : NULL;
1199                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1200                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1201                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1202    #ifdef DYNTRANS_ARM
1203                    if (useraccess)
1204                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1205                                |= 1 << (index & 31);
1206    #endif
1207  #endif  /*  32  */  #endif  /*  32  */
1208  #endif  /*  !ALPHA  */  #endif  /*  !ALPHA  */
1209          } else {          } else {
# Line 972  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1211  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1211                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
1212                   *      Writeflag = 0:  Do nothing.                   *      Writeflag = 0:  Do nothing.
1213                   *      Writeflag = 1:  Make sure the page is writable.                   *      Writeflag = 1:  Make sure the page is writable.
1214                   *      Writeflag = -1: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1215                   */                   */
1216                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[found].timestamp =                  r = found;
1217                      highest + 1;  #ifndef MODE32
1218                  if (writeflag == 1)                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1219    #endif
1220                    if (writeflag & MEM_WRITE)
1221                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1222                  if (writeflag == -1)                  if (writeflag & MEM_DOWNGRADE)
1223                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
1224  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
1225                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
# Line 990  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1231  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1231                          vph_p = cpu->cd.alpha.vph_table0[a];                          vph_p = cpu->cd.alpha.vph_table0[a];
1232                  vph_p->phys_page[b] = NULL;                  vph_p->phys_page[b] = NULL;
1233                  if (vph_p->phys_addr[b] == paddr_page) {                  if (vph_p->phys_addr[b] == paddr_page) {
1234                          if (writeflag == 1)                          if (writeflag & MEM_WRITE)
1235                                  vph_p->host_store[b] = host_page;                                  vph_p->host_store[b] = host_page;
1236                          if (writeflag == -1)                          if (writeflag & MEM_DOWNGRADE)
1237                                  vph_p->host_store[b] = NULL;                                  vph_p->host_store[b] = NULL;
1238                  } else {                  } else {
1239                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
# Line 1002  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1243  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1243                  }                  }
1244  #else  #else
1245  #ifdef MODE32  #ifdef MODE32
1246                  index = vaddr_page >> 12;                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1247                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1248    #ifdef DYNTRANS_ARM
1249                    cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1250                    if (useraccess)
1251                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1252                                |= 1 << (index & 31);
1253    #endif
1254                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1255                          if (writeflag == 1)                          if (writeflag & MEM_WRITE)
1256                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1257                                      host_page;                                      host_page;
1258                          if (writeflag == -1)                          if (writeflag & MEM_DOWNGRADE)
1259                                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1260                  } else {                  } else {
1261                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
# Line 1067  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1314  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1314  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1315          /*          /*
1316           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated.
1317             *  Mark the page as containing a translation.
1318             *
1319             *  (Special case for 32-bit mode: set the corresponding bit in the
1320             *  phystranslation[] array.)
1321           */           */
1322          translated;  #ifdef MODE32
1323            if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1324                    uint32_t index = DYNTRANS_ADDR_TO_PAGENR(addr);
1325                    cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1326                        (1 << (index & 31));
1327            }
1328    #endif
1329            cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;
1330    
1331    
1332          /*          /*
1333           *  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 1077  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1336  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1336           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1337           *  instruction combination.           *  instruction combination.
1338           */           */
1339          if (!single_step && !cpu->machine->instruction_trace)          if (!single_step && !cpu->machine->instruction_trace) {
1340                  COMBINE_INSTRUCTIONS(cpu, ic, addr);                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1341                        cpu->machine->speed_tricks)
1342                            cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1343                                addr & (DYNTRANS_PAGESIZE - 1));
1344                    cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1345            }
1346    
1347          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1348          if (single_step_breakpoint) {          if (single_step_breakpoint) {

Legend:
Removed from v.14  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26