/[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 41 by dpavlin, Mon Oct 8 16:22:11 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.147 2007/04/19 15:18:16 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.165 2007/06/15 21:43:53 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
# Line 51  static void gather_statistics(struct cpu Line 51  static void gather_statistics(struct cpu
51                  return;                  return;
52          }          }
53    
54            /*  low_pc must be within the page!  */
55            if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
56                    return;
57    
58          buf[0] = '\0';          buf[0] = '\0';
59    
60          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
# Line 64  static void gather_statistics(struct cpu Line 68  static void gather_statistics(struct cpu
68                          break;                          break;
69                  case 'p':                  case 'p':
70                          /*  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));  
71                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
72                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
73                          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 76  static void gather_statistics(struct cpu
76                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77                          if (cpu->is_32bit)                          if (cpu->is_32bit)
78                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
79                                      "0x%016"PRIx32, (uint32_t)a);                                      "0x%08"PRIx32, (uint32_t)a);
80                          else                          else
81                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
82                                      "0x%016"PRIx64, (uint64_t)a);                                      "0x%016"PRIx64, (uint64_t)a);
83                          break;                          break;
84                  case 'v':                  case 'v':
85                          /*  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));  
86                          a = cpu->pc;                          a = cpu->pc;
87                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
88                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
89                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
90                          if (cpu->is_32bit)                          if (cpu->is_32bit)
91                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
92                                      "0x%016"PRIx32, (uint32_t)a);                                      "0x%08"PRIx32, (uint32_t)a);
93                          else                          else
94                                  snprintf(buf + strlen(buf), sizeof(buf),                                  snprintf(buf + strlen(buf), sizeof(buf),
95                                      "0x%016"PRIx64, (uint64_t)a);                                      "0x%016"PRIx64, (uint64_t)a);
# Line 109  static void gather_statistics(struct cpu Line 105  static void gather_statistics(struct cpu
105  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
106    
107    
108  #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  
109    
110  /*  The normal instruction execution core:  */  /*  The normal instruction execution core:  */
111  #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);
112    
113    #else
114    
115  /*  For heavy debugging:  */  /*  For heavy debugging:  */
116  /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \  #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
117                  {       \                  {       \
118                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \                          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
119                              (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 122  static void gather_statistics(struct cpu
122                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \                              cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
123                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \                              ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
124                  } \                  } \
125                  ic->f(cpu, ic);  */                  ic->f(cpu, ic);
126    
127    #endif
128    
129  /*  static long long nr_of_I_calls = 0;  */  /*  static long long nr_of_I_calls = 0;  */
130    
# Line 161  static void gather_statistics(struct cpu Line 157  static void gather_statistics(struct cpu
157          }                                               \          }                                               \
158          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }          ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
159  */  */
 #endif  
