/[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 38 by dpavlin, Mon Oct 8 16:21:53 2007 UTC revision 44 by dpavlin, Mon Oct 8 16:22:56 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.145 2007/04/10 17:26:20 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.186 2007/07/20 09:03:33 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31     *
32     *  Note: This might be a bit hard to follow, if you are reading this source
33     *  code for the first time. It is basically a hack to implement "templates"
34     *  with normal C code, by using suitable defines/macros, and then including
35     *  this file.
36   */   */
37    
38    
# Line 45  static void gather_statistics(struct cpu Line 50  static void gather_statistics(struct cpu
50          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
51              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
52    
53          if (cpu->machine->statistics_file == NULL) {          if (cpu->machine->statistics.file == NULL) {
54                  fatal("statistics gathering with no filename set is"                  fatal("statistics gathering with no filename set is"
55                      " meaningless\n");                      " meaningless\n");
56                  return;                  return;
57          }          }
58    
59            /*  low_pc must be within the page!  */
60            if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
61                    return;
62    
63          buf[0] = '\0';          buf[0] = '\0';
64    
65          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {          while ((ch = cpu->machine->statistics.fields[i]) != '\0') {
66                  if (i != 0)                  if (i != 0)
67                          strlcat(buf, " ", sizeof(buf));                          strlcat(buf, " ", sizeof(buf));
68    
# Line 64  static void gather_statistics(struct cpu Line 73  static void gather_statistics(struct cpu
73                          break;                          break;
74                  case 'p':                  case 'p':
75                          /*  Physical program counter address:  */                          /*  Physical program counter address:  */
                         /*  (low_pc must be within the page!)  */  
                         if (low_pc < 0 ||  
                             low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
                                 strlcat(buf, "-", sizeof(buf));  
76                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
77                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
78                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
# Line 76  static void gather_statistics(struct cpu Line 81  static void gather_statistics(struct cpu
81                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
82                          if (cpu->is_32bit)                          if (cpu->is_32bit)
83                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
84                                      "0x%016"PRIx32, (uint32_t)a);                                      "0x%08"PRIx32, (uint32_t)a);
85                          else                          else
86                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
87                                      "0x%016"PRIx64, (uint64_t)a);                                      "0x%016"PRIx64, (uint64_t)a);
88                          break;                          break;
89                  case 'v':                  case 'v':
90                          /*  Virtual program counter address:  */                          /*  Virtual program counter address:  */
                         /*  (low_pc inside the page, or in a delay slot)  */  
                         if (low_pc < 0 ||  
                             low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE + 2)  
                                 strlcat(buf, "-", sizeof(buf));  
91                          a = cpu->pc;                          a = cpu->pc;
92                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
93                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
94                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
95                          if (cpu->is_32bit)                          if (cpu->is_32bit)
96                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
97                                      "0x%016"PRIx32, (uint32_t)a);                                      "0x%08"PRIx32, (uint32_t)a);
98                          else                          else
99                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
100                                      "0x%016"PRIx64, (uint64_t)a);                                      "0x%016"PRIx64, (uint64_t)a);
# Line 102  static void gather_statistics(struct cpu Line 103  static void gather_statistics(struct cpu
103                  i++;                  i++;
104          }          }
105    
106          fprintf(cpu->machine->statistics_file, "%s\n", buf);          fprintf(cpu->machine->statistics.file, "%s\n", buf);
107  }  }
108    
109    
110  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
111    
112    
113  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  #if 1
 #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  
                         cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \  
                         ic->f(cpu, ic);  
 #else  
114    
115  /*  The normal instruction execution core:  */  /*  The normal instruction execution core:  */
116  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
117    
118    #else
119    
120  /*  For heavy debugging:  */  /*  For heavy debugging:  */
121  /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
122                  {       \                  {       \
123                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
124                              (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \                              (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
# Line 128  static void gather_statistics(struct cpu Line 127  static void gather_statistics(struct cpu
127                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
128                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
129                  } \                  } \
130                  ic->f(cpu, ic);  */                  ic->f(cpu, ic);
131    
132    #endif
133    
134  /*  static long long nr_of_I_calls = 0;  */  /*  static long long nr_of_I_calls = 0;  */
135    
# Line 161  static void gather_statistics(struct cpu Line 162  static void gather_statistics(struct cpu
162          }                                               \          }                                               \
163          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
164  */  */
 #endif  
