/[gxemul]/trunk/src/cpus/cpu_dyntrans.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/cpu_dyntrans.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.99 2006/06/23 20:43:44 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
# Line 187  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 187  int DYNTRANS_CPU_RUN_INSTR(struct emul *
187           */           */
188          int show_opcode_statistics = 0;          int show_opcode_statistics = 0;
189    
190  #ifdef DYNTRANS_DUALMODE_32  #ifdef MODE32
         uint64_t cached_pc;  
 #else  
191          uint32_t cached_pc;          uint32_t cached_pc;
192    #else
193            uint64_t cached_pc;
194  #endif  #endif
195          int low_pc, n_instrs;          int low_pc, n_instrs;
196    
# Line 358  while (cycles-- > 0) Line 358  while (cycles-- > 0)
358    
359                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
360                              n_instrs + cpu->n_translated_instrs >=                              n_instrs + cpu->n_translated_instrs >=
361                              N_SAFE_DYNTRANS_LIMIT / 2)                              N_SAFE_DYNTRANS_LIMIT)
362                                  break;                                  break;
363                  }                  }
364          } else if (show_opcode_statistics) {          } else if (show_opcode_statistics) {
# Line 376  while (cycles-- > 0) Line 376  while (cycles-- > 0)
376    
377                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
378                              n_instrs + cpu->n_translated_instrs >=                              n_instrs + cpu->n_translated_instrs >=
379                              N_SAFE_DYNTRANS_LIMIT / 2)                              N_SAFE_DYNTRANS_LIMIT)
380                                  break;                                  break;
381                  }                  }
382          } else {          } else {
# Line 397  while (cycles-- > 0) Line 397  while (cycles-- > 0)
397    
398                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
399                              n_instrs + cpu->n_translated_instrs >=                              n_instrs + cpu->n_translated_instrs >=
400                              N_SAFE_DYNTRANS_LIMIT / 2)                              N_SAFE_DYNTRANS_LIMIT)
401                                  break;                                  break;
402                  }                  }
403          }          }
# Line 575  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 575  void DYNTRANS_FUNCTION_TRACE(struct cpu
575    
576    
577  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
   
 /*  forward declaration of to_be_translated and end_of_page:  */  
 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
   
 #ifdef DYNTRANS_DELAYSLOT  
 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
 #endif  
   
578  /*  /*
579   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
580   *   *
# Line 601  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 585  static void DYNTRANS_TC_ALLOCATE_DEFAULT
585          uint64_t physaddr)          uint64_t physaddr)
586  {  {
587          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
588    
         /*  Create the physpage header:  */  
589          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
590              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
   
         /*  TODO: Is this faster than copying an entire template page?  */  
         for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {  
                 ppp->ics[i].f =  
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 ppp->ics[i].arg[0] = 0;  
 #endif  
         }  
   
         /*  End-of-page:  */  
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =  
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page) :  
 #endif  
             instr(end_of_page);  
591    
592  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH          /*  Copy the entire template page first:  */
593          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
594  #endif              struct DYNTRANS_TC_PHYSPAGE));
595    
596          /*  End-of-page-2, for delay-slot architectures:  */          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
 #ifdef DYNTRANS_DELAYSLOT  
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =  
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page2) :  
 #endif  
             instr(end_of_page2);  
 #endif  