160  #endif  /*  STATIC STUFF  */  #endif  /*  STATIC STUFF  */
161    
162    
# Line 306  int DYNTRANS_RUN_INSTR(struct cpu *cpu) Line 301  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
301                  I;                  I;
302    
303                  n_instrs = 1;                  n_instrs = 1;
         } else if (cpu->machine->cycle_accurate) {  
                 /*  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;  
                 }  
304          } else if (cpu->machine->statistics_enabled) {          } else if (cpu->machine->statistics_enabled) {
305                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
306                  n_instrs = 0;                  n_instrs = 0;
# Line 345  while (cycles-- > 0) Line 319  while (cycles-- > 0)
319                                  break;                                  break;
320                  }                  }
321          } else {          } else {
322                  /*  Execute multiple instructions:  */                  /*
323                     *  Execute multiple instructions:
324                     *
325                     *  (This is the core dyntrans loop.)
326                     */
327                  n_instrs = 0;                  n_instrs = 0;
328                    cpu->sampling = 1;
329    
330                  for (;;) {                  for (;;) {
331                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
332    
# Line 370  while (cycles-- > 0) Line 350  while (cycles-- > 0)
350                          if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)                          if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)
351                                  break;                                  break;
352                  }                  }
353    
354                    cpu->sampling = 0;
355          }          }
356    
357          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 439  while (cycles-- > 0) Line 421  while (cycles-- > 0)
421          }          }
422  #endif  #endif
423    
424            cpu->ninstrs += n_instrs;
425    
426            /*
427             *  Check if there are enough samples to decide whether or not to
428             *  perform native code generation:
429             */
430            if (cpu->sampling_curindex == N_PADDR_SAMPLES) {
431                    /*  TODO: Check against known blocks, etc.  */
432    
433                    cpu->sampling_curindex = 0;
434            }
435    
436          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
437          return n_instrs;          return n_instrs;
438  }  }
# Line 456  while (cycles-- > 0) Line 450  while (cycles-- > 0)
450   */   */
451  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)
452  {  {
453            int show_symbolic_function_name = 1;
454          char strbuf[50];          char strbuf[50];
455          char *symbol;          char *symbol;
456          uint64_t ot;          uint64_t ot;
# Line 476  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 471  void DYNTRANS_FUNCTION_TRACE(struct cpu
471                  n_args_to_print = n_args;                  n_args_to_print = n_args;
472          }          }
473    
474    #ifdef DYNTRANS_M88K
475            /*  Special hack for M88K userspace:  */
476            if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
477                    show_symbolic_function_name = 0;
478    #endif
479    
480          /*          /*
481           *  TODO: The type of each argument should be taken from the symbol           *  TODO: The type of each argument should be taken from the symbol
482           *  table, in some way.           *  table, in some way.
# 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 545  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 547  void DYNTRANS_FUNCTION_TRACE(struct cpu
547    
548    
549    
550    #ifdef DYNTRANS_TIMER_SAMPLE_TICK
551    /*
552     *  XXX_timer_sample_tick():
553     *
554     *  Gathers statistics about which translation blocks are being executed.
555     *  This can then be used to calculate if it is worth the effort to perform
556     *  native code generation (which is assumed to have a large overhead, but
557     *  will result in faster code).
558     */
559    void DYNTRANS_TIMER_SAMPLE_TICK(struct timer *timer, void *extra)
560    {
561            struct cpu *cpu = extra;
562            struct DYNTRANS_IC *next_ic;
563            size_t low_pc;
564            uint64_t paddr;
565    
566            /*
567             *  Don't sample if:
568             *
569             *  1)  Sampling is not enabled. It should only be enabled during
570             *      the core dyntrans loop.
571             *  2)  Enough samples have already been gathered.
572             */
573    
574            if (!cpu->sampling || cpu->sampling_curindex == N_PADDR_SAMPLES)
575                    return;
576    
577            /*  Get the physical address of the program counter:  */
578    
579            next_ic = cpu->cd.DYNTRANS_ARCH.next_ic;
580            low_pc = ((size_t)next_ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)
581                / sizeof(struct DYNTRANS_IC);
582    
583            /*  Not possible to represent as a physical address? Then abort.  */
584            if (low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
585                    return;
586    
587            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
588                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
589            paddr = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
590            paddr &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
591                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
592            paddr += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
593    
594            /*  ... and finally add the sample to the sampling array:  */
595            cpu->sampling_paddr[cpu->sampling_curindex ++] = paddr;
596    }
597    #endif  /*  DYNTRANS_TIMER_SAMPLE_TICK  */
598    
599    
600    
601  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
602  /*  /*
603   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
# Line 896  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 949  void DYNTRANS_INIT_TABLES(struct cpu *cp
949          int x1, x2;          int x1, x2;
950  #endif  #endif
951          int i;          int i;
952          struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(          struct DYNTRANS_TC_PHYSPAGE *ppp;
             struct DYNTRANS_TC_PHYSPAGE));  
953    
954          if (ppp == NULL) {          CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
955    
956          ppp->next_ofs = 0;          ppp->next_ofs = 0;
957          ppp->translations = 0;          ppp->translations = 0;
# Line 914  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 963  void DYNTRANS_INIT_TABLES(struct cpu *cp
963                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
964  #endif  #endif
965                      instr(to_be_translated);                      instr(to_be_translated);
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 ppp->ics[i].arg[0] = 0;  
 #endif  
966          }          }
967    
968          /*  End-of-page:  */          /*  End-of-page:  */
# Line 926  void DYNTRANS_INIT_TABLES(struct cpu *cp Line 972  void DYNTRANS_INIT_TABLES(struct cpu *cp
972  #endif  #endif
973              instr(end_of_page);              instr(end_of_page);
974    
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;  
 #endif  
   
975          /*  End-of-page-2, for delay-slot architectures:  */          /*  End-of-page-2, for delay-slot architectures:  */
976  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
977          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
# Line 1381  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1423  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1423  #ifdef MODE32  #ifdef MODE32
1424          uint32_t index;          uint32_t index;
1425          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
1426          paddr_page &= 0xffffffffULL;  
1427            if (paddr_page > 0xffffffffULL) {
1428                    fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1429                        " p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag,
1430                        paddr_page);
1431                    exit(1);
1432            }
1433    
1434          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1435              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1436              (int)paddr_page);  */              (int)paddr_page);  */
# Line 1406  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1455  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1455                  useraccess = 1;                  useraccess = 1;
1456          }          }
1457    
1458    #ifdef DYNTRANS_M88K
1459            /*  TODO  */
1460            if (useraccess)
1461                    return;
1462    #endif
1463    
1464          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1465    
1466  #ifdef MODE32  #ifdef MODE32
# Line 1479  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1534  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1534                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;                                  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1535                          } else {                          } else {
1536                                  int i;                                  int i;
1537                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =                                  CHECK_ALLOCATION(l2 =
1538                                      malloc(sizeof(struct DYNTRANS_L2_64_TABLE));                                      cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(
1539                                        sizeof(struct DYNTRANS_L2_64_TABLE)));
1540                                  l2->refcount = 0;                                  l2->refcount = 0;
1541                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)                                  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1542                                          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 1696  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1696          /*          /*
1697           *  Check for breakpoints.           *  Check for breakpoints.
1698           */           */
1699          if (!single_step_breakpoint) {          if (!single_step_breakpoint && !cpu->translation_readahead) {
1700                  MODE_uint_t curpc = cpu->pc;                  MODE_uint_t curpc = cpu->pc;
1701                  int i;                  int i;
1702                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->breakpoints.n; i++)
1703                          if (curpc == (MODE_uint_t)                          if (curpc == (MODE_uint_t)
1704                              cpu->machine->breakpoint_addr[i]) {                              cpu->machine->breakpoints.addr[i]) {
1705                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1706                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1707                                          quiet_mode = 0;                                          quiet_mode = 0;
1708                                          DISASSEMBLE(cpu, ib, 1, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1709                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1710                                  }                                  }
1711    #ifdef MODE32
1712                                    fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The "
1713                                        "instruction has not yet executed.)\n",
1714                                        (uint32_t)cpu->pc);
1715    #else
1716                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1717                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1718                                      (uint64_t)cpu->pc);                                      (uint64_t)cpu->pc);
1719    #endif
1720  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1721                                  if (cpu->delay_slot != NOT_DELAYED)                                  if (cpu->delay_slot != NOT_DELAYED)
1722                                          fatal("ERROR! Breakpoint in a delay"                                          fatal("ERROR! Breakpoint in a delay"
# Line 1695  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1757  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1757           *  be converted into a single function call.           *  be converted into a single function call.
1758           *           *
1759           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1760           *  instruction combination. For architectures with delay slots,           *  instruction combinations. For architectures with delay slots,
1761           *  we also ignore combinations if the delay slot is across a page           *  we also ignore combinations if the delay slot is across a page
1762           *  boundary.           *  boundary.
1763           */           */
# Line 1726  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v Line 1788  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].v
1788          }          }
1789    
1790          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1791    
1792            /*  (Except when doing read-ahead!)  */
1793            if (cpu->translation_readahead)
1794                    return;
1795    
1796            /*
1797             *  Special case when single-stepping: Execute the translated
1798             *  instruction, but then replace it with a "to be translated"
1799             *  directly afterwards.
1800             */
1801          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1802  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1803              || in_crosspage_delayslot              || in_crosspage_delayslot
1804  #endif  #endif
1805              ) {              ) {
                 /*  
                  *  Special case when single-stepping: Execute the translated  
                  *  instruction, but then replace it with a "to be translated"  
                  *  directly afterwards.  
                  */  
1806                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
 #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
                 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
 #endif  
1807                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1808                  ic->f =                  ic->f =
1809  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1810                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
1811  #endif  #endif
1812                      instr(to_be_translated);                      instr(to_be_translated);
1813  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
1814                  ic->arg[0] = 0;                  return;
1815            }
1816    
1817            /*  Translation read-ahead:  */
1818            if (!single_step && !cpu->machine->instruction_trace) {
1819                    /*  Do readahead:  */
1820                    int i = 1;
1821                    uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(cpu->pc);
1822                    uint64_t baseaddr = cpu->pc;
1823    
1824                    cpu->translation_readahead = MAX_DYNTRANS_READAHEAD;
1825    
1826                    while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1827                        (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1828                        cpu->translation_readahead > 0) {
1829                            void (*old_f)(struct cpu *,
1830                                struct DYNTRANS_IC *) = ic[i].f;
1831    
1832                            /*  Already translated? Then abort:  */
1833                            if (old_f != (
1834    #ifdef DYNTRANS_DUALMODE_32
1835                                cpu->is_32bit? instr32(to_be_translated) :
1836  #endif  #endif
1837          } else {                              instr(to_be_translated)))
1838  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                                  break;
                 cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];  
1839    
1840                  /*  Additional check, for variable length ISAs:  */                          /*  Translate the instruction:  */
1841                  if (ic->arg[0] == 0) {                          ic[i].f(cpu, ic+i);
1842                          fatal("INTERNAL ERROR: instr len = 0!\n");  
1843                          goto bad;                          /*  Translation failed? Then abort.  */
1844                            if (ic[i].f == old_f)
1845                                    break;
1846    
1847                            cpu->translation_readahead --;
1848                            ++i;
1849                  }                  }
 #endif  
