/[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 14 by dpavlin, Mon Oct 8 16:18:51 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.19 2005/10/07 22:10:51 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)
57    {
58            uint64_t a;
59            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
60                cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
61            if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)
62                    return;
63    
64    #if 0
65            /*  Use the physical address:  */
66            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
67                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
68            a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
69    #else
70            /*  Use the PC (virtual address):  */
71            a = cpu->pc;
72    #endif
73    
74            a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
75                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
76            a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77    
78            /*
79             *  TODO: Everything below this line should be cleaned up :-)
80             */
81    a &= 0x03ffffff;
82    {
83            static long long *array = NULL;
84            static char *array_16kpage_in_use = NULL;
85            static int n = 0;
86            a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;
87            if (array == NULL)
88                    array = zeroed_alloc(sizeof(long long) * 16384*1024);
89            if (array_16kpage_in_use == NULL)
90                    array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);
91            a &= (16384*1024-1);
92            array[a] ++;
93            array_16kpage_in_use[a / 16384] = 1;
94            n++;
95            if ((n & 0x3fffffff) == 0) {
96                    FILE *f = fopen("statistics.out", "w");
97                    int i, j;
98                    printf("Saving statistics... "); fflush(stdout);
99                    for (i=0; i<1024; i++)
100                            if (array_16kpage_in_use[i]) {
101                                    for (j=0; j<16384; j++)
102                                            if (array[i*16384 + j] > 0)
103                                                    fprintf(f, "%lli\t0x%016llx\n",
104                                                        (long long)array[i*16384+j],
105                                                        (long long)((i*16384+j) <<
106                                    DYNTRANS_INSTR_ALIGNMENT_SHIFT));
107                            }
108                    fclose(f);
109                    printf("n=0x%08x\n", n);
110            }
111    }
112    }
113    #endif  /*  PC statistics  */
114    
115    #define S               gather_statistics(cpu)
116    
117    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
118    #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
122    #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
123    #endif
124    
125    
126  /*  /*
127   *  XXX_cpu_run_instr():   *  XXX_cpu_run_instr():
128   *   *
# Line 66  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    
171          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
172          cpu->running_translated = 1;          cpu->running_translated = 1;
173    
174            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
175                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
176    
177          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace) {
178                  /*                  /*
179                   *  Single-step:                   *  Single-step:
# Line 97  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 122  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 231  int DYNTRANS_CPU_RUN_INSTR(struct emul *
231                              ~(COMBINATIONS | TRANSLATIONS);                              ~(COMBINATIONS | TRANSLATIONS);
232                  }                  }
233    
234                    if (show_opcode_statistics)
235                            S;
236    
237                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
238                  ic->f(cpu, ic);                  ic->f(cpu, ic);
239                  n_instrs = 1;                  n_instrs = 1;
240          } else {          } else if (show_opcode_statistics) {
241                  /*  Execute multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
242                  n_instrs = 0;                  n_instrs = 0;
243                  for (;;) {                  for (;;) {
244                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
245    
246  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                          S; I; S; I; S; I; S; I; S; I; S; I;
247  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic; ic->f(cpu, ic);                          S; I; S; I; S; I; S; I; S; I; S; I;
248  #else                          S; I; S; I; S; I; S; I; S; I; S; I;
249  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);                          S; I; S; I; S; I; S; I; S; I; S; I;
 #endif  
250    
251                          I; I; I; I; I;   I; I; I; I; I;                          n_instrs += 24;
252                          I; I; I; I; I;   I; I; I; I; I;  
253                          I; I; I; I; I;   I; I; I; I; I;                          if (!cpu->running_translated ||
254                          I; I; I; I; I;   I; I; I; I; I;                              n_instrs + cpu->n_translated_instrs >= 16384)
255                          I; I; I; I; I;   I; I; I; I; I;                                  break;
256                    }
257            } else {
258                    /*  Execute multiple instructions:  */
259                    n_instrs = 0;
260                    for (;;) {
261                            struct DYNTRANS_IC *ic;
262    
263                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
264                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
# Line 150  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 267  int DYNTRANS_CPU_RUN_INSTR(struct emul *
267                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
268    
269                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
                         I; I; I; I; I;   I; I; I; I; I;  
270    
271                          n_instrs += 120;                          n_instrs += 60;
272    
273                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
274                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >= 16384)
# Line 160  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 281  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 313  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 320  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 346  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 --;
497            cpu->translation_cache_cur_ofs |= 63;
498            cpu->translation_cache_cur_ofs ++;
499  }  }
500  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
501    
# Line 371  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 380  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 523  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
523  #ifdef MODE32  #ifdef MODE32
524          int index;          int index;
525          cached_pc = cpu->pc;          cached_pc = cpu->pc;
526          index = cached_pc >> 12;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
527  #else  #else
528  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
529          uint32_t a, b;          uint32_t a, b;
# Line 395  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 418  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 437  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 458  cpu->cd.arm.r[ARM_PC]); Line 590  cpu->cd.arm.r[ARM_PC]);
590                          }                          }
591                  }                  }
592                  cached_pc = cpu->pc;                  cached_pc = cpu->pc;
593    #ifdef MODE32
594                    index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
595    #endif
596                  physaddr = paddr;                  physaddr = paddr;
597          }          }
598    
599          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE)  #ifdef MODE32
600            if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
601                    unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
602                        physaddr, MEM_READ);
603                    if (host_page != NULL) {
604                            int q = DYNTRANS_PAGESIZE - 1;
605                            host_page += (physaddr &
606                                ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
607                            cpu->update_translation_table(cpu, cached_pc & ~q,
608                                host_page, TLB_CODE, physaddr & ~q);
609                    }
610            }
611    #endif
612    
613            if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
614                    debug("[ dyntrans: resetting the translation cache ]\n");
615                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
616            }
617    
618          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
619          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
# Line 509  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          cpu->invalidate_translation_caches_paddr(cpu, physaddr,  #ifdef MODE32
664              JUST_MARK_AS_NON_WRITABLE);          /*  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,
671                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 +
676              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
677    
# Line 543  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;
709          cached_pc = cpu->pc;          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
         index = cached_pc >> 12;  
710          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
711          if (ppp != NULL)          if (ppp != NULL)
712                  goto have_it;                  goto have_it;
# Line 558  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 572  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 595  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 610  have_it: Line 765  have_it:
765   *  is just downgraded to non-writable (ie the host store page is set to   *  is just downgraded to non-writable (ie the host store page is set to
766   *  NULL). Otherwise, the entire translation is removed.   *  NULL). Otherwise, the entire translation is removed.
767   */   */
768  void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,  static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
769  #ifdef MODE32  #ifdef MODE32
770          uint32_t          uint32_t
771  #else  #else
# Line 619  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 774  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
774          vaddr_page, int flags)          vaddr_page, int flags)
775  {  {
776  #ifdef MODE32  #ifdef MODE32
777          uint32_t index = vaddr_page >> 12;          uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
778    
779    #ifdef DYNTRANS_ARM
780            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
781    #endif
782    
783          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
784                  /*  printf("JUST MARKING NON-W: vaddr 0x%08x\n",                  /*  printf("JUST MARKING NON-W: vaddr 0x%08x\n",
# Line 630  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 789  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
789                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
790                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
791                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
792                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
793          }          }
794  #else  #else
795          /*  2-level:  */          /*  2-level:  */
# Line 675  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 835  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
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  }  }
842  #endif  #endif
843    
844    
845  #ifdef DYNTRANS_INVALIDATE_TC_PADDR  #ifdef DYNTRANS_INVALIDATE_TC
846  /*  /*
847   *  XXX_invalidate_translation_caches_paddr():   *  XXX_invalidate_translation_caches():
848   *   *
849   *  Invalidate all entries matching a specific physical address, a specific   *  Invalidate all entries matching a specific physical address, a specific
850   *  virtual address, or ALL entries.   *  virtual address, or ALL entries.
# Line 696  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc Line 852  void DYNTRANS_INVALIDATE_TLB_ENTRY(struc
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   *   *
862   *  NOTE/TODO: Poorly choosen name for this function, as it can   *  NOTE/TODO: When invalidating a virtual address, it is only cleared from
863   *             invalidate based on virtual address as well.   *             the quick translation array, not from the linear
864     *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
865   */   */
866  void DYNTRANS_INVALIDATE_TC_PADDR(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 710  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 871  void DYNTRANS_INVALIDATE_TC_PADDR(struct
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            /*  fatal("invalidate(): ");  */
877    
878            /*  Quick case for _one_ virtual addresses: see note above.  */
879            if (flags & INVALIDATE_VADDR) {
880                    /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */
881                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
882                    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) ||  
                     (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==  
                     addr_page && flags & INVALIDATE_VADDR) ||  
                     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 731  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 934  void DYNTRANS_INVALIDATE_TC_PADDR(struct
934                  }                  }
935          }          }
936  }  }
937  #endif  /*  DYNTRANS_INVALIDATE_TC_PADDR  */  #endif  /*  DYNTRANS_INVALIDATE_TC  */
938    
939    
940    
# Line 745  void DYNTRANS_INVALIDATE_TC_PADDR(struct Line 948  void DYNTRANS_INVALIDATE_TC_PADDR(struct
948  void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)  void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)
949  {  {
950          int r;          int r;
951  #ifdef MODE_32  #ifdef MODE32
952          uint32_t          uint32_t
953  #else  #else
954          uint64_t          uint64_t
# Line 760  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 963  void DYNTRANS_INVALIDATE_TC_CODE(struct
963          if (flags & INVALIDATE_PADDR) {          if (flags & INVALIDATE_PADDR) {
964                  int pagenr, table_index;                  int pagenr, table_index;
965                  uint32_t physpage_ofs, *physpage_entryp;                  uint32_t physpage_ofs, *physpage_entryp;
966                  struct DYNTRANS_TC_PHYSPAGE *ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
967    
968                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
969    
970    #ifdef MODE32
971                    /*  If this page isn't marked as having any translations,
972                        then return immediately.  */
973                    if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]
974                        & 1 << (pagenr & 31)))
975                            return;
976                    /*  Remove the mark:  */
977                    cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=
978                        ~ (1 << (pagenr & 31));
979    #endif
980    
981                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
982    
983                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
984                      translation_cache)[table_index]);                      translation_cache)[table_index]);
985                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
986                  ppp = NULL;                  prev_ppp = ppp = NULL;
987    
988                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
989                  while (physpage_ofs != 0) {                  while (physpage_ofs != 0) {
990                            prev_ppp = ppp;
991                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
992                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
993                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
# Line 782  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 998  void DYNTRANS_INVALIDATE_TC_CODE(struct
998                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
999                  }                  }
1000    
1001                  /*  If the page was found, then we should invalidate all                  if (physpage_ofs == 0)
1002                      code translations:  */                          ppp = NULL;
1003    
1004    #if 1
1005                    /*
1006                     *  "Bypass" the page, removing it from the code cache.
1007                     *
1008                     *  NOTE/TODO: This gives _TERRIBLE_ performance with self-
1009                     *  modifying code, or when a single page is used for both
1010                     *  code and (writable) data.
1011                     */
1012                    if (ppp != NULL) {
1013                            if (prev_ppp != NULL)
1014                                    prev_ppp->next_ofs = ppp->next_ofs;
1015                            else
1016                                    *physpage_entryp = ppp->next_ofs;
1017                    }
1018    #else
1019                    /*
1020                     *  Instead of removing the page from the code cache, each
1021                     *  entry can be set to "to_be_translated". This is slow in
1022                     *  the general case, but in the case of self-modifying code,
1023                     *  it might be faster since we don't risk wasting cache
1024                     *  memory as quickly (which would force unnecessary Restarts).
1025                     */
1026                  if (ppp != NULL) {                  if (ppp != NULL) {
1027                          /*  TODO: Is this faster than copying an entire                          /*  TODO: Is this faster than copying an entire
1028                              template page?  */                              template page?  */
# Line 795  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1034  void DYNTRANS_INVALIDATE_TC_CODE(struct
1034  #endif  #endif
1035                                      instr(to_be_translated);                                      instr(to_be_translated);
1036                  }                  }
1037    #endif
1038          }          }
1039    
1040          /*  Invalidate entries in the VPH table:  */          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */
1041          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;
1042                 r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
1043                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1044                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1045                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 809  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1050  void DYNTRANS_INVALIDATE_TC_CODE(struct
1050                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||                              (flags & INVALIDATE_PADDR && paddr_page == addr) ||
1051                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {                              (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
1052  #ifdef MODE32  #ifdef MODE32
1053                                  uint32_t index = vaddr_page >> 12;                                  uint32_t index =
1054                                        DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1055                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1056                                    /*  Remove the mark:  */
1057                                    index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);
1058                                    cpu->cd.DYNTRANS_ARCH.phystranslation[
1059                                        index >> 5] &= ~ (1 << (index & 31));
1060  #else  #else
1061                                  /*  2-level:  */                                  /*  2-level:  */
1062  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
# Line 831  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 856  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          int found, r, lowest_index;  #endif
1103            int found, r, lowest_index, start, end, useraccess = 0;
1104    
1105  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
1106          uint32_t a, b;          uint32_t a, b;
# Line 875  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
1125    
1126            if (writeflag & MEMORY_USER_ACCESS) {
1127                    writeflag &= ~MEMORY_USER_ACCESS;
1128                    useraccess = 1;
1129            }
1130    
1131            start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;
1132    #if 1
1133            /*  Half of the TLB used for data, half for code:  */
1134            if (writeflag & TLB_CODE) {
1135                    writeflag &= ~TLB_CODE;
1136                    start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1137            }
1138    #else
1139            /*  Data and code entries are mixed.  */
1140            end = DYNTRANS_MAX_VPH_TLB_ENTRIES;
1141  #endif  #endif
1142    
1143          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1144          found = -1; lowest_index = 0;          lowest_index = start;
1145    
1146    #ifdef MODE32
1147            /*
1148             *  NOTE 1: vaddr_to_tlbindex is one more than the index, so that
1149             *          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;
1157            if (found < 0) {
1158                    static unsigned int x = 0;
1159                    lowest_index = (x % (end-start)) + start;
1160                    x ++;
1161            }
1162    #else
1163          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1164          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          found = -1;
1165            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.
1168                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 903  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 918  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 959  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1238  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1238                  vph_p->phys_page[b] = NULL;                  vph_p->phys_page[b] = NULL;
1239  #else  #else
1240  #ifdef MODE32  #ifdef MODE32
1241                  index = vaddr_page >> 12;                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1242                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1243                  cpu->cd.DYNTRANS_ARCH.host_store[index] =                  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1244                      writeflag? host_page : NULL;                      writeflag? host_page : NULL;
1245                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1246                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1247                    cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1248    #ifdef DYNTRANS_ARM
1249                    if (useraccess)
1250                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1251                                |= 1 << (index & 31);
1252    #endif
1253  #endif  /*  32  */  #endif  /*  32  */
1254  #endif  /*  !ALPHA  */  #endif  /*  !ALPHA  */
1255          } else {          } else {
# Line 972  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                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[found].timestamp =                  r = found;
1263                      highest + 1;  #ifndef MODE32
1264                  if (writeflag == 1)                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;
1265    #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 990  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 1002  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1289  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1289                  }                  }
1290  #else  #else
1291  #ifdef MODE32  #ifdef MODE32
1292                  index = vaddr_page >> 12;                  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
1295                    cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1296                    if (useraccess)
1297                            cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1298                                |= 1 << (index & 31);
1299    #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 1053  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 1067  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1366  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1366  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1367          /*          /*
1368           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated.
1369             *  Mark the page as containing a translation.
1370             *
1371             *  (Special case for 32-bit mode: set the corresponding bit in the
1372             *  phystranslation[] array.)
1373             */
1374    #ifdef MODE32
1375            if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1376                    uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);
1377                    cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1378                        (1 << (index & 31));
1379            }
1380    #endif
1381            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          translated;          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
# Line 1077  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1504  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1504           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1505           *  instruction combination.           *  instruction combination.
1506           */           */
1507          if (!single_step && !cpu->machine->instruction_trace)          if (!single_step && !cpu->machine->instruction_trace) {
1508                  COMBINE_INSTRUCTIONS(cpu, ic, addr);                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1509                        cpu->machine->speed_tricks)
1510                            cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1511                                addr & (DYNTRANS_PAGESIZE - 1));
1512                    cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1513            }
1514    
1515          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1516          if (single_step_breakpoint) {          if (single_step_breakpoint) {

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

  ViewVC Help
Powered by ViewVC 1.1.26