165  #endif  /*  STATIC STUFF  */  #endif  /*  STATIC STUFF  */
166    
167    
168    
169  #ifdef  DYNTRANS_RUN_INSTR  #ifdef  DYNTRANS_RUN_INSTR_DEF
170  /*  /*
171   *  XXX_run_instr():   *  XXX_run_instr():
172   *   *
# Line 176  static void gather_statistics(struct cpu Line 176  static void gather_statistics(struct cpu
176   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
177   *  0 if no instructions were executed.   *  0 if no instructions were executed.
178   */   */
179  int DYNTRANS_RUN_INSTR(struct cpu *cpu)  int DYNTRANS_RUN_INSTR_DEF(struct cpu *cpu)
180  {  {
181          MODE_uint_t cached_pc;          MODE_uint_t cached_pc;
182          int low_pc, n_instrs;          int low_pc, n_instrs;
# Line 204  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 204  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
204          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))
205                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
206  #endif  #endif
207    #ifdef DYNTRANS_M88K
208            if (cpu->cd.m88k.irq_asserted &&
209                !(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_IND))
210                    m88k_exception(cpu, M88K_EXCEPTION_INTERRUPT, 0);
211    #endif
212  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
213          {          {
214                  int enabled, mask;                  int enabled, mask;
# Line 299  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 304  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
304                          }                          }
305                  }                  }
306    
307                  if (cpu->machine->statistics_enabled)                  if (cpu->machine->statistics.enabled)
308                          S;                          S;
309    
310                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
311                  I;                  I;
312    
313                  n_instrs = 1;                  n_instrs = 1;
314          } else if (cpu->machine->cycle_accurate) {          } else if (cpu->machine->statistics.enabled) {
                 /*  Executing multiple instructions, and call devices'  
                     tick functions:  */  
                 n_instrs = 0;  
                 for (;;) {  
                         struct DYNTRANS_IC *ic;  
 /*  TODO: continue here  */  
 int64_t cycles = cpu->cd.avr.extra_cycles;  
                         I;  
                         n_instrs += 1;  
 cycles = cpu->cd.avr.extra_cycles - cycles + 1;  
 /*  The instruction took 'cycles' cycles.  */  
 /* printf("A\n"); */  
 while (cycles-- > 0)  
         cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);  
 /* printf("B\n"); */  
   
                         if (n_instrs + cpu->n_translated_instrs >=  
                             N_SAFE_DYNTRANS_LIMIT)  
                                 break;  
                 }  
         } else if (cpu->machine->statistics_enabled) {  
315                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
316                  n_instrs = 0;                  n_instrs = 0;
317                  for (;;) {                  for (;;) {
# Line 345  while (cycles-- > 0) Line 329  while (cycles-- > 0)
329                                  break;                                  break;
330                  }                  }
331          } else {          } else {
332                  /*  Execute multiple instructions:  */                  /*
333                     *  Execute multiple instructions:
334                     *
335                     *  (This is the core dyntrans loop.)
336                     */
337                  n_instrs = 0;                  n_instrs = 0;
338    
339                  for (;;) {                  for (;;) {
340                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
341    
# Line 439  while (cycles-- > 0) Line 428  while (cycles-- > 0)
428          }          }
429  #endif  #endif
430    
431            cpu->ninstrs += n_instrs;
432    
433          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
434          return n_instrs;          return n_instrs;
435  }  }
# Line 446  while (cycles-- > 0) Line 437  while (cycles-- > 0)
437    
438    
439    
440  #ifdef DYNTRANS_FUNCTION_TRACE  #ifdef DYNTRANS_FUNCTION_TRACE_DEF
441  /*  /*
442   *  XXX_cpu_functioncall_trace():   *  XXX_cpu_functioncall_trace():
443   *   *
# Line 454  while (cycles-- > 0) Line 445  while (cycles-- > 0)
445   *  like    <f()>  or  <0x1234()>   on a function call. It is up to this   *  like    <f()>  or  <0x1234()>   on a function call. It is up to this
446   *  function to print the arguments passed.   *  function to print the arguments passed.
447   */   */
448  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)  void DYNTRANS_FUNCTION_TRACE_DEF(struct cpu *cpu, uint64_t f, int n_args)
449  {  {
450            int show_symbolic_function_name = 1;
451          char strbuf[50];          char strbuf[50];
452          char *symbol;          char *symbol;
453          uint64_t ot;          uint64_t ot;
# Line 463  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 455  void DYNTRANS_FUNCTION_TRACE(struct cpu
455  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
456              6              6
457  #else  #else
458  #ifdef DYNTRANS_SH  #if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K)
459              8   /*  Both for 32-bit and 64-bit SuperH  */              8   /*  Both for 32-bit and 64-bit SuperH, and M88K  */
460  #else  #else
461              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
462  #endif  #endif
# Line 476  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 468  void DYNTRANS_FUNCTION_TRACE(struct cpu
468                  n_args_to_print = n_args;                  n_args_to_print = n_args;
469          }          }
470    
471    #ifdef DYNTRANS_M88K
472            /*  Special hack for M88K userspace:  */
473            if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
474                    show_symbolic_function_name = 0;
475    #endif
476    
477          /*          /*
478           *  TODO: The type of each argument should be taken from the symbol           *  TODO: The type of each argument should be taken from the symbol
479           *  table, in some way.           *  table, in some way.
# Line 500  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 498  void DYNTRANS_FUNCTION_TRACE(struct cpu
498                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
499                      r[24                      r[24
500  #endif  #endif
 #ifdef DYNTRANS_M68K  
                     d[0         /*  TODO  */  
 #endif  