597    
598          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
599    
600          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
601          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
602          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
603  }  }
604  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 707  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 661  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
661    
662          if (!ok) {          if (!ok) {
663                  uint64_t paddr;                  uint64_t paddr;
664                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
665                          ok = cpu->translate_address(cpu, cached_pc,                          ok = cpu->translate_v2p(
666                              &paddr, FLAG_INSTR);                              cpu, cached_pc, &paddr, FLAG_INSTR);
667                  else {                  } else {
668                          paddr = cached_pc;                          paddr = cached_pc;
669                          ok = 1;                          ok = 1;
670                  }                  }
# Line 719  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 673  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
673                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
674                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
675    
676                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
677                              FLAG_INSTR);                              FLAG_INSTR);
678    
679                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
# Line 761  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 715  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
715                          host_page += (physaddr &                          host_page += (physaddr &
716                              ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);                              ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
717                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
718                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr & ~q);
719  #ifndef MODE32  #ifndef MODE32
720                          /*  Recalculate l2 and l3, since they might have                          /*  Recalculate l2 and l3, since they might have
721                              changed now:  */                              changed now:  */
# Line 772  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 726  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
726          }          }
727    
728          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
729                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
730                    fatal("[ dyntrans: resetting the translation cache ]\n");
731    #endif
732                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
733          }          }
734    
735            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
736    
737          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
738          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
739    
# Line 787  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 745  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
745          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
746                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
747                      + physpage_ofs);                      + physpage_ofs);
748    
749                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
750                  if (DYNTRANS_ADDR_TO_PAGENR(ppp->physaddr) == pagenr)                  if (ppp->physaddr == physaddr)
751                          break;                          break;
752    
753                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
754                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
755          }          }
# Line 904  have_it: Line 864  have_it:
864    
865    
866    
867  #ifdef DYNTRANS_INIT_64BIT_DUMMY_TABLES  #ifdef DYNTRANS_INIT_TABLES
868    
869    /*  forward declaration of to_be_translated and end_of_page:  */
870    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
871    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
872    #ifdef DYNTRANS_DUALMODE_32
873    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
874    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
875    #endif
876    
877    #ifdef DYNTRANS_DELAYSLOT
878    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
879    #ifdef DYNTRANS_DUALMODE_32
880    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
881    #endif
882    #endif
883    
884  /*  /*
885   *  XXX_init_64bit_dummy_tables():   *  XXX_init_tables():
886   *   *
887   *  Initializes 64-bit dummy tables and pointers.   *  Initializes the default translation page (for newly allocated pages), and
888     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
889   */   */
890  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(struct cpu *cpu)  void DYNTRANS_INIT_TABLES(struct cpu *cpu)
891  {  {
892    #ifndef MODE32
893          struct DYNTRANS_L2_64_TABLE *dummy_l2;          struct DYNTRANS_L2_64_TABLE *dummy_l2;
894          struct DYNTRANS_L3_64_TABLE *dummy_l3;          struct DYNTRANS_L3_64_TABLE *dummy_l3;
895          int x1, x2;          int x1, x2;
896    #endif
897            int i;
898            struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
899                struct DYNTRANS_TC_PHYSPAGE));
900    
901            if (ppp == NULL) {
902                    fprintf(stderr, "out of memory\n");
903                    exit(1);
904            }
905    
906            ppp->next_ofs = 0;
907            /*  ppp->physaddr is filled in by the page allocator  */
908    
909            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
910                    ppp->ics[i].f =
911    #ifdef DYNTRANS_DUALMODE_32
912                        cpu->is_32bit? instr32(to_be_translated) :
913    #endif
914                        instr(to_be_translated);
915    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
916                    ppp->ics[i].arg[0] = 0;
917    #endif
918            }
919    
920            /*  End-of-page:  */
921            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
922    #ifdef DYNTRANS_DUALMODE_32
923                cpu->is_32bit? instr32(end_of_page) :
924    #endif
925                instr(end_of_page);
926    
927    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
928            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;
929    #endif
930    
931            /*  End-of-page-2, for delay-slot architectures:  */
932    #ifdef DYNTRANS_DELAYSLOT
933            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
934    #ifdef DYNTRANS_DUALMODE_32
935                cpu->is_32bit? instr32(end_of_page2) :
936    #endif
937                instr(end_of_page2);
938    #endif
939    
940            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
941    
942    
943            /*  Prepare 64-bit virtual address translation tables:  */
944    #ifndef MODE32
945          if (cpu->is_32bit)          if (cpu->is_32bit)
946                  return;                  return;
947    
# Line 930  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st Line 956  void DYNTRANS_INIT_64BIT_DUMMY_TABLES(st
956    
957          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)          for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
958                  dummy_l2->l3[x2] = dummy_l3;                  dummy_l2->l3[x2] = dummy_l3;
959    #endif
960  }  }
961  #endif  /*  DYNTRANS_INIT_64BIT_DUMMY_TABLES  */  #endif  /*  DYNTRANS_INIT_TABLES  */
962    
963    
964    
# Line 1177  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1204  void DYNTRANS_INVALIDATE_TC_CODE(struct
1204                          prev_ppp = ppp;                          prev_ppp = ppp;
1205                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1206                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1207    
1208                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1209                              then we're done:  */                              then we're done:  */
1210                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1211                                  break;                                  break;
1212    
1213                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1214                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1215                  }                  }
# Line 1224  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1253  void DYNTRANS_INVALIDATE_TC_CODE(struct
1253  #endif  #endif
1254          }          }
1255    
1256          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1257          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;          for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
              r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {  
1258                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1259                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1260                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1281  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1309  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1309  #ifndef MODE32  #ifndef MODE32
1310          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1311  #endif  #endif
1312          int found, r, lowest_index, start, end, useraccess = 0;          int found, r, lowest_index, useraccess = 0;
1313    
1314  #ifdef MODE32  #ifdef MODE32
1315          uint32_t index;          uint32_t index;
# Line 1302  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1330  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1330              (uint64_t)paddr_page);  */              (uint64_t)paddr_page);  */
1331  #endif  #endif
1332    
1333            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1334            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1335    
1336          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1337                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1338                  useraccess = 1;                  useraccess = 1;
1339          }          }
1340    
         start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  
 #if 1  
         /*  Half of the TLB used for data, half for code:  */  
         if (writeflag & TLB_CODE) {  
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
 #endif  
   
1341          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1342          lowest_index = start;          lowest_index = 0;
1343    
1344  #ifdef MODE32  #ifdef MODE32
1345          /*          /*
# Line 1335  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1354  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1354              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1355          if (found < 0) {          if (found < 0) {
1356                  static unsigned int x = 0;                  static unsigned int x = 0;
1357                  lowest_index = (x % (end-start)) + start;                  lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
                 x ++;  
1358          }          }
1359  #else  #else
1360          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1361          found = -1;          found = -1;
1362          for (r=start; r<end; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1363                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1364                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
1365                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 1521  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1539  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1539                                              " slot! Not yet supported.\n");                                              " slot! Not yet supported.\n");
1540  #endif  #endif
1541                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1542                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1543                                  goto stop_running_translated;                                  goto stop_running_translated;
1544                          }                          }
1545          }          }

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

  ViewVC Help
Powered by ViewVC 1.1.26