/[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 18 by dpavlin, Mon Oct 8 16:19:11 2007 UTC revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_dyntrans.c,v 1.27 2005/10/27 14:01:13 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.54 2006/02/09 22:55:20 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    #if 1   /*  IC statistics:  */
36    static void gather_statistics(struct cpu *cpu)
37    {
38            struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
39            static long long n = 0;
40            static FILE *f = NULL;
41    
42            n++;
43            if (n < 100000000)
44                    return;
45    
46            if (f == NULL) {
47                    f = fopen("instruction_call_statistics.raw", "w");
48                    if (f == NULL) {
49                            fatal("Unable to open statistics file for output.\n");
50                            exit(1);
51                    }
52            }
53            fwrite(&ic->f, 1, sizeof(void *), f);
54    }
55    #else   /*  PC statistics:  */
56  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
57  {  {
58          uint64_t a;          uint64_t a;
# Line 40  static void gather_statistics(struct cpu Line 61  static void gather_statistics(struct cpu
61          if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)          if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
62                  return;                  return;
63    
64  #if 1  #if 0
65          /*  Use the physical address:  */          /*  Use the physical address:  */
66          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
67              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
# Line 89  a &= 0x03ffffff; Line 110  a &= 0x03ffffff;
110          }          }
111  }  }
112  }  }
113    #endif  /*  PC statistics  */
114    
115  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
116    
117  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
118  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic; ic->f(cpu, ic);  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \
119                            cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \
120                            ic->f(cpu, ic);
121  #else  #else
122  #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);
123  #endif  #endif
# Line 134  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 157  int DYNTRANS_CPU_RUN_INSTR(struct emul *
157          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))
158                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
159  #endif  #endif
160    #ifdef DYNTRANS_PPC
161            if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
162                    ppc_exception(cpu, PPC_EXCEPTION_DEC);
163                    cpu->cd.ppc.dec_intr_pending = 0;
164            }
165            if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
166                    ppc_exception(cpu, PPC_EXCEPTION_EI);
167    #endif
168    
169          cached_pc = cpu->pc;          cached_pc = cpu->pc;
170    
# Line 168  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 199  int DYNTRANS_CPU_RUN_INSTR(struct emul *
199                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
200                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_cpu_run_instr(): could not read "
201                                      "the instruction\n");                                      "the instruction\n");
202                          } else                          } else {
203                                  cpu_disassemble_instr(cpu->machine, cpu,                                  cpu_disassemble_instr(cpu->machine, cpu,
204                                      instr, 1, 0, 0);                                      instr, 1, 0, 0);
205    #ifdef DYNTRANS_MIPS
206    /*  TODO: generalize, not just MIPS  */
207                                    /*  Show the instruction in the delay slot,
208                                        if any:  */
209                                    fatal("TODO: check for delay slot!\n");
210    #endif
211                            }
212                  }                  }
213    
214                  /*  When single-stepping, multiple instruction calls cannot                  /*  When single-stepping, multiple instruction calls cannot
# Line 238  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 276  int DYNTRANS_CPU_RUN_INSTR(struct emul *
276                  }                  }
277          }          }
278    
279            n_instrs += cpu->n_translated_instrs;
280    
281          /*          /*  Synchronize the program counter:  */
          *  Update the program counter and return the correct number of  
          *  executed instructions:  
          */  
282          low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
283              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
   
284          if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {          if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {
 #ifdef DYNTRANS_ARM  
                 cpu->cd.arm.r[ARM_PC] &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1)<<2);  
                 cpu->cd.arm.r[ARM_PC] += (low_pc << 2);  
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
 #else  
285                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
286                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
287                  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);                  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);
 #endif  
288          } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {          } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {
289                  /*  Switch to next page:  */                  /*  Switch to next page:  */
 #ifdef DYNTRANS_ARM  
                 cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);  
                 cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE << 2);  
                 cpu->pc = cpu->cd.arm.r[ARM_PC];  
 #else  
290                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<                  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
291                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
292                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
293                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
294  #endif          } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE + 1) {
295          } else {                  /*  Switch to next page and skip an instruction which was
296                  /*  debug("debug: Outside a page (This is actually ok)\n");  */                      already executed (in a delay slot):  */
297                    cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
298                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
299                    cpu->pc += ((DYNTRANS_IC_ENTRIES_PER_PAGE + 1) <<
300                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
301          }          }
302    
303          return n_instrs + cpu->n_translated_instrs;  #ifdef DYNTRANS_PPC
304            /*  Update the Decrementer and Time base registers:  */
305            {
306                    uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
307                    cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
308                    if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
309                        && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
310                            cpu->cd.ppc.dec_intr_pending = 1;
311                    old = cpu->cd.ppc.spr[SPR_TBL];
312                    cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
313                    if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)
314                            cpu->cd.ppc.spr[SPR_TBU] ++;
315            }
316    #endif
317    
318            /*  Return the nr of instructions executed:  */
319            return n_instrs;
320  }  }
321  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */
322    
# Line 359  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 403  void DYNTRANS_FUNCTION_TRACE(struct cpu
403                      r[2                      r[2
404  #endif  #endif
405  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
406                      r_i[0                      r[24
407  #endif  #endif
408                      + x];                      + x];
409  #endif  #endif
# Line 391  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 435  void DYNTRANS_FUNCTION_TRACE(struct cpu
435    
436    
437  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
438    
439  /*  forward declaration of to_be_translated and end_of_page:  */  /*  forward declaration of to_be_translated and end_of_page:  */
440  static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
441  static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
# Line 398  static void instr(end_of_page)(struct cp Line 443  static void instr(end_of_page)(struct cp
443  static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
444  static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
445  #endif  #endif
446    
447    #ifdef DYNTRANS_DELAYSLOT
448    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
449    #ifdef DYNTRANS_DUALMODE_32
450    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
451    #endif
452    #endif
453    
454  /*  /*
455   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
456   *   *
# Line 424  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 477  static void DYNTRANS_TC_ALLOCATE_DEFAULT
477  #endif  #endif
478                      instr(to_be_translated);                      instr(to_be_translated);
479    
480          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE].f =          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
481  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
482              cpu->is_32bit? instr32(end_of_page) :              cpu->is_32bit? instr32(end_of_page) :
483  #endif  #endif
484              instr(end_of_page);              instr(end_of_page);
485    
486    #ifdef DYNTRANS_DELAYSLOT
487            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
488    #ifdef DYNTRANS_DUALMODE_32
489                cpu->is_32bit? instr32(end_of_page2) :
490    #endif
491                instr(end_of_page2);
492    #endif
493    
494          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
495    
496          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
# Line 453  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 514  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
514  #else  #else
515          uint64_t          uint64_t
516  #endif  #endif
517              cached_pc, physaddr;              cached_pc, physaddr = 0;
518          uint32_t physpage_ofs;          uint32_t physpage_ofs;
519          int ok, pagenr, table_index;          int ok, pagenr, table_index;
520          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
# Line 477  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 538  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
538          } else          } else
539                  vph_p = cpu->cd.alpha.vph_table0[a];                  vph_p = cpu->cd.alpha.vph_table0[a];
540  #else  #else
541  #ifdef DYNTRANS_IA64          fatal("Neither alpha nor 32-bit? 3\n");
         fatal("IA64 todo\n");  
 #else  
         fatal("Neither alpha, ia64, nor 32-bit? 3\n");  
542          exit(1);          exit(1);
543  #endif  #endif
544  #endif  #endif
 #endif  
545    
546          /*  Virtual to physical address translation:  */          /*  Virtual to physical address translation:  */
547          ok = 0;          ok = 0;
# Line 500  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 557  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
557                  ok = 1;                  ok = 1;
558          }          }
559  #else  #else
560  #ifdef DYNTRANS_IA64          fatal("Neither alpha nor 32-bit? 4\n");
         fatal("IA64 todo\n");  
 #else  
         fatal("Neither alpha, ia64, nor 32-bit? 4\n");  
561          exit(1);          exit(1);
562  #endif  #endif
563  #endif  #endif
 #endif  
564    
565          if (!ok) {          if (!ok) {
566                  uint64_t paddr;                  uint64_t paddr;
# Line 519  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 572  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
572                          ok = 1;                          ok = 1;
573                  }                  }
574                  if (!ok) {                  if (!ok) {
575  /*                          /*  fatal("TODO: instruction vaddr=>paddr translation"
                         fatal("TODO: instruction vaddr=>paddr translation"  
576                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                              " failed. vaddr=0x%llx\n", (long long)cached_pc);
577  fatal("!! cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */
578  cpu->cd.arm.r[ARM_PC]);  
 */  
579                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,
580                              FLAG_INSTR);                              FLAG_INSTR);
581  /*  
582  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> paddr = 0x%x\n",                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
583          (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
584  fatal("!? cpu->pc=0x%llx arm_pc=0x%x\n", (long long)cpu->pc,                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */
585  cpu->cd.arm.r[ARM_PC]);  
 */  
586                          if (!ok) {                          if (!ok) {
587                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
588                                      " address of the exception handler?");                                      " address of the exception handler?");
# Line 561  cpu->cd.arm.r[ARM_PC]); Line 611  cpu->cd.arm.r[ARM_PC]);
611  #endif  #endif
612    
613          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
614                  fatal("[ dyntrans: resetting the translation cache ]\n");                  debug("[ dyntrans: resetting the translation cache ]\n");
615                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
616          }          }
617    
# Line 610  cpu->cd.arm.r[ARM_PC]); Line 660  cpu->cd.arm.r[ARM_PC]);
660                  vph_p->phys_page[b] = ppp;                  vph_p->phys_page[b] = ppp;
661  #endif  #endif
662    
663    #ifdef MODE32
664            /*  Small optimization: only mark the physical page as non-writable
665                if it did not contain translations. (Because if it does contain
666                translations, it is already non-writable.)  */
667            if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &
668                (1 << (pagenr & 31)))
669    #endif
670          cpu->invalidate_translation_caches(cpu, physaddr,          cpu->invalidate_translation_caches(cpu, physaddr,
671              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);              JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
672    
 /*      cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  */  
673          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
674    
675          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 +
# Line 645  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 701  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
701  #else  #else
702          uint64_t          uint64_t
703  #endif  #endif
704              cached_pc;              cached_pc = cpu->pc;
705          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
706    
707  #ifdef MODE32  #ifdef MODE32
708          int index;          int index;
         cached_pc = cpu->pc;  
709          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
710          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
711          if (ppp != NULL)          if (ppp != NULL)
# Line 660  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 715  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
715          uint32_t a, b;          uint32_t a, b;
716          int kernel = 0;          int kernel = 0;
717          struct alpha_vph_page *vph_p;          struct alpha_vph_page *vph_p;
         cached_pc = cpu->pc;  
718          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
719          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);
720          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
# Line 674  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 728  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
728                          goto have_it;                          goto have_it;
729          }          }
730  #else  #else
731  #ifdef DYNTRANS_IA64          fatal("X1: cached_pc=%016llx\n", (long long)cached_pc);
732          fatal("IA64 todo\n");          /*  Temporary, to avoid a compiler warning:  */
733  #else          ppp = NULL;
734          fatal("Neither alpha, ia64, nor 32-bit? 1\n");          fatal("Neither alpha nor 32-bit? 1\n");
         { char *p = (char *) 0; *p = 0; }  
735          exit(1);          exit(1);
736  #endif  #endif
737  #endif  #endif
 #endif  
738    
739          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
740          return;          return;
741    
742          /*  Quick return path:  */          /*  Quick return path:  */
743    #if defined(MODE32) || defined(DYNTRANS_ALPHA)
744  have_it:  have_it:
 /*      cpu->cd.DYNTRANS_ARCH.cur_physpage = ppp;  */  
745          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
746          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 +
747              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
# Line 697  have_it: Line 749  have_it:
749          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "
750              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,
751              (long long)table_index, (long long)physpage_ofs);  */              (long long)table_index, (long long)physpage_ofs);  */
752    #endif
753  }  }
754  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
755    
# Line 724  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 777  static void DYNTRANS_INVALIDATE_TLB_ENTR
777          uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);          uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
778    
779  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
780          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3] &= ~(1 << (index & 7));          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
781  #endif  #endif
782    
783          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
# Line 782  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 835  static void DYNTRANS_INVALIDATE_TLB_ENTR
835                              cpu->cd.alpha.vph_default_page;                              cpu->cd.alpha.vph_default_page;
836          }          }
837  #else   /*  !DYNTRANS_ALPHA  */  #else   /*  !DYNTRANS_ALPHA  */
838  #ifdef DYNTRANS_IA64          fatal("Not yet for non-1-level, non-Alpha\n");
         fatal("IA64: blah blah TODO\n");  
 #else  
         fatal("Not yet for non-1-level, non-Alpha, non-ia64\n");  
 #endif  /*  !DYNTRANS_IA64  */  
839  #endif  /*  !DYNTRANS_ALPHA  */  #endif  /*  !DYNTRANS_ALPHA  */
840  #endif  #endif
841  }  }
# Line 803  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 852  static void DYNTRANS_INVALIDATE_TLB_ENTR
852   *  flags should be one of   *  flags should be one of
853   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL
854   *   *
855     *  In addition, for INVALIDATE_ALL, INVALIDATE_VADDR_UPPER4 may be set and
856     *  bit 31..28 of addr are used to select the virtual addresses to invalidate.
857     *  (This is useful for PowerPC emulation, when segment registers are updated.)
858     *
859   *  In the case when all translations are invalidated, paddr doesn't need   *  In the case when all translations are invalidated, paddr doesn't need
860   *  to be supplied.   *  to be supplied.
861   *   *
# Line 810  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 863  static void DYNTRANS_INVALIDATE_TLB_ENTR
863   *             the quick translation array, not from the linear   *             the quick translation array, not from the linear
864   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
865   */   */
866  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t paddr, int flags)  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
867  {  {
868          int r;          int r;
869  #ifdef MODE32  #ifdef MODE32
# Line 818  void DYNTRANS_INVALIDATE_TC(struct cpu * Line 871  void DYNTRANS_INVALIDATE_TC(struct cpu *
871  #else  #else
872          uint64_t          uint64_t
873  #endif  #endif
874              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);              addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
875    
876          /*  Quick case for virtual addresses: see note above.  */          /*  fatal("invalidate(): ");  */
877    
878            /*  Quick case for _one_ virtual addresses: see note above.  */
879          if (flags & INVALIDATE_VADDR) {          if (flags & INVALIDATE_VADDR) {
880                    /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */
881                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
882                  return;                  return;
883          }          }
884    
885            /*  Invalidate everything:  */
886    #ifdef DYNTRANS_PPC
887            if (flags & INVALIDATE_ALL && flags & INVALIDATE_VADDR_UPPER4) {
888                    /*  fatal("all, upper4 (PowerPC segment)\n");  */
889                    for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
890                            if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
891                                (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page
892                                & 0xf0000000) == addr_page) {
893                                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
894                                        DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
895                                        0);
896                                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
897                            }
898                    }
899                    return;
900            }
901    #endif
902            if (flags & INVALIDATE_ALL) {
903                    /*  fatal("all\n");  */
904                    for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
905                            if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
906                                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
907                                        DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
908                                        0);
909                                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
910                            }
911                    }
912                    return;
913            }
914    
915            /*  Invalidate a physical page:  */
916    
917            if (!(flags & INVALIDATE_PADDR))
918                    fatal("HUH? Invalidate: Not vaddr, all, or paddr?\n");
919    
920            /*  fatal("addr 0x%08x\n", (int)addr_page);  */
921    
922          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
923                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
924                      (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page ==                      == cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page) {
                     addr_page && flags & INVALIDATE_PADDR) ||  
                     flags & INVALIDATE_ALL) ) {  
925                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
926                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
927                              flags);                              flags);
# Line 986  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1077  void DYNTRANS_INVALIDATE_TC_CODE(struct
1077                                          vph_p = cpu->cd.alpha.vph_table0[a];                                          vph_p = cpu->cd.alpha.vph_table0[a];
1078                                  vph_p->phys_page[b] = NULL;                                  vph_p->phys_page[b] = NULL;
1079  #else   /*  !DYNTRANS_ALPHA  */  #else   /*  !DYNTRANS_ALPHA  */
1080  #ifdef DYNTRANS_IA64                                  fatal("Not yet for non-1-level, non-Alpha\n");
                                 fatal("IA64: blah yo yo TODO\n");  
 #else  
                                 fatal("Not yet for non-1-level, non-Alpha, "  
                                     "non-ia64\n");  
 #endif  /*  !DYNTRANS_IA64  */  
1081  #endif  /*  !DYNTRANS_ALPHA  */  #endif  /*  !DYNTRANS_ALPHA  */
1082  #endif  #endif
1083                          }                          }
# Line 1011  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1097  void DYNTRANS_INVALIDATE_TC_CODE(struct
1097  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1098          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1099  {  {
1100    #ifndef MODE32
1101          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1102    #endif
1103          int found, r, lowest_index, start, end, useraccess = 0;          int found, r, lowest_index, start, end, useraccess = 0;
1104    
1105  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 1030  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1118  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1118              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1119              (int)paddr_page);  */              (int)paddr_page);  */
1120  #else   /*  !MODE32  */  #else   /*  !MODE32  */
1121  #ifdef DYNTRANS_IA64          fatal("Neither 32-bit nor Alpha? 2\n");
         fatal("IA64 update todo\n");  
 #else  
         fatal("Neither 32-bit, IA64, nor Alpha? 2\n");  
1122          exit(1);          exit(1);
1123  #endif  #endif
1124  #endif  #endif
 #endif  
1125    
1126          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1127                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
# Line 1057  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1141  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1141  #endif  #endif
1142    
1143          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1144          found = -1; lowest_index = start;          lowest_index = start;
         lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;  
1145    
1146  #ifdef MODE32  #ifdef MODE32
1147          /*  NOTE: vaddr_to_tlbindex is one more than the index, so that          /*
1148              0 becomes -1, which means a miss.  */           *  NOTE 1: vaddr_to_tlbindex is one more than the index, so that
1149          found = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[           *          0 becomes -1, which means a miss.
1150             *
1151             *  NOTE 2: When a miss occurs, instead of scanning the entire tlb
1152             *          for the entry with the lowest time stamp, just choosing
1153             *          one at random will work as well.
1154             */
1155            found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1156              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1157          if (found < 0)          if (found < 0) {
1158                  lowest_index = (random() % (end-start)) + start;                  static unsigned int x = 0;
1159          if (0)                  lowest_index = (x % (end-start)) + start;
1160  #endif                  x ++;
1161            }
1162    #else
1163            lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1164            found = -1;
1165          for (r=start; r<end; r++) {          for (r=start; r<end; r++) {
1166                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1167                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
# Line 1086  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1178  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1178                          break;                          break;
1179                  }                  }
1180          }          }
1181    #endif
1182    
1183          if (found < 0) {          if (found < 0) {
1184                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting the oldest one:  */
# Line 1101  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1194  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1194                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;
1195                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;
1196                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1197                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = writeflag;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1198                        writeflag & MEM_WRITE;
1199    #ifndef MODE32
1200                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1201    #endif
1202    
1203                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
1204  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 1151  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1247  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1247                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1248  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
1249                  if (useraccess)                  if (useraccess)
1250                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1251                              |= 1 << (index & 7);                              |= 1 << (index & 31);
1252  #endif  #endif
1253  #endif  /*  32  */  #endif  /*  32  */
1254  #endif  /*  !ALPHA  */  #endif  /*  !ALPHA  */
# Line 1161  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1257  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1257                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
1258                   *      Writeflag = 0:  Do nothing.                   *      Writeflag = 0:  Do nothing.
1259                   *      Writeflag = 1:  Make sure the page is writable.                   *      Writeflag = 1:  Make sure the page is writable.
1260                   *      Writeflag = -1: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1261                   */                   */
1262                  r = found;                  r = found;
1263    #ifndef MODE32
1264                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1265                  if (writeflag == 1)  #endif
1266                    if (writeflag & MEM_WRITE)
1267                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1268                  if (writeflag == -1)                  if (writeflag & MEM_DOWNGRADE)
1269                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
1270  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
1271                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);
# Line 1179  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1277  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1277                          vph_p = cpu->cd.alpha.vph_table0[a];                          vph_p = cpu->cd.alpha.vph_table0[a];
1278                  vph_p->phys_page[b] = NULL;                  vph_p->phys_page[b] = NULL;
1279                  if (vph_p->phys_addr[b] == paddr_page) {                  if (vph_p->phys_addr[b] == paddr_page) {
1280                          if (writeflag == 1)                          if (writeflag & MEM_WRITE)
1281                                  vph_p->host_store[b] = host_page;                                  vph_p->host_store[b] = host_page;
1282                          if (writeflag == -1)                          if (writeflag & MEM_DOWNGRADE)
1283                                  vph_p->host_store[b] = NULL;                                  vph_p->host_store[b] = NULL;
1284                  } else {                  } else {
1285                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
# Line 1194  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1292  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1292                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1293                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1294  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
1295                  cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]&=~(1<<(index&7));                  cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1296                  if (useraccess)                  if (useraccess)
1297                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 3]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1298                              |= 1 << (index & 7);                              |= 1 << (index & 31);
1299  #endif  #endif
1300                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {                  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1301                          if (writeflag == 1)                          if (writeflag & MEM_WRITE)
1302                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1303                                      host_page;                                      host_page;
1304                          if (writeflag == -1)                          if (writeflag & MEM_DOWNGRADE)
1305                                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1306                  } else {                  } else {
1307                          /*  Change the entire physical/host mapping:  */                          /*  Change the entire physical/host mapping:  */
# Line 1248  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1346  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1346                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "
1347                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1348                                      (long long)cpu->pc);                                      (long long)cpu->pc);
1349    #ifdef DYNTRANS_DELAYSLOT
1350                                    if (cpu->cd.DYNTRANS_ARCH.delay_slot !=
1351                                        NOT_DELAYED)
1352                                            fatal("ERROR! Breakpoint in a delay"
1353                                                " slot! Not yet supported.\n");
1354    #endif
1355                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1356                                  single_step = 1;                                  single_step = 1;
1357                                  goto stop_running_translated;                                  goto stop_running_translated;
# Line 1269  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1373  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1373           */           */
1374  #ifdef MODE32  #ifdef MODE32
1375          if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {          if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1376                  uint32_t index = DYNTRANS_ADDR_TO_PAGENR(addr);                  uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);
1377                  cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=                  cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1378                      (1 << (index & 31));                      (1 << (index & 31));
1379          }          }
# Line 1277  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1381  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1381          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;
1382    
1383    
1384    #ifdef DYNTRANS_BACKEND
1385            /*
1386             *  "Empty"/simple native dyntrans backend stuff:
1387             *
1388             *  1) If no translation is currently being done, but the translated
1389             *     instruction was simple enough, then let's start making a new
1390             *     native translation block.
1391             *
1392             *  2) If a native translation block is currently being constructed,
1393             *     but this instruction wasn't simple enough, then end the block
1394             *     (without including this instruction).
1395             *
1396             *  3) If a native translation block is currently being constructed,
1397             *     and this is a simple instruction, then add it.
1398             */
1399            if (simple && cpu->translation_context.p == NULL &&
1400                dyntrans_backend_enable) {
1401                    size_t s = 0;
1402    
1403                    if (cpu->translation_context.translation_buffer == NULL) {
1404                            cpu->translation_context.translation_buffer =
1405                                zeroed_alloc(DTB_TRANSLATION_SIZE_MAX +
1406                                DTB_TRANSLATION_SIZE_MARGIN);
1407                    }
1408    
1409                    cpu->translation_context.p =
1410                        cpu->translation_context.translation_buffer;
1411    
1412                    cpu->translation_context.ic_page =
1413                        cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1414                    cpu->translation_context.start_instr_call_index =
1415                        ((size_t)ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)
1416                        / (sizeof(*ic));
1417    
1418                    dtb_function_prologue(&cpu->translation_context, &s);
1419                    cpu->translation_context.p += s;
1420                    cpu->translation_context.n_simple = 0;
1421            }
1422    
1423            /*  If this is not a continuation of a simple translation, then
1424                stop now!  */
1425            if (cpu->translation_context.ic_page != cpu->cd.DYNTRANS_ARCH.
1426                cur_ic_page || ic != &cpu->cd.DYNTRANS_ARCH.cur_ic_page[
1427                cpu->translation_context.start_instr_call_index +
1428                cpu->translation_context.n_simple])
1429                    simple = 0;
1430    
1431            if (cpu->translation_context.p != NULL && !simple) {
1432                    size_t s = 0, total;
1433    
1434                    if (cpu->translation_context.n_simple > 1) {
1435                            dtb_generate_ptr_inc(cpu, &cpu->translation_context,
1436                                &s, &cpu->cd.DYNTRANS_ARCH.next_ic,
1437                                (cpu->translation_context.n_simple - 1) *
1438                                sizeof(*(cpu->cd.DYNTRANS_ARCH.next_ic)));
1439                            cpu->translation_context.p += s;
1440                    }
1441    
1442                    dtb_function_epilogue(&cpu->translation_context, &s);
1443                    cpu->translation_context.p += s;
1444    
1445                    cpu_dtb_do_fixups(cpu);
1446    #if 0
1447    {
1448    int i;
1449    unsigned char *addr = cpu->translation_context.translation_buffer;
1450    printf("index = %i\n", cpu->translation_context.start_instr_call_index);
1451    quiet_mode = 0;
1452    for (i=0; i<4*32; i+=4)
1453            alpha_cpu_disassemble_instr(cpu, (unsigned char *)addr + i,
1454            0, i, 0);
1455    }
1456    #endif
1457                    total = (size_t)cpu->translation_context.p -
1458                        (size_t)cpu->translation_context.translation_buffer;
1459    
1460                    /*  Copy the translated block to the translation cache:  */
1461                    /*  Align first:  */
1462                    cpu->translation_cache_cur_ofs --;
1463                    cpu->translation_cache_cur_ofs |= 31;
1464                    cpu->translation_cache_cur_ofs ++;
1465    
1466                    memcpy(cpu->translation_cache + cpu->translation_cache_cur_ofs,
1467                        cpu->translation_context.translation_buffer, total);
1468    
1469                    /*  Set the ic pointer:  */
1470                    ((struct DYNTRANS_IC *)cpu->translation_context.ic_page)
1471                        [cpu->translation_context.start_instr_call_index].f =
1472                        (void *)
1473                        (cpu->translation_cache + cpu->translation_cache_cur_ofs);
1474    
1475                    /*  Align cur_ofs afterwards as well, just to be safe.  */
1476                    cpu->translation_cache_cur_ofs += total;
1477                    cpu->translation_cache_cur_ofs --;
1478                    cpu->translation_cache_cur_ofs |= 31;
1479                    cpu->translation_cache_cur_ofs ++;
1480    
1481                    /*  Set the "combined instruction" flag for this page:  */
1482                    cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1483                        cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1484                    cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= COMBINATIONS;
1485    
1486                    dtb_host_cacheinvalidate(0,0); /* p , size ... ); */
1487    
1488                    cpu->translation_context.p = NULL;
1489            }
1490            if (cpu->translation_context.p != NULL) {
1491                    size_t s = 0;
1492                    dtb_generate_fcall(cpu, &cpu->translation_context,
1493                        &s, (size_t)ic->f, (size_t)ic);
1494                    cpu->translation_context.p += s;
1495                    cpu->translation_context.n_simple ++;
1496            }
1497    #endif  /*  DYNTRANS_BACKEND  */
1498    
1499    
1500          /*          /*
1501           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
1502           *  be converted into a single function call.           *  be converted into a single function call.
# Line 1285  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1505  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1505           *  instruction combination.           *  instruction combination.
1506           */           */
1507          if (!single_step && !cpu->machine->instruction_trace) {          if (!single_step && !cpu->machine->instruction_trace) {
1508                  if (cpu->combination_check != NULL &&                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1509                      cpu->machine->speed_tricks)                      cpu->machine->speed_tricks)
1510                          cpu->combination_check(cpu, ic,                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1511                              addr & (DYNTRANS_PAGESIZE - 1));                              addr & (DYNTRANS_PAGESIZE - 1));
1512                  cpu->combination_check = NULL;                  cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1513          }          }
1514    
1515          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */

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

  ViewVC Help
Powered by ViewVC 1.1.26