1850    
1851                  /*  Finally finally :-), execute the instruction:  */                  cpu->translation_readahead = 0;
                 ic->f(cpu, ic);  
1852          }          }
1853    
1854    
1855            /*
1856             *  Finally finally :-), execute the instruction.
1857             *
1858             *  Note: The instruction might have changed during read-ahead, if
1859             *  instruction combinations are used.
1860             */
1861    
1862            ic->f(cpu, ic);
1863    
1864          return;          return;
1865    
1866    
# Line 1771  bad:   /* Line 1868  bad:   /*
1868           *  Nothing was translated. (Unimplemented or illegal instruction.)           *  Nothing was translated. (Unimplemented or illegal instruction.)
1869           */           */
1870    
1871            /*  Clear the translation, in case it was "half-way" done:  */
1872            ic->f =
1873    #ifdef DYNTRANS_DUALMODE_32
1874                cpu->is_32bit? instr32(to_be_translated) :
1875    #endif
1876                instr(to_be_translated);
1877    
1878            if (cpu->translation_readahead)
1879                    return;
1880    
1881          quiet_mode = 0;          quiet_mode = 0;
1882          fatal("to_be_translated(): TODO: unimplemented instruction");          fatal("to_be_translated(): TODO: unimplemented instruction");
1883    
# Line 1795  stop_running_translated: Line 1902  stop_running_translated:
1902          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1903          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1904    
1905    #ifdef DYNTRANS_DELAYSLOT
1906            /*  Special hack: If the bad instruction was in a delay slot,
1907                make sure that execution does not continue anyway:  */
1908            if (cpu->delay_slot)
1909                    cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT;
1910    #endif
1911    
1912          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1913          ic->f(cpu, ic);          ic->f(cpu, ic);
1914    

Legend:
Removed from v.41  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26