501  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
502                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
503  #endif  #endif
504    #ifdef DYNTRANS_M32R
505                        r[0         /*  r0..r3?  */
506    #endif
507    #ifdef DYNTRANS_M88K
508                        r[2         /*  r2..r9  */
509    #endif
510  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
511                      gpr[3                      gpr[3
512  #endif  #endif
# Line 525  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 526  void DYNTRANS_FUNCTION_TRACE(struct cpu
526                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))
527                          fatal("\"%s\"", memory_conv_to_string(cpu,                          fatal("\"%s\"", memory_conv_to_string(cpu,
528                              cpu->mem, d, strbuf, sizeof(strbuf)));                              cpu->mem, d, strbuf, sizeof(strbuf)));
529                  else if (symbol != NULL && ot == 0)                  else if (symbol != NULL && ot == 0 &&
530                        show_symbolic_function_name)
531                          fatal("&%s", symbol);                          fatal("&%s", symbol);
532                  else {                  else {
533                          if (cpu->is_32bit)                          if (cpu->is_32bit)
# Line 541  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 543  void DYNTRANS_FUNCTION_TRACE(struct cpu
543          if (print_dots)          if (print_dots)
544                  fatal(",..");                  fatal(",..");
545  }  }
546  #endif  #endif  /*  DYNTRANS_FUNCTION_TRACE_DEF  */
547    
548    
549    
550  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF
551  /*  /*
552   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
553   *   *
554   *  Create a default page (with just pointers to instr(to_be_translated)   *  Create a default page (with just pointers to instr(to_be_translated)
555   *  at cpu->translation_cache_cur_ofs.   *  at cpu->translation_cache_cur_ofs.
556   */   */
557  static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE(struct cpu *cpu,  static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF(struct cpu *cpu,
558          uint64_t physaddr)          uint64_t physaddr)
559  {  {
560          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
# Line 569  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 571  static void DYNTRANS_TC_ALLOCATE_DEFAULT
571          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
572    
573          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
574          cpu->translation_cache_cur_ofs |= 127;          cpu->translation_cache_cur_ofs |= 63;
575          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
576  }  }
577  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF  */
578    
579    
580    
# Line 785  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 787  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
787           *  as non-writable. If there are already translations, then it           *  as non-writable. If there are already translations, then it
788           *  should already have been marked as non-writable.           *  should already have been marked as non-writable.
789           */           */
790          if (ppp->translations == 0) {          if (ppp->translations_bitmap == 0) {
791                  cpu->invalidate_translation_caches(cpu, physaddr,                  cpu->invalidate_translation_caches(cpu, physaddr,
792                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
793          }          }
# Line 875  static void instr32(to_be_translated)(st Line 877  static void instr32(to_be_translated)(st
877  static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
878  #endif  #endif
879    
880    #ifdef DYNTRANS_DUALMODE_32
881    #define TO_BE_TRANSLATED    ( cpu->is_32bit? instr32(to_be_translated) : \
882                                  instr(to_be_translated) )
883    #else
884    #define TO_BE_TRANSLATED    ( instr(to_be_translated) )
885    #endif
886    
887  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
888  static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
889  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
# Line 896  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 905  void DYNTRANS_INIT_TABLES(struct cpu *cp
905          int x1, x2;          int x1, x2;
906  #endif  #endif
907          int i;          int i;
908          struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(          struct DYNTRANS_TC_PHYSPAGE *ppp;
             struct DYNTRANS_TC_PHYSPAGE));  
909    
910          if (ppp == NULL) {          CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
911    
912          ppp->next_ofs = 0;          ppp->next_ofs = 0;
913          ppp->translations = 0;          ppp->translations_bitmap = 0;
914            ppp->translation_ranges_ofs = 0;
915          /*  ppp->physaddr is filled in by the page allocator  */          /*  ppp->physaddr is filled in by the page allocator  */
916    
917          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
918                  ppp->ics[i].f =                  ppp->ics[i].f = TO_BE_TRANSLATED;
 #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  
         }  
919    
920          /*  End-of-page:  */          /*  End-of-page:  */
921          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
# Line 926  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 924  void DYNTRANS_INIT_TABLES(struct cpu *cp
924  #endif  #endif
925              instr(end_of_page);              instr(end_of_page);
926    
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;  
 #endif  
   
927          /*  End-of-page-2, for delay-slot architectures:  */          /*  End-of-page-2, for delay-slot architectures:  */
928  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
929          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
# Line 1301  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1295  void DYNTRANS_INVALIDATE_TC_CODE(struct
1295                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1296                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1297                   */                   */
1298                  if (ppp != NULL && ppp->translations != 0) {                  if (ppp != NULL && ppp->translations_bitmap != 0) {
1299                          uint32_t x = ppp->translations; /*  TODO:                          uint32_t x = ppp->translations_bitmap;  /*  TODO:
1300                                  urk Should be same type as ppp->translations */                                  urk Should be same type as the bitmap */
1301                          int i, j, n, m;                          int i, j, n, m;
1302                          n = 8 * sizeof(x);                          n = 8 * sizeof(x);
1303                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
# Line 1312  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1306  void DYNTRANS_INVALIDATE_TC_CODE(struct
1306                                  if (x & 1) {                                  if (x & 1) {
1307                                          for (j=0; j<m; j++)                                          for (j=0; j<m; j++)
1308                                                  ppp->ics[i*m + j].f =                                                  ppp->ics[i*m + j].f =
1309  #ifdef DYNTRANS_DUALMODE_32                                                      TO_BE_TRANSLATED;
                                                     cpu->is_32bit?  
                                                     instr32(to_be_translated) :  
 #endif  
                                                     instr(to_be_translated);  
1310                                  }                                  }
1311    
1312                                  x >>= 1;                                  x >>= 1;
1313                          }                          }
1314    
1315                          ppp->translations = 0;                          ppp->translations_bitmap = 0;
1316    
1317                            /*  Clear the list of translatable ranges:  */
1318                            if (ppp->translation_ranges_ofs != 0) {
1319                                    struct physpage_ranges *physpage_ranges =
1320                                        (struct physpage_ranges *)
1321                                        (cpu->translation_cache +
1322                                        ppp->translation_ranges_ofs);
1323                                    physpage_ranges->next_ofs = 0;
1324                                    physpage_ranges->n_entries_used = 0;
1325                            }
1326                  }                  }
1327  #endif  #endif
1328          }          }
# Line 1381  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1381  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1381  #ifdef MODE32  #ifdef MODE32
1382          uint32_t index;          uint32_t index;
1383          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
1384          paddr_page &= 0xffffffffULL;  
1385            if (paddr_page > 0xffffffffULL) {
1386                    fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1387                        " p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag,
1388                        paddr_page);
1389                    exit(1);
1390            }
1391    
1392          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1393              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1394              (int)paddr_page);  */              (int)paddr_page);  */
# Line 1406  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1413  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1413                  useraccess = 1;                  useraccess = 1;
1414          }          }
1415    
1416    #ifdef DYNTRANS_M88K
1417            /*  TODO  */
1418            if (useraccess)
1419                    return;
1420    #endif
1421    
1422          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1423    
1424  #ifdef MODE32  #ifdef MODE32
# Line 1479  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1492  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1492                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1493                          } else {                          } else {
1494                                  int i;                                  int i;
1495                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  CHECK_ALLOCATION(l2 =
1496                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(
1497                                        sizeof(struct DYNTRANS_L2_64_TABLE)));
1498                                  l2->refcount = 0;                                  l2->refcount = 0;
1499                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1500                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.                                          l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
# Line 1640  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1654  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1654          /*          /*
1655           *  Check for breakpoints.           *  Check for breakpoints.
1656           */           */
1657          if (!single_step_breakpoint) {          if (!single_step_breakpoint && !cpu->translation_readahead) {
1658                  MODE_uint_t curpc = cpu->pc;                  MODE_uint_t curpc = cpu->pc;
1659                  int i;                  int i;
1660                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->breakpoints.n; i++)
1661                          if (curpc == (MODE_uint_t)                          if (curpc == (MODE_uint_t)
1662                              cpu->machine->breakpoint_addr[i]) {                              cpu->machine->breakpoints.addr[i]) {
1663                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1664                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1665                                          quiet_mode = 0;                                          quiet_mode = 0;
1666                                          DISASSEMBLE(cpu, ib, 1, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1667                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1668                                  }                                  }
1669    #ifdef MODE32
1670                                    fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The "
1671                                        "instruction has not yet executed.)\n",
1672                                        (uint32_t)cpu->pc);
1673    #else
1674                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1675                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1676                                      (uint64_t)cpu->pc);                                      (uint64_t)cpu->pc);
1677    #endif
1678  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1679                                  if (cpu->delay_slot != NOT_DELAYED)                                  if (cpu->delay_slot != NOT_DELAYED)
1680                                          fatal("ERROR! Breakpoint in a delay"                                          fatal("ERROR! Breakpoint in a delay"
# Line 1684  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1704  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1704          {          {
1705                  int x = addr & (DYNTRANS_PAGESIZE - 1);                  int x = addr & (DYNTRANS_PAGESIZE - 1);
1706                  int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *                  int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1707                      sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));                      sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->
1708                        translations_bitmap));
1709                  x /= addr_per_translation_range;                  x /= addr_per_translation_range;
1710    
1711                  cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);                  cpu->cd.DYNTRANS_ARCH.cur_physpage->
1712                        translations_bitmap |= (1 << x);
1713          }          }
1714    
1715    
1716          /*          /*
1717           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
1718           *  be converted into a single function call.           *  be converted into a single function call.
1719           *           *
1720           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1721           *  instruction combination. For architectures with delay slots,           *  instruction combinations. For architectures with delay slots,
1722           *  we also ignore combinations if the delay slot is across a page           *  we also ignore combinations if the delay slot is across a page
1723           *  boundary.           *  boundary.
1724           */           */
# Line 1712  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1735  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1735          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1736    
1737          /*  An additional check, to catch some bugs:  */          /*  An additional check, to catch some bugs:  */
1738          if (ic->f == (          if (ic->f == TO_BE_TRANSLATED) {
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
             instr(to_be_translated))) {  
1739                  fatal("INTERNAL ERROR: ic->f not set!\n");                  fatal("INTERNAL ERROR: ic->f not set!\n");
1740                  goto bad;                  goto bad;
1741          }          }
# Line 1725  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1744  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1744                  goto bad;                  goto bad;
1745          }          }
1746    
1747          /*  ... and finally execute the translated instruction:  */  
1748            /*
1749             *  ... and finally execute the translated instruction:
1750             */
1751    
1752            /*  (Except when doing read-ahead!)  */
1753            if (cpu->translation_readahead)
1754                    return;
1755    
1756            /*
1757             *  Special case when single-stepping: Execute the translated
1758             *  instruction, but then replace it with a "to be translated"
1759             *  directly afterwards.
1760             */
1761          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1762  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1763              || in_crosspage_delayslot              || in_crosspage_delayslot
1764  #endif  #endif
1765              ) {              ) {
                 /*  
                  *  Special case when single-stepping: Execute the translated  
                  *  instruction, but then replace it with a "to be translated"  
                  *  directly afterwards.  
                  */  
1766                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
 #endif  
1767                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1768                  ic->f =                  ic->f = TO_BE_TRANSLATED;
1769  #ifdef DYNTRANS_DUALMODE_32                  return;
1770                      cpu->is_32bit? instr32(to_be_translated) :          }
 #endif  
                     instr(to_be_translated);  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 ic->arg[0] = 0;  
 #endif  
         } else {  
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
1771    
1772                  /*  Additional check, for variable length ISAs:  */          /*  Translation read-ahead:  */
1773                  if (ic->arg[0] == 0) {          if (!single_step && !cpu->machine->instruction_trace) {
1774                          fatal("INTERNAL ERROR: instr len = 0!\n");                  uint64_t baseaddr = cpu->pc;
1775                          goto bad;                  uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(baseaddr);
1776                    int i = 1;
1777    
1778                    cpu->translation_readahead = MAX_DYNTRANS_READAHEAD;
1779    
1780                    while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1781                        (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1782                        cpu->translation_readahead > 0) {
1783                            void (*old_f)(struct cpu *,
1784                                struct DYNTRANS_IC *) = ic[i].f;
1785    
1786                            /*  Already translated? Then abort:  */
1787                            if (old_f != TO_BE_TRANSLATED)
1788                                    break;
1789    
1790                            /*  Translate the instruction:  */
1791                            ic[i].f(cpu, ic+i);
1792    
1793                            /*  Translation failed? Then abort.  */
1794                            if (ic[i].f == old_f)
1795                                    break;
1796    
1797                            cpu->translation_readahead --;
1798                            ++i;
1799                  }                  }
 #endif  
1800    
1801                  /*  Finally finally :-), execute the instruction:  */                  cpu->translation_readahead = 0;
                 ic->f(cpu, ic);  
1802          }          }
1803    
1804    
1805            /*
1806             *  Finally finally :-), execute the instruction.
1807             *
1808             *  Note: The instruction might have changed during read-ahead, if
1809             *  instruction combinations are used.
1810             */
1811    
1812            ic->f(cpu, ic);
1813    
1814          return;          return;
1815    
1816    
# Line 1771  bad:   /* Line 1818  bad:   /*
1818           *  Nothing was translated. (Unimplemented or illegal instruction.)           *  Nothing was translated. (Unimplemented or illegal instruction.)
1819           */           */
1820    
1821            /*  Clear the translation, in case it was "half-way" done:  */
1822            ic->f = TO_BE_TRANSLATED;
1823    
1824            if (cpu->translation_readahead)
1825                    return;
1826    
1827          quiet_mode = 0;          quiet_mode = 0;
1828          fatal("to_be_translated(): TODO: unimplemented instruction");          fatal("to_be_translated(): TODO: unimplemented instruction");
1829    
1830          if (cpu->machine->instruction_trace)          if (cpu->machine->instruction_trace) {
1831  #ifdef MODE32                  if (cpu->is_32bit)
1832                  fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);                          fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1833  #else                  else
1834                  fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);                          fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1835  #endif          } else {
         else {  
1836                  fatal(":\n");                  fatal(":\n");
1837                  DISASSEMBLE(cpu, ib, 1, 0);                  DISASSEMBLE(cpu, ib, 1, 0);
1838          }          }
# Line 1795  stop_running_translated: Line 1847  stop_running_translated:
1847          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1848          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1849    
1850    #ifdef DYNTRANS_DELAYSLOT
1851            /*  Special hack: If the bad instruction was in a delay slot,
1852                make sure that execution does not continue anyway:  */
1853            if (cpu->delay_slot)
1854                    cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT;
1855    #endif
1856    
1857          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1858          ic->f(cpu, ic);          ic->f(cpu, ic);
1859    

Legend:
Removed from v.38  
changed lines
  Added in v.44

  ViewVC Help
Powered by ViewVC 1.1.26