/[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 17 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 18 by dpavlin, Mon Oct 8 16:19:11 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.27 2005/10/27 14:01:13 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 1
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; ic->f(cpu, ic);
98    #else
99    #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
100    #endif
101    
102    
103  /*  /*
104   *  XXX_cpu_run_instr():   *  XXX_cpu_run_instr():
105   *   *
# Line 72  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 140  int DYNTRANS_CPU_RUN_INSTR(struct emul *
140          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
141          cpu->running_translated = 1;          cpu->running_translated = 1;
142    
143            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
144                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
145    
146          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace) {
147                  /*                  /*
148                   *  Single-step:                   *  Single-step:
# Line 122  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 193  int DYNTRANS_CPU_RUN_INSTR(struct emul *
193                              ~(COMBINATIONS | TRANSLATIONS);                              ~(COMBINATIONS | TRANSLATIONS);
194                  }                  }
195    
196                    if (show_opcode_statistics)
197                            S;
198    
199                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
200                  ic->f(cpu, ic);                  ic->f(cpu, ic);
201                  n_instrs = 1;                  n_instrs = 1;
202          } else {          } else if (show_opcode_statistics) {
203                  /*  Execute multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
204                  n_instrs = 0;                  n_instrs = 0;
205                  for (;;) {                  for (;;) {
206                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
207    
208  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                          S; I; S; I; S; I; S; I; S; I; S; I;
209  #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;
210  #else                          S; I; S; I; S; I; S; I; S; I; S; I;
211  #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  
212    
213                          I; I; I; I; I;   I; I; I; I; I;                          n_instrs += 24;
214                          I; I; I; I; I;   I; I; I; I; I;  
215                          I; I; I; I; I;   I; I; I; I; I;                          if (!cpu->running_translated ||
216                          I; I; I; I; I;   I; I; I; I; I;                              n_instrs + cpu->n_translated_instrs >= 16384)
217                          I; I; I; I; I;   I; I; I; I; I;                                  break;
218                    }
219            } else {
220                    /*  Execute multiple instructions:  */
221                    n_instrs = 0;
222                    for (;;) {
223                            struct DYNTRANS_IC *ic;
224    
225                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
226                          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 229  int DYNTRANS_CPU_RUN_INSTR(struct emul *
229                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
230    
231                          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;  
232    
233                          n_instrs += 120;                          n_instrs += 60;
234    
235                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
236                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >= 16384)
# Line 353  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 431  static void DYNTRANS_TC_ALLOCATE_DEFAULT
431              instr(end_of_page);              instr(end_of_page);
432    
433          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
434    
435            cpu->translation_cache_cur_ofs --;
436            cpu->translation_cache_cur_ofs |= 63;
437            cpu->translation_cache_cur_ofs ++;
438  }  }
439  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
440    
# Line 380  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 462  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
462  #ifdef MODE32  #ifdef MODE32
463          int index;          int index;
464          cached_pc = cpu->pc;          cached_pc = cpu->pc;
465          index = cached_pc >> 12;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
466  #else  #else
467  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
468          uint32_t a, b;          uint32_t a, b;
# Line 458  cpu->cd.arm.r[ARM_PC]); Line 540  cpu->cd.arm.r[ARM_PC]);
540                          }                          }
541                  }                  }
542                  cached_pc = cpu->pc;                  cached_pc = cpu->pc;
543    #ifdef MODE32
544                    index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
545    #endif
546                  physaddr = paddr;                  physaddr = paddr;
547          }          }
548    
549          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE)  #ifdef MODE32
550            if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
551                    unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
552                        physaddr, MEM_READ);
553                    if (host_page != NULL) {
554                            int q = DYNTRANS_PAGESIZE - 1;
555                            host_page += (physaddr &
556                                ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
557                            cpu->update_translation_table(cpu, cached_pc & ~q,
558                                host_page, TLB_CODE, physaddr & ~q);
559                    }
560            }
561    #endif
562    
563            if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
564                    fatal("[ dyntrans: resetting the translation cache ]\n");
565                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
566            }
567    
568          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
569          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
# Line 509  cpu->cd.arm.r[ARM_PC]); Line 610  cpu->cd.arm.r[ARM_PC]);
610                  vph_p->phys_page[b] = ppp;                  vph_p->phys_page[b] = ppp;
611  #endif  #endif
612    
613          cpu->invalidate_translation_caches_paddr(cpu, physaddr,          cpu->invalidate_translation_caches(cpu, physaddr,
614              JUST_MARK_AS_NON_WRITABLE);              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
615    
616          cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  /*      cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  */
617          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
618    
619          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 +
620              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
621    
# Line 549  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 651  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
651  #ifdef MODE32  #ifdef MODE32
652          int index;          int index;
653          cached_pc = cpu->pc;          cached_pc = cpu->pc;
654          index = cached_pc >> 12;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
655          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
656          if (ppp != NULL)          if (ppp != NULL)
657                  goto have_it;                  goto have_it;
# Line 587  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 689  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
689    
690          /*  Quick return path:  */          /*  Quick return path:  */
691  have_it:  have_it:
692          cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  /*      cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  */
693          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
694          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 +
695              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
# Line 610  have_it: Line 712  have_it:
712   *  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
713   *  NULL). Otherwise, the entire translation is removed.   *  NULL). Otherwise, the entire translation is removed.
714   */   */
715  void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,  static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
716  #ifdef MODE32  #ifdef MODE32
717          uint32_t          uint32_t
718  #else  #else
# Line 619  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 721  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
721          vaddr_page, int flags)          vaddr_page, int flags)
722  {  {
723  #ifdef MODE32  #ifdef MODE32
724          uint32_t index = vaddr_page >> 12;          uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
725    
726    #ifdef DYNTRANS_ARM
727            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3] &= ~(1 << (index & 7));
728    #endif
729    
730          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
731                  /*  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 736  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
736                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
737                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
738                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
739                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
740          }          }
741  #else  #else
742          /*  2-level:  */          /*  2-level:  */
# Line 686  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 793  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
793  #endif  #endif
794    
795    
796  #ifdef DYNTRANS_INVALIDATE_TC_PADDR  #ifdef DYNTRANS_INVALIDATE_TC
797  /*  /*
798   *  XXX_invalidate_translation_caches_paddr():   *  XXX_invalidate_translation_caches():
799   *   *
800   *  Invalidate all entries matching a specific physical address, a specific   *  Invalidate all entries matching a specific physical address, a specific
801   *  virtual address, or ALL entries.   *  virtual address, or ALL entries.
# Line 699  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 806  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
806   *  In the case when all translations are invalidated, paddr doesn't need   *  In the case when all translations are invalidated, paddr doesn't need
807   *  to be supplied.   *  to be supplied.
808   *   *
809   *  NOTE/TODO: Poorly choosen name for this function, as it can   *  NOTE/TODO: When invalidating a virtual address, it is only cleared from
810   *             invalidate based on virtual address as well.   *             the quick translation array, not from the linear
811     *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
812   */   */
813  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)
814  {  {
815          int r;          int r;
816  #ifdef MODE32  #ifdef MODE32
# Line 712  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 820  void DYNTRANS_INVALIDATE_TC_PADDR(struct
820  #endif  #endif
821              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);
822    
823            /*  Quick case for virtual addresses: see note above.  */
824            if (flags & INVALIDATE_VADDR) {
825                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
826                    return;
827            }
828    
829          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
830                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (
831                      (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==                      (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==
832                      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) ||  
833                      flags & INVALIDATE_ALL) ) {                      flags & INVALIDATE_ALL) ) {
834                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
835                              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 843  void DYNTRANS_INVALIDATE_TC_PADDR(struct
843                  }                  }
844          }          }
845  }  }
846  #endif  /*  DYNTRANS_INVALIDATE_TC_PADDR  */  #endif  /*  DYNTRANS_INVALIDATE_TC  */
847    
848    
849    
# Line 745  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 857  void DYNTRANS_INVALIDATE_TC_PADDR(struct
857  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)
858  {  {
859          int r;          int r;
860  #ifdef MODE_32  #ifdef MODE32
861          uint32_t          uint32_t
862  #else  #else
863          uint64_t          uint64_t
# Line 760  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 872  void DYNTRANS_INVALIDATE_TC_CODE(struct
872          if (flags & INVALIDATE_PADDR) {          if (flags & INVALIDATE_PADDR) {
873                  int pagenr, table_index;                  int pagenr, table_index;
874                  uint32_t physpage_ofs, *physpage_entryp;                  uint32_t physpage_ofs, *physpage_entryp;
875                  struct DYNTRANS_TC_PHYSPAGE *ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
876    
877                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
878    
879    #ifdef MODE32
880                    /*  If this page isn't marked as having any translations,
881                        then return immediately.  */
882                    if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]
883                        & 1 << (pagenr & 31)))
884                            return;
885                    /*  Remove the mark:  */
886                    cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=
887                        ~ (1 << (pagenr & 31));
888    #endif
889    
890                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
891    
892                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
893                      translation_cache)[table_index]);                      translation_cache)[table_index]);
894                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
895                  ppp = NULL;                  prev_ppp = ppp = NULL;
896    
897                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
898                  while (physpage_ofs != 0) {                  while (physpage_ofs != 0) {
899                            prev_ppp = ppp;
900                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
901                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
902                          /*  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 907  void DYNTRANS_INVALIDATE_TC_CODE(struct
907                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
908                  }                  }
909    
910                  /*  If the page was found, then we should invalidate all                  if (physpage_ofs == 0)
911                      code translations:  */                          ppp = NULL;
912    
913    #if 1
914                    /*
915                     *  "Bypass" the page, removing it from the code cache.
916                     *
917                     *  NOTE/TODO: This gives _TERRIBLE_ performance with self-
918                     *  modifying code, or when a single page is used for both
919                     *  code and (writable) data.
920                     */
921                    if (ppp != NULL) {
922                            if (prev_ppp != NULL)
923                                    prev_ppp->next_ofs = ppp->next_ofs;
924                            else
925                                    *physpage_entryp = ppp->next_ofs;
926                    }
927    #else
928                    /*
929                     *  Instead of removing the page from the code cache, each
930                     *  entry can be set to "to_be_translated". This is slow in
931                     *  the general case, but in the case of self-modifying code,
932                     *  it might be faster since we don't risk wasting cache
933                     *  memory as quickly (which would force unnecessary Restarts).
934                     */
935                  if (ppp != NULL) {                  if (ppp != NULL) {
936                          /*  TODO: Is this faster than copying an entire                          /*  TODO: Is this faster than copying an entire
937                              template page?  */                              template page?  */
# Line 795  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 943  void DYNTRANS_INVALIDATE_TC_CODE(struct
943  #endif  #endif
944                                      instr(to_be_translated);                                      instr(to_be_translated);
945                  }                  }
946    #endif
947          }          }
948    
949          /*  Invalidate entries in the VPH table:  */          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */
950          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;
951                 r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
952                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
953                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
954                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 809  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 959  void DYNTRANS_INVALIDATE_TC_CODE(struct
959                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||
960                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
961  #ifdef MODE32  #ifdef MODE32
962                                  uint32_t index = vaddr_page >> 12;                                  uint32_t index =
963                                        DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
964                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
965                                    /*  Remove the mark:  */
966                                    index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);
967                                    cpu->cd.DYNTRANS_ARCH.phystranslation[
968                                        index >> 5] &= ~ (1 << (index & 31));
969  #else  #else
970                                  /*  2-level:  */                                  /*  2-level:  */
971  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 857  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1012  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1012          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1013  {  {
1014          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1015          int found, r, lowest_index;          int found, r, lowest_index, start, end, useraccess = 0;
1016    
1017  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
1018          uint32_t a, b;          uint32_t a, b;
# Line 884  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1039  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1039  #endif  #endif
1040  #endif  #endif
1041    
1042            if (writeflag & MEMORY_USER_ACCESS) {
1043                    writeflag &= ~MEMORY_USER_ACCESS;
1044                    useraccess = 1;
1045            }
1046    
1047            start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;
1048    #if 1
1049            /*  Half of the TLB used for data, half for code:  */
1050            if (writeflag & TLB_CODE) {
1051                    writeflag &= ~TLB_CODE;
1052                    start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1053            }
1054    #else
1055            /*  Data and code entries are mixed.  */
1056            end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1057    #endif
1058    
1059          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1060          found = -1; lowest_index = 0;          found = -1; lowest_index = start;
1061          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1062          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {  
1063    #ifdef MODE32
1064            /*  NOTE: vaddr_to_tlbindex is one more than the index, so that
1065                0 becomes -1, which means a miss.  */
1066            found = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1067                DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1068            if (found < 0)
1069                    lowest_index = (random() % (end-start)) + start;
1070            if (0)
1071    #endif
1072    
1073            for (r=start; r<end; r++) {
1074                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1075                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
1076                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 959  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1142  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1142                  vph_p->phys_page[b] = NULL;                  vph_p->phys_page[b] = NULL;
1143  #else  #else
1144  #ifdef MODE32  #ifdef MODE32
1145                  index = vaddr_page >> 12;                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1146                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1147                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1148                      writeflag? host_page : NULL;                      writeflag? host_page : NULL;
1149                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1150                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1151                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1152    #ifdef DYNTRANS_ARM
1153                    if (useraccess)
1154                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]
1155                                |= 1 << (index & 7);
1156    #endif
1157  #endif  /*  32  */  #endif  /*  32  */
1158  #endif  /*  !ALPHA  */  #endif  /*  !ALPHA  */
1159          } else {          } else {
# Line 974  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1163  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1163                   *      Writeflag = 1:  Make sure the page is writable.                   *      Writeflag = 1:  Make sure the page is writable.
1164                   *      Writeflag = -1: Downgrade to readonly.                   *      Writeflag = -1: Downgrade to readonly.
1165                   */                   */
1166                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[found].timestamp =                  r = found;
1167                      highest + 1;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1168                  if (writeflag == 1)                  if (writeflag == 1)
1169                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1170                  if (writeflag == -1)                  if (writeflag == -1)
# Line 1002  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1191  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1191                  }                  }
1192  #else  #else
1193  #ifdef MODE32  #ifdef MODE32
1194                  index = vaddr_page >> 12;                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1195                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1196    #ifdef DYNTRANS_ARM
1197                    cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]&=~(1<<(index&7));
1198                    if (useraccess)
1199                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]
1200                                |= 1 << (index & 7);
1201    #endif
1202                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1203                          if (writeflag == 1)                          if (writeflag == 1)
1204                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
# Line 1067  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1262  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1262  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1263          /*          /*
1264           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated.
1265             *  Mark the page as containing a translation.
1266             *
1267             *  (Special case for 32-bit mode: set the corresponding bit in the
1268             *  phystranslation[] array.)
1269           */           */
1270          translated;  #ifdef MODE32
1271            if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1272                    uint32_t index = DYNTRANS_ADDR_TO_PAGENR(addr);
1273                    cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1274                        (1 << (index & 31));
1275            }
1276    #endif
1277            cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;
1278    
1279    
1280          /*          /*
1281           *  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 1284  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1284           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1285           *  instruction combination.           *  instruction combination.
1286           */           */
1287          if (!single_step && !cpu->machine->instruction_trace)          if (!single_step && !cpu->machine->instruction_trace) {
1288                  COMBINE_INSTRUCTIONS(cpu, ic, addr);                  if (cpu->combination_check != NULL &&
1289                        cpu->machine->speed_tricks)
1290                            cpu->combination_check(cpu, ic,
1291                                addr & (DYNTRANS_PAGESIZE - 1));
1292                    cpu->combination_check = NULL;
1293            }
1294    
1295          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1296          if (single_step_breakpoint) {          if (single_step_breakpoint) {

Legend:
Removed from v.17  
changed lines
  Added in v.18

  ViewVC Help
Powered by ViewVC 1.1.26