/[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 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 26 by dpavlin, Mon Oct 8 16:20:10 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.41 2005/11/23 22:03:31 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.104 2006/06/25 00:15:44 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
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 79  a &= 0x03ffffff; Line 100  a &= 0x03ffffff;
100                          if (array_16kpage_in_use[i]) {                          if (array_16kpage_in_use[i]) {
101                                  for (j=0; j<16384; j++)                                  for (j=0; j<16384; j++)
102                                          if (array[i*16384 + j] > 0)                                          if (array[i*16384 + j] > 0)
103                                                  fprintf(f, "%lli\t0x%016llx\n",                                                  fprintf(f, "%lli\t"
104                                                      (long long)array[i*16384+j],                                                      "0x%016"PRIx64"\n",
105                                                      (long long)((i*16384+j) <<                                                      (uint64_t)array[i*16384+j],
106                                  DYNTRANS_INSTR_ALIGNMENT_SHIFT));                                                      (uint64_t)((i*16384+j) <<
107                                                DYNTRANS_INSTR_ALIGNMENT_SHIFT));
108                          }                          }
109                  fclose(f);                  fclose(f);
110                  printf("n=0x%08x\n", n);                  printf("n=0x%08x\n", n);
111          }          }
112  }  }
113  }  }
114    #endif  /*  PC statistics  */
115    
116    
117  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
118    
119    
120  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
121  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \
122                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->len;       \                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \
123                          ic->f(cpu, ic);                          ic->f(cpu, ic);
124  #else  #else
125  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  
126    /*  The normal instruction execution core:  */
127    #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
128    
129    /*  For heavy debugging:  */
130    /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
131                    {       \
132                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
133                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
134                                sizeof(struct DYNTRANS_IC);                 \
135                            printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n",  \
136                                cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
137                                ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
138                    } \
139                    ic->f(cpu, ic);  */
140    
141    /*  static long long nr_of_I_calls = 0;  */
142    
143    /*  Temporary hack for finding NULL bugs:  */
144    /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;                  \
145                    nr_of_I_calls ++;                                       \
146                    if (ic->f == NULL) {                                    \
147                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
148                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
149                                sizeof(struct DYNTRANS_IC);                 \
150                            cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \
151                                DYNTRANS_INSTR_ALIGNMENT_SHIFT);            \
152                            cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\
153                            printf("Crash at %016"PRIx64"\n", cpu->pc);     \
154                            printf("nr of I calls: %lli\n", nr_of_I_calls); \
155                            printf("Next ic = %p\n", cpu->cd.               \
156                                    DYNTRANS_ARCH.next_ic);                 \
157                            printf("cur ic page = %p\n", cpu->cd.           \
158                                    DYNTRANS_ARCH.cur_ic_page);             \
159                            cpu->running = 0;                               \
160                            return 0;                                       \
161                    }                                                       \
162                    ic->f(cpu, ic);  */
163    
164    /*  Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs:  */
165    /*  #define I           { int k; for (k=1; k<=31; k++)  \
166            cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\
167            if (cpu->cd.mips.gpr[0] != 0) {                 \
168                    fatal("NOOOOOO\n"); exit(1);            \
169            }                                               \
170            ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
171    */
172  #endif  #endif
173    
174    
# Line 112  a &= 0x03ffffff; Line 182  a &= 0x03ffffff;
182   */   */
183  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)
184  {  {
185            /*
186             *  TODO:  Statistics stuff!
187             */
188            int show_opcode_statistics = 0;
189    
190  #ifdef MODE32  #ifdef MODE32
191          uint32_t cached_pc;          uint32_t cached_pc;
192  #else  #else
# Line 131  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 206  int DYNTRANS_CPU_RUN_INSTR(struct emul *
206           *  conversion; if the conversion caused an exception of some kind           *  conversion; if the conversion caused an exception of some kind
207           *  then interrupts are probably disabled, and the exception will get           *  then interrupts are probably disabled, and the exception will get
208           *  priority over device interrupts.)           *  priority over device interrupts.)
209             *
210             *  TODO: Turn this into a family-specific function somewhere...
211           */           */
212  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
213          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))
214                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
215  #endif  #endif
216    #ifdef DYNTRANS_MIPS
217            {
218                    int enabled, mask;
219                    int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
220                    if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
221                            /*  R3000:  */
222                            enabled = status & MIPS_SR_INT_IE;
223                    } else {
224                            /*  R4000 and others:  */
225                            enabled = (status & STATUS_IE)
226                                && !(status & STATUS_EXL) && !(status & STATUS_ERL);
227                            /*  Special case for R5900/C790/TX79:  */
228                            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
229                                !(status & R5900_STATUS_EIE))
230                                    enabled = 0;
231                    }
232                    mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]
233                        & STATUS_IM_MASK;
234    
235                    if (enabled && mask)
236                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0);
237            }
238    #endif
239  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
240          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {          if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
241                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  ppc_exception(cpu, PPC_EXCEPTION_DEC);
# Line 153  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 253  int DYNTRANS_CPU_RUN_INSTR(struct emul *
253          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
254              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
255    
256          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace
257                || cpu->machine->register_dump) {
258                  /*                  /*
259                   *  Single-step:                   *  Single-step:
260                   */                   */
261                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
262  #ifndef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                  if (cpu->machine->register_dump) {
263                      ++                          debug("\n");
264  #endif                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
265                      ;                  }
266                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
267  #ifdef DYNTRANS_X86  #ifdef DYNTRANS_X86
268                          unsigned char instr[17];                          unsigned char instr[17];
# Line 174  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 275  int DYNTRANS_CPU_RUN_INSTR(struct emul *
275                          unsigned char instr[4];         /*  General case...  */                          unsigned char instr[4];         /*  General case...  */
276  #endif  #endif
277  #endif  #endif
278    
279                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
280                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
281                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_cpu_run_instr(): could not read "
282                                      "the instruction\n");                                      "the instruction\n");
283                          } else                          } else {
284                                  cpu_disassemble_instr(cpu->machine, cpu,                                  cpu_disassemble_instr(cpu->machine, cpu,
285                                      instr, 1, 0, 0);                                      instr, 1, 0);
286    #ifdef DYNTRANS_DELAYSLOT
287                                    /*  Show the instruction in the delay slot,
288                                        if any:  */
289                                    if (cpu->instruction_has_delayslot == NULL)
290                                            fatal("WARNING: ihd func not yet"
291                                                " implemented?\n");
292                                    else if (cpu->instruction_has_delayslot(cpu,
293                                        instr)) {
294                                            int saved_delayslot = cpu->delay_slot;
295                                            cpu->memory_rw(cpu, cpu->mem, cached_pc
296                                                + sizeof(instr), &instr[0],
297                                                sizeof(instr), MEM_READ,
298                                                CACHE_INSTRUCTION);
299                                            cpu->delay_slot = DELAYED;
300                                            cpu->pc += sizeof(instr);
301                                            cpu_disassemble_instr(cpu->machine,
302                                                cpu, instr, 1, 0);
303                                            cpu->delay_slot = saved_delayslot;
304                                            cpu->pc -= sizeof(instr);
305                                    }
306    #endif
307                            }
308                  }                  }
309    
310                  /*  When single-stepping, multiple instruction calls cannot                  /*  When single-stepping, multiple instruction calls cannot
311                      be combined into one. This clears all translations:  */                      be combined into one. This clears all translations:  */
312                  if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {                  if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {
313                          int i;                          int i;
314                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
315                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =
316  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
317                                      cpu->is_32bit?                                      cpu->is_32bit?
318                                          instr32(to_be_translated) :                                          instr32(to_be_translated) :
319  #endif  #endif
320                                          instr(to_be_translated);                                          instr(to_be_translated);
321                          fatal("[ Note: The translation of physical page 0x%llx"  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
322                              " contained combinations of instructions; these "                                  cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].
323                              "are now flushed because we are single-stepping."                                      arg[0] = 0;
324                              " ]\n", (long long)cpu->cd.DYNTRANS_ARCH.  #endif
325                            }
326                            fatal("[ Note: The translation of physical page 0x%"
327                                PRIx64" contained combinations of instructions; "
328                                "these are now flushed because we are single-"
329                                "stepping. ]\n", (long long)cpu->cd.DYNTRANS_ARCH.
330                              cur_physpage->physaddr);                              cur_physpage->physaddr);
331                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=
332                              ~(COMBINATIONS | TRANSLATIONS);                              ~(COMBINATIONS | TRANSLATIONS);
# Line 207  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 336  int DYNTRANS_CPU_RUN_INSTR(struct emul *
336                          S;                          S;
337    
338                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
339                  ic->f(cpu, ic);                  I;
340    
341                  n_instrs = 1;                  n_instrs = 1;
342            } else if (cpu->machine->cycle_accurate) {
343                    /*  Executing multiple instructions, and call devices'
344                        tick functions:  */
345                    n_instrs = 0;
346                    for (;;) {
347                            struct DYNTRANS_IC *ic;
348    /*  TODO: continue here  */
349    int64_t cycles = cpu->cd.avr.extra_cycles;
350                            I;
351                            n_instrs += 1;
352    cycles = cpu->cd.avr.extra_cycles - cycles + 1;
353    /*  The instruction took 'cycles' cycles.  */
354    /* printf("A\n"); */
355    while (cycles-- > 0)
356            cpu->machine->tick_func[1](cpu, cpu->machine->tick_extra[1]);
357    /* printf("B\n"); */
358    
359                            if (!cpu->running_translated ||
360                                n_instrs + cpu->n_translated_instrs >=
361                                N_SAFE_DYNTRANS_LIMIT)
362                                    break;
363                    }
364          } else if (show_opcode_statistics) {          } else if (show_opcode_statistics) {
365                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
366                  n_instrs = 0;                  n_instrs = 0;
# Line 223  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 375  int DYNTRANS_CPU_RUN_INSTR(struct emul *
375                          n_instrs += 24;                          n_instrs += 24;
376    
377                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
378                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >=
379                                N_SAFE_DYNTRANS_LIMIT)
380                                  break;                                  break;
381                  }                  }
382          } else {          } else {
# Line 243  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 396  int DYNTRANS_CPU_RUN_INSTR(struct emul *
396                          n_instrs += 60;                          n_instrs += 60;
397    
398                          if (!cpu->running_translated ||                          if (!cpu->running_translated ||
399                              n_instrs + cpu->n_translated_instrs >= 16384)                              n_instrs + cpu->n_translated_instrs >=
400                                N_SAFE_DYNTRANS_LIMIT)
401                                  break;                                  break;
402                  }                  }
403          }          }
# Line 263  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 417  int DYNTRANS_CPU_RUN_INSTR(struct emul *
417                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
418                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
419                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
420            } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE + 1) {
421                    /*  Switch to next page and skip an instruction which was
422                        already executed (in a delay slot):  */
423                    cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
424                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
425                    cpu->pc += ((DYNTRANS_IC_ENTRIES_PER_PAGE + 1) <<
426                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
427          }          }
428    
429    #ifdef DYNTRANS_MIPS
430            /*  Update the count register (on everything except EXC3K):  */
431            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
432                    uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
433                    int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
434                    int32_t diff2;
435                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
436                        (int32_t) (old + n_instrs);
437                    diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
438                        cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
439                    if (cpu->cd.mips.compare_register_set && diff1>0 && diff2<=0)
440                            cpu_interrupt(cpu, 7);
441            }
442    #endif
443  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
444          /*  Update the Decrementer and Time base registers:  */          /*  Update the Decrementer and Time base registers:  */
445          {          {
446                  uint32_t old = cpu->cd.ppc.spr[SPR_DEC];                  uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
447                  cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);                  cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
448                  if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1)                  if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
449                        && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
450                          cpu->cd.ppc.dec_intr_pending = 1;                          cpu->cd.ppc.dec_intr_pending = 1;
   
451                  old = cpu->cd.ppc.spr[SPR_TBL];                  old = cpu->cd.ppc.spr[SPR_TBL];
452                  cpu->cd.ppc.spr[SPR_TBL] += n_instrs;                  cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
453                  if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)                  if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)
# Line 301  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 476  void DYNTRANS_FUNCTION_TRACE(struct cpu
476          char *symbol;          char *symbol;
477          uint64_t ot;          uint64_t ot;
478          int x, print_dots = 1, n_args_to_print =          int x, print_dots = 1, n_args_to_print =
479  #ifdef DYNTRANS_ALPHA  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
480              6              6
481  #else  #else
482  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
# Line 361  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 536  void DYNTRANS_FUNCTION_TRACE(struct cpu
536  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
537                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
538  #endif  #endif
 #ifdef DYNTRANS_NEWMIPS  
                     r[0         /*  TODO  */  
 #endif  
539  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
540                      gpr[3                      gpr[3
541  #endif  #endif
# Line 371  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 543  void DYNTRANS_FUNCTION_TRACE(struct cpu
543                      r[2                      r[2
544  #endif  #endif
545  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
546                      r_i[0                      r[24
547  #endif  #endif
548                      + x];                      + x];
549  #endif  #endif
# Line 386  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 558  void DYNTRANS_FUNCTION_TRACE(struct cpu
558                          fatal("&%s", symbol);                          fatal("&%s", symbol);
559                  else {                  else {
560                          if (cpu->is_32bit)                          if (cpu->is_32bit)
561                                  fatal("0x%x", (int)d);                                  fatal("0x%"PRIx32, (uint32_t)d);
562                          else                          else
563                                  fatal("0x%llx", (long long)d);                                  fatal("0x%"PRIx64, (uint64_t)d);
564                  }                  }
565    
566                  if (x < n_args_to_print - 1)                  if (x < n_args_to_print - 1)
# Line 403  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 575  void DYNTRANS_FUNCTION_TRACE(struct cpu
575    
576    
577  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
 /*  forward declaration of to_be_translated and end_of_page:  */  
 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);  
 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
578  /*  /*
579   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
580   *   *
# Line 420  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 585  static void DYNTRANS_TC_ALLOCATE_DEFAULT
585          uint64_t physaddr)          uint64_t physaddr)
586  {  {
587          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
588    
         /*  Create the physpage header:  */  
589          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
590              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
591    
592          /*  TODO: Is this faster than copying an entire template page?  */          /*  Copy the entire template page first:  */
593          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
594                  ppp->ics[i].f =              struct DYNTRANS_TC_PHYSPAGE));
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
595    
596          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE].f =          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page) :  
 #endif  
             instr(end_of_page);  
597    
598          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
599    
600          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
601          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
602          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
603  }  }
604  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 465  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 618  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
618  #else  #else
619          uint64_t          uint64_t
620  #endif  #endif
621              cached_pc, physaddr = 0;              cached_pc = cpu->pc, physaddr = 0;
622          uint32_t physpage_ofs;          uint32_t physpage_ofs;
623          int ok, pagenr, table_index;          int ok, pagenr, table_index;
624          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
625          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
626    
627  #ifdef MODE32  #ifdef MODE32
628          int index;          int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
         cached_pc = cpu->pc;  
         index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
 #else  
 #ifdef DYNTRANS_ALPHA  
         uint32_t a, b;  
         int kernel = 0;  
         struct alpha_vph_page *vph_p;  
         cached_pc = cpu->pc;  
         a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
         b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
         if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {  
                 vph_p = cpu->cd.alpha.vph_table0_kernel[a];  
                 kernel = 1;  
         } else  
                 vph_p = cpu->cd.alpha.vph_table0[a];  
629  #else  #else
630  #ifdef DYNTRANS_IA64          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
631          fatal("IA64 todo\n");          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
632  #else          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
633          fatal("Neither alpha, ia64, nor 32-bit? 3\n");          uint32_t x1, x2, x3;
634          exit(1);          struct DYNTRANS_L2_64_TABLE *l2;
635  #endif          struct DYNTRANS_L3_64_TABLE *l3;
636  #endif  
637            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
638            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
639            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
640            /*  fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n",
641                (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3);  */
642            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
643            /*  fatal("  l2 = %p\n", l2);  */
644            l3 = l2->l3[x2];
645            /*  fatal("  l3 = %p\n", l3);  */
646  #endif  #endif
647    
648          /*  Virtual to physical address translation:  */          /*  Virtual to physical address translation:  */
# Line 506  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 653  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
653                  ok = 1;                  ok = 1;
654          }          }
655  #else  #else
656  #ifdef DYNTRANS_ALPHA          if (l3->host_load[x3] != NULL) {
657          if (vph_p->host_load[b] != NULL) {                  physaddr = l3->phys_addr[x3];
                 physaddr = vph_p->phys_addr[b];  
658                  ok = 1;                  ok = 1;
659          }          }
 #else  
 #ifdef DYNTRANS_IA64  
         fatal("IA64 todo\n");  
 #else  
         fatal("Neither alpha, ia64, nor 32-bit? 4\n");  
         exit(1);  
 #endif  
 #endif  
660  #endif  #endif
661    
662          if (!ok) {          if (!ok) {
663                  uint64_t paddr;                  uint64_t paddr;
664                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
665                          ok = cpu->translate_address(cpu, cached_pc,                          ok = cpu->translate_v2p(
666                              &paddr, FLAG_INSTR);                              cpu, cached_pc, &paddr, FLAG_INSTR);
667                  else {                  } else {
668                          paddr = cached_pc;                          paddr = cached_pc;
669                          ok = 1;                          ok = 1;
670                  }                  }
671                  if (!ok) {                  if (!ok) {
672                          /*  fatal("TODO: instruction vaddr=>paddr translation"                          /*  fatal("TODO: instruction vaddr=>paddr translation "
673                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                              "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
674                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */                          fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
675    
676                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
677                              FLAG_INSTR);                              FLAG_INSTR);
678    
679                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
680                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
681                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */                          fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
682    
683                          if (!ok) {                          if (!ok) {
684                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
# Line 548  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 686  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
686                                  exit(1);                                  exit(1);
687                          }                          }
688                  }                  }
689    
690                    /*  If there was an exception, the PC can have changed.
691                        Update cached_pc:  */
692                  cached_pc = cpu->pc;                  cached_pc = cpu->pc;
693    
694  #ifdef MODE32  #ifdef MODE32
695                  index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);                  index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
696    #else
697                    x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
698                    x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
699                    x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
700                        & mask3;
701  #endif  #endif
702    
703                  physaddr = paddr;                  physaddr = paddr;
704          }          }
705    
706  #ifdef MODE32  #ifdef MODE32
707          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
708    #else
709            if (l3->host_load[x3] == NULL) {
710    #endif
711                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
712                      physaddr, MEM_READ);                      physaddr, MEM_READ);
713                  if (host_page != NULL) {                  if (host_page != NULL) {
# Line 564  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 715  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
715                          host_page += (physaddr &                          host_page += (physaddr &
716                              ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);                              ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);
717                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
718                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr & ~q);
719    #ifndef MODE32
720                            /*  Recalculate l2 and l3, since they might have
721                                changed now:  */
722                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
723                            l3 = l2->l3[x2];
724    #endif
725                  }                  }
726          }          }
 #endif  
727    
728          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {
729                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
730                    fatal("[ dyntrans: resetting the translation cache ]\n");
731    #endif
732                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
733          }          }
734    
735            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
736    
737          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);          pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
738          table_index = PAGENR_TO_TABLE_INDEX(pagenr);          table_index = PAGENR_TO_TABLE_INDEX(pagenr);
739    
# Line 585  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 745  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
745          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
746                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
747                      + physpage_ofs);                      + physpage_ofs);
748    
749                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
750                  if (ppp->physaddr == physaddr)                  if (ppp->physaddr == physaddr)
751                          break;                          break;
752    
753                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
754                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
755          }          }
# Line 596  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 758  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
758              new "default" empty translation page.  */              new "default" empty translation page.  */
759    
760          if (ppp == NULL) {          if (ppp == NULL) {
761                  /*  fatal("CREATING page %lli (physaddr 0x%llx), table index "                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
762                      "%i\n", (long long)pagenr, (long long)physaddr,                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,
763                      (int)table_index);  */                      (int)table_index);  */
764                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
765                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
# Line 612  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 774  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
774  #ifdef MODE32  #ifdef MODE32
775          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
776                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
777  #endif  #else
778            if (l3->host_load[x3] != NULL)
779  #ifdef DYNTRANS_ALPHA                  l3->phys_page[x3] = ppp;
         if (vph_p->host_load[b] != NULL)  
                 vph_p->phys_page[b] = ppp;  
780  #endif  #endif
781    
782  #ifdef MODE32  #ifdef MODE32
# Line 634  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 794  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
794          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 +
795              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
796    
797          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
798              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
799              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
800  }  }
801    
802    
# Line 660  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 820  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
820  #else  #else
821          uint64_t          uint64_t
822  #endif  #endif
823              cached_pc;              cached_pc = cpu->pc;
824          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
825    
826  #ifdef MODE32  #ifdef MODE32
827          int index;          int index;
         cached_pc = cpu->pc;  
828          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
829          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
830          if (ppp != NULL)          if (ppp != NULL)
831                  goto have_it;                  goto have_it;
832  #else  #else
833  #ifdef DYNTRANS_ALPHA          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
834          uint32_t a, b;          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
835          int kernel = 0;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
836          struct alpha_vph_page *vph_p;          uint32_t x1, x2, x3;
837          cached_pc = cpu->pc;          struct DYNTRANS_L2_64_TABLE *l2;
838          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          struct DYNTRANS_L3_64_TABLE *l3;
839          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
840          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
841                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
842                  kernel = 1;          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
843          } else          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
844                  vph_p = cpu->cd.alpha.vph_table0[a];          l3 = l2->l3[x2];
845          if (vph_p != cpu->cd.alpha.vph_default_page) {          ppp = l3->phys_page[x3];
846                  ppp = vph_p->phys_page[b];          if (ppp != NULL)
847                  if (ppp != NULL)                  goto have_it;
                         goto have_it;  
         }  
 #else  
         /*  Temporary, to avoid a compiler warning:  */  
         cached_pc = 0;  
         ppp = NULL;  
 #ifdef DYNTRANS_IA64  
         fatal("IA64 todo\n");  
 #else  
         fatal("Neither alpha, ia64, nor 32-bit? 1\n");  
         exit(1);  
 #endif  
 #endif  
848  #endif  #endif
849    
850          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
851          return;          return;
852    
853          /*  Quick return path:  */          /*  Quick return path:  */
 #if defined(MODE32) || defined(DYNTRANS_ALPHA)  
854  have_it:  have_it:
855          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
856          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 +
857              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
858    
859          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
860              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
861              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
 #endif  
862  }  }
863  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
864    
865    
866    
867    #ifdef DYNTRANS_INIT_TABLES
868    
869    /*  forward declaration of to_be_translated and end_of_page:  */
870    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
871    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
872    #ifdef DYNTRANS_DUALMODE_32
873    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
874    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
875    #endif
876    
877    #ifdef DYNTRANS_DELAYSLOT
878    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
879    #ifdef DYNTRANS_DUALMODE_32
880    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
881    #endif
882    #endif
883    
884    /*
885     *  XXX_init_tables():
886     *
887     *  Initializes the default translation page (for newly allocated pages), and
888     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
889     */
890    void DYNTRANS_INIT_TABLES(struct cpu *cpu)
891    {
892    #ifndef MODE32
893            struct DYNTRANS_L2_64_TABLE *dummy_l2;
894            struct DYNTRANS_L3_64_TABLE *dummy_l3;
895            int x1, x2;
896    #endif
897            int i;
898            struct DYNTRANS_TC_PHYSPAGE *ppp = malloc(sizeof(
899                struct DYNTRANS_TC_PHYSPAGE));
900    
901            if (ppp == NULL) {
902                    fprintf(stderr, "out of memory\n");
903                    exit(1);
904            }
905    
906            ppp->next_ofs = 0;
907            /*  ppp->physaddr is filled in by the page allocator  */
908    
909            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
910                    ppp->ics[i].f =
911    #ifdef DYNTRANS_DUALMODE_32
912                        cpu->is_32bit? instr32(to_be_translated) :
913    #endif
914                        instr(to_be_translated);
915    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
916                    ppp->ics[i].arg[0] = 0;
917    #endif
918            }
919    
920            /*  End-of-page:  */
921            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
922    #ifdef DYNTRANS_DUALMODE_32
923                cpu->is_32bit? instr32(end_of_page) :
924    #endif
925                instr(end_of_page);
926    
927    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
928            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].arg[0] = 0;
929    #endif
930    
931            /*  End-of-page-2, for delay-slot architectures:  */
932    #ifdef DYNTRANS_DELAYSLOT
933            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
934    #ifdef DYNTRANS_DUALMODE_32
935                cpu->is_32bit? instr32(end_of_page2) :
936    #endif
937                instr(end_of_page2);
938    #endif
939    
940            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
941    
942    
943            /*  Prepare 64-bit virtual address translation tables:  */
944    #ifndef MODE32
945            if (cpu->is_32bit)
946                    return;
947    
948            dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
949            dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
950    
951            cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
952            cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
953    
954            for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
955                    cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
956    
957            for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
958                    dummy_l2->l3[x2] = dummy_l3;
959    #endif
960    }
961    #endif  /*  DYNTRANS_INIT_TABLES  */
962    
963    
964    
965  #ifdef DYNTRANS_INVAL_ENTRY  #ifdef DYNTRANS_INVAL_ENTRY
966  /*  /*
967   *  XXX_invalidate_tlb_entry():   *  XXX_invalidate_tlb_entry():
# Line 750  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 992  static void DYNTRANS_INVALIDATE_TLB_ENTR
992                      (int)vaddr_page);  */                      (int)vaddr_page);  */
993                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
994          } else {          } else {
995                    int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
996                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
997                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
998                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
999                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1000                    if (tlbi > 0)
1001                            cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1002                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1003          }          }
1004  #else  #else
1005          /*  2-level:  */          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1006  #ifdef DYNTRANS_ALPHA          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1007          struct alpha_vph_page *vph_p;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1008          uint32_t a, b;          uint32_t x1, x2, x3;
1009          int kernel = 0;          struct DYNTRANS_L2_64_TABLE *l2;
1010            struct DYNTRANS_L3_64_TABLE *l3;
1011          a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
1012          b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1013          if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1014                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))& mask3;
                 kernel = 1;  
         } else  
                 vph_p = cpu->cd.alpha.vph_table0[a];  
1015    
1016          if (vph_p == cpu->cd.alpha.vph_default_page) {          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1017                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n");          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1018                  exit(1);                  return;
1019          }  
1020            l3 = l2->l3[x2];
1021            if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1022                    return;
1023    
1024          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
1025                  vph_p->host_store[b] = NULL;                  l3->host_store[x3] = NULL;
1026                  return;                  return;
1027          }          }
1028          vph_p->host_load[b] = NULL;          l3->host_load[x3] = NULL;
1029          vph_p->host_store[b] = NULL;          l3->host_store[x3] = NULL;
1030          vph_p->phys_addr[b] = 0;          l3->phys_addr[x3] = 0;
1031          vph_p->phys_page[b] = NULL;          l3->phys_page[x3] = NULL;
1032          vph_p->refcount --;          l3->refcount --;
1033          if (vph_p->refcount < 0) {          if (l3->refcount < 0) {
1034                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n");                  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1035                  exit(1);                  exit(1);
1036          }          }
1037          if (vph_p->refcount == 0) {          if (l3->refcount == 0) {
1038                  vph_p->next = cpu->cd.alpha.vph_next_free_page;                  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1039                  cpu->cd.alpha.vph_next_free_page = vph_p;                  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1040                  if (kernel)                  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1041                          cpu->cd.alpha.vph_table0_kernel[a] =  
1042                              cpu->cd.alpha.vph_default_page;                  l2->refcount --;
1043                  else                  if (l2->refcount < 0) {
1044                          cpu->cd.alpha.vph_table0[a] =                          fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1045                              cpu->cd.alpha.vph_default_page;                          exit(1);
1046                    }
1047                    if (l2->refcount == 0) {
1048                            l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1049                            cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1050                            cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1051                                cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1052                    }
1053          }          }
 #else   /*  !DYNTRANS_ALPHA  */  
 #ifdef DYNTRANS_IA64  
         fatal("IA64: blah blah TODO\n");  
 #else  
         fatal("Not yet for non-1-level, non-Alpha, non-ia64\n");  
 #endif  /*  !DYNTRANS_IA64  */  
 #endif  /*  !DYNTRANS_ALPHA  */  
1054  #endif  #endif
1055  }  }
1056  #endif  #endif
# Line 821  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1066  static void DYNTRANS_INVALIDATE_TLB_ENTR
1066   *  flags should be one of   *  flags should be one of
1067   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL
1068   *   *
1069     *  In addition, for INVALIDATE_ALL, INVALIDATE_VADDR_UPPER4 may be set and
1070     *  bit 31..28 of addr are used to select the virtual addresses to invalidate.
1071     *  (This is useful for PowerPC emulation, when segment registers are updated.)
1072     *
1073   *  In the case when all translations are invalidated, paddr doesn't need   *  In the case when all translations are invalidated, paddr doesn't need
1074   *  to be supplied.   *  to be supplied.
1075   *   *
# Line 828  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1077  static void DYNTRANS_INVALIDATE_TLB_ENTR
1077   *             the quick translation array, not from the linear   *             the quick translation array, not from the linear
1078   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
1079   */   */
1080  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t paddr, int flags)  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
1081  {  {
1082          int r;          int r;
1083  #ifdef MODE32  #ifdef MODE32
# Line 836  void DYNTRANS_INVALIDATE_TC(struct cpu * Line 1085  void DYNTRANS_INVALIDATE_TC(struct cpu *
1085  #else  #else
1086          uint64_t          uint64_t
1087  #endif  #endif
1088              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);              addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
1089    
1090          /*  fatal("invalidate(): ");  */          /*  fatal("invalidate(): ");  */
1091    
1092          /*  Quick case for virtual addresses: see note above.  */          /*  Quick case for _one_ virtual addresses: see note above.  */
1093          if (flags & INVALIDATE_VADDR) {          if (flags & INVALIDATE_VADDR) {
1094                  /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */                  /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */
1095                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
1096                  return;                  return;
1097          }          }
1098    
1099            /*  Invalidate everything:  */
1100    #ifdef DYNTRANS_PPC
1101            if (flags & INVALIDATE_ALL && flags & INVALIDATE_VADDR_UPPER4) {
1102                    /*  fatal("all, upper4 (PowerPC segment)\n");  */
1103                    for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1104                            if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
1105                                (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page
1106                                & 0xf0000000) == addr_page) {
1107                                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
1108                                        DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1109                                        0);
1110                                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1111                            }
1112                    }
1113                    return;
1114            }
1115    #endif
1116          if (flags & INVALIDATE_ALL) {          if (flags & INVALIDATE_ALL) {
1117                  /*  fatal("all\n");  */                  /*  fatal("all\n");  */
1118                  for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {                  for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
# Line 860  void DYNTRANS_INVALIDATE_TC(struct cpu * Line 1126  void DYNTRANS_INVALIDATE_TC(struct cpu *
1126                  return;                  return;
1127          }          }
1128    
1129          /*  fatal("paddr 0x%08x\n", (int)addr_page);  */          /*  Invalidate a physical page:  */
1130    
1131            if (!(flags & INVALIDATE_PADDR))
1132                    fatal("HUH? Invalidate: Not vaddr, all, or paddr?\n");
1133    
1134            /*  fatal("addr 0x%08x\n", (int)addr_page);  */
1135    
1136          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1137                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
1138                      (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) ) {  
1139                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
1140                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1141                              flags);                              flags);
# Line 935  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1204  void DYNTRANS_INVALIDATE_TC_CODE(struct
1204                          prev_ppp = ppp;                          prev_ppp = ppp;
1205                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1206                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1207    
1208                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1209                              then we're done:  */                              then we're done:  */
1210                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1211                                  break;                                  break;
1212    
1213                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1214                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1215                  }                  }
# Line 982  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1253  void DYNTRANS_INVALIDATE_TC_CODE(struct
1253  #endif  #endif
1254          }          }
1255    
1256          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1257          for (r = DYNTRANS_MAX_VPH_TLB_ENTRIES/2;          for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
              r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {  
1258                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1259                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1260                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1003  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1273  void DYNTRANS_INVALIDATE_TC_CODE(struct
1273                                  cpu->cd.DYNTRANS_ARCH.phystranslation[                                  cpu->cd.DYNTRANS_ARCH.phystranslation[
1274                                      index >> 5] &= ~ (1 << (index & 31));                                      index >> 5] &= ~ (1 << (index & 31));
1275  #else  #else
1276                                  /*  2-level:  */                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1277  #ifdef DYNTRANS_ALPHA                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1278                                  struct alpha_vph_page *vph_p;                                  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1279                                  uint32_t a, b;                                  uint32_t x1, x2, x3;
1280                                  int kernel = 0;                                  struct DYNTRANS_L2_64_TABLE *l2;
1281                                    struct DYNTRANS_L3_64_TABLE *l3;
1282                                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT)  
1283                                      & (ALPHA_LEVEL0 - 1);                                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1284                                  b = (vaddr_page >> ALPHA_LEVEL1_SHIFT)                                  x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1285                                      & (ALPHA_LEVEL1 - 1);                                      DYNTRANS_L2N)) & mask2;
1286                                  if ((vaddr_page >> ALPHA_TOPSHIFT) ==                                  x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1287                                      ALPHA_TOP_KERNEL) {                                      DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1288                                          vph_p = cpu->cd.alpha.                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1289                                              vph_table0_kernel[a];                                  l3 = l2->l3[x2];
1290                                          kernel = 1;                                  l3->phys_page[x3] = NULL;
                                 } else  
                                         vph_p = cpu->cd.alpha.vph_table0[a];  
                                 vph_p->phys_page[b] = NULL;  
 #else   /*  !DYNTRANS_ALPHA  */  
 #ifdef DYNTRANS_IA64  
                                 fatal("IA64: blah yo yo TODO\n");  
 #else  
                                 fatal("Not yet for non-1-level, non-Alpha, "  
                                     "non-ia64\n");  
 #endif  /*  !DYNTRANS_IA64  */  
 #endif  /*  !DYNTRANS_ALPHA  */  
1291  #endif  #endif
1292                          }                          }
1293                  }                  }
# Line 1050  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1309  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1309  #ifndef MODE32  #ifndef MODE32
1310          int64_t lowest, highest = -1;          int64_t lowest, highest = -1;
1311  #endif  #endif
1312          int found, r, lowest_index, start, end, useraccess = 0;          int found, r, lowest_index, useraccess = 0;
1313    
 #ifdef DYNTRANS_ALPHA  
         uint32_t a, b;  
         struct alpha_vph_page *vph_p;  
         int kernel = 0;  
         /*  fatal("update_translation_table(): v=0x%llx, h=%p w=%i"  
             " p=0x%llx\n", (long long)vaddr_page, host_page, writeflag,  
             (long long)paddr_page);  */  
 #else  
1314  #ifdef MODE32  #ifdef MODE32
1315          uint32_t index;          uint32_t index;
1316          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
# Line 1068  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1319  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1319              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1320              (int)paddr_page);  */              (int)paddr_page);  */
1321  #else   /*  !MODE32  */  #else   /*  !MODE32  */
1322  #ifdef DYNTRANS_IA64          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1323          fatal("IA64 update todo\n");          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1324  #else          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1325          fatal("Neither 32-bit, IA64, nor Alpha? 2\n");          uint32_t x1, x2, x3;
1326          exit(1);          struct DYNTRANS_L2_64_TABLE *l2;
1327  #endif          struct DYNTRANS_L3_64_TABLE *l3;
1328  #endif          /*  fatal("update_translation_table(): v=0x%"PRIx64", h=%p w=%i"
1329                " p=0x%"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1330                (uint64_t)paddr_page);  */
1331  #endif  #endif
1332    
1333            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1334            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1335    
1336          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1337                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1338                  useraccess = 1;                  useraccess = 1;
1339          }          }
1340    
         start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  
 #if 1  
         /*  Half of the TLB used for data, half for code:  */  
         if (writeflag & TLB_CODE) {  
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
 #endif  
   
1341          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
1342          lowest_index = start;          lowest_index = 0;
1343    
1344  #ifdef MODE32  #ifdef MODE32
1345          /*          /*
# Line 1110  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1354  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1354              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1355          if (found < 0) {          if (found < 0) {
1356                  static unsigned int x = 0;                  static unsigned int x = 0;
1357                  lowest_index = (x % (end-start)) + start;                  lowest_index = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
                 x ++;  
1358          }          }
1359  #else  #else
1360          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;
1361          found = -1;          found = -1;
1362          for (r=start; r<end; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1363                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {
1364                          lowest = cpu->cd.DYNTRANS_ARCH.                          lowest = cpu->cd.DYNTRANS_ARCH.
1365                              vph_tlb_entry[r].timestamp;                              vph_tlb_entry[r].timestamp;
# Line 1155  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1398  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1398  #endif  #endif
1399    
1400                  /*  Add the new translation to the table:  */                  /*  Add the new translation to the table:  */
 #ifdef DYNTRANS_ALPHA  
                 a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
                 b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
                 if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {  
                         vph_p = cpu->cd.alpha.vph_table0_kernel[a];  
                         kernel = 1;  
                 } else  
                         vph_p = cpu->cd.alpha.vph_table0[a];  
                 if (vph_p == cpu->cd.alpha.vph_default_page) {  
                         if (cpu->cd.alpha.vph_next_free_page != NULL) {  
                                 if (kernel)  
                                         vph_p = cpu->cd.alpha.vph_table0_kernel  
                                             [a] = cpu->cd.alpha.  
                                             vph_next_free_page;  
                                 else  
                                         vph_p = cpu->cd.alpha.vph_table0[a] =  
                                             cpu->cd.alpha.vph_next_free_page;  
                                 cpu->cd.alpha.vph_next_free_page = vph_p->next;  
                         } else {  
                                 if (kernel)  
                                         vph_p = cpu->cd.alpha.vph_table0_kernel  
                                             [a] = malloc(sizeof(struct  
                                             alpha_vph_page));  
                                 else  
                                         vph_p = cpu->cd.alpha.vph_table0[a] =  
                                             malloc(sizeof(struct  
                                             alpha_vph_page));  
                                 memset(vph_p, 0, sizeof(struct alpha_vph_page));  
                         }  
                 }  
                 vph_p->refcount ++;  
                 vph_p->host_load[b] = host_page;  
                 vph_p->host_store[b] = writeflag? host_page : NULL;  
                 vph_p->phys_addr[b] = paddr_page;  
                 vph_p->phys_page[b] = NULL;  
 #else  
1401  #ifdef MODE32  #ifdef MODE32
1402                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1403                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
# Line 1204  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1411  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1411                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1412                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1413  #endif  #endif
1414  #endif  /*  32  */  #else   /* !MODE32  */
1415  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1416                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1417                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1418                        & mask3;
1419                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1420                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1421                            if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1422                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1423                                        cpu->cd.DYNTRANS_ARCH.next_free_l2;
1424                                    cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1425                            } else {
1426                                    int i;
1427                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1428                                        malloc(sizeof(struct DYNTRANS_L2_64_TABLE));
1429                                    for (i=0; i<(1 << DYNTRANS_L2N); i++)
1430                                            l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1431                                                l3_64_dummy;
1432                            }
1433                    }
1434                    l3 = l2->l3[x2];
1435                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1436                            if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1437                                    l3 = l2->l3[x2] =
1438                                        cpu->cd.DYNTRANS_ARCH.next_free_l3;
1439                                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1440                            } else {
1441                                    l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1442                                        struct DYNTRANS_L3_64_TABLE));
1443                            }
1444                            l2->refcount ++;
1445                    }
1446                    l3->host_load[x3] = host_page;
1447                    l3->host_store[x3] = writeflag? host_page : NULL;
1448                    l3->phys_addr[x3] = paddr_page;
1449                    l3->phys_page[x3] = NULL;
1450                    l3->vaddr_to_tlbindex[x3] = r + 1;
1451                    l3->refcount ++;
1452    #endif  /* !MODE32  */
1453          } else {          } else {
1454                  /*                  /*
1455                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
# Line 1221  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1465  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1465                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1466                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
1467                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
 #ifdef DYNTRANS_ALPHA  
                 a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
                 b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
                 if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {  
                         vph_p = cpu->cd.alpha.vph_table0_kernel[a];  
                         kernel = 1;  
                 } else  
                         vph_p = cpu->cd.alpha.vph_table0[a];  
                 vph_p->phys_page[b] = NULL;  
                 if (vph_p->phys_addr[b] == paddr_page) {  
                         if (writeflag & MEM_WRITE)  
                                 vph_p->host_store[b] = host_page;  
                         if (writeflag & MEM_DOWNGRADE)  
                                 vph_p->host_store[b] = NULL;  
                 } else {  
                         /*  Change the entire physical/host mapping:  */  
                         vph_p->host_load[b] = host_page;  
                         vph_p->host_store[b] = writeflag? host_page : NULL;  
                         vph_p->phys_addr[b] = paddr_page;  
                 }  
 #else  
1468  #ifdef MODE32  #ifdef MODE32
1469                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1470                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
# Line 1264  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1487  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1487                              writeflag? host_page : NULL;                              writeflag? host_page : NULL;
1488                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1489                  }                  }
1490  #endif  /*  32  */  #else   /*  !MODE32  */
1491  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1492                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1493                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1494                        & mask3;
1495                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1496                    l3 = l2->l3[x2];
1497                    if (l3->phys_addr[x3] == paddr_page) {
1498                            if (writeflag & MEM_WRITE)
1499                                    l3->host_store[x3] = host_page;
1500                            if (writeflag & MEM_DOWNGRADE)
1501                                    l3->host_store[x3] = NULL;
1502                    } else {
1503                            /*  Change the entire physical/host mapping:  */
1504                            l3->host_load[x3] = host_page;
1505                            l3->host_store[x3] = writeflag? host_page : NULL;
1506                            l3->phys_addr[x3] = paddr_page;
1507                    }
1508    #endif  /*  !MODE32  */
1509          }          }
1510  }  }
1511  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */
# Line 1279  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1519  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1519           *  Check for breakpoints.           *  Check for breakpoints.
1520           */           */
1521          if (!single_step_breakpoint) {          if (!single_step_breakpoint) {
1522  #ifdef MODE32                  MODE_uint_t curpc = cpu->pc;
                 uint32_t curpc = cpu->pc;  
 #else  
                 uint64_t curpc = cpu->pc;  
 #endif  
1523                  int i;                  int i;
1524                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->n_breakpoints; i++)
1525                          if (curpc ==                          if (curpc == (MODE_uint_t)
 #ifdef MODE32  
                             (uint32_t)  
 #endif  
1526                              cpu->machine->breakpoint_addr[i]) {                              cpu->machine->breakpoint_addr[i]) {
1527                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1528                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1529                                          quiet_mode = 0;                                          quiet_mode = 0;
1530                                          DISASSEMBLE(cpu, ib, 1, 0, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1531                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1532                                  }                                  }
1533                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "                                  fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1534                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1535                                      (long long)cpu->pc);                                      (uint64_t)cpu->pc);
1536    #ifdef DYNTRANS_DELAYSLOT
1537                                    if (cpu->delay_slot != NOT_DELAYED)
1538                                            fatal("ERROR! Breakpoint in a delay"
1539                                                " slot! Not yet supported.\n");
1540    #endif
1541                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1542                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1543                                  goto stop_running_translated;                                  goto stop_running_translated;
1544                          }                          }
1545          }          }
# Line 1319  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1557  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1557           *  (Special case for 32-bit mode: set the corresponding bit in the           *  (Special case for 32-bit mode: set the corresponding bit in the
1558           *  phystranslation[] array.)           *  phystranslation[] array.)
1559           */           */
1560            /*  Make sure cur_physpage is in synch:  */
1561            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1562                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1563  #ifdef MODE32  #ifdef MODE32
1564          if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {          if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {
1565                  uint32_t index = DYNTRANS_ADDR_TO_PAGENR(addr);                  uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);
1566                  cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=                  cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=
1567                      (1 << (index & 31));                      (1 << (index & 31));
1568          }          }
# Line 1334  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1575  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1575           *  be converted into a single function call.           *  be converted into a single function call.
1576           *           *
1577           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1578           *  instruction combination.           *  instruction combination. For architectures with delay slots,
1579             *  we also ignore combinations if the delay slot is across a page
1580             *  boundary.
1581           */           */
1582          if (!single_step && !cpu->machine->instruction_trace) {          if (!single_step && !cpu->machine->instruction_trace
1583    #ifdef DYNTRANS_DELAYSLOT
1584                && !in_crosspage_delayslot
1585    #endif
1586                ) {
1587                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&
1588                      cpu->machine->speed_tricks)                      cpu->machine->speed_tricks)
1589                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1590                              addr & (DYNTRANS_PAGESIZE - 1));                              addr & (DYNTRANS_PAGESIZE - 1));
1591                  cpu->cd.DYNTRANS_ARCH.combination_check = NULL;          }
1592    
1593            cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1594    
1595            /*  An additional check, to catch some bugs:  */
1596            if (ic->f == (
1597    #ifdef DYNTRANS_DUALMODE_32
1598                cpu->is_32bit? instr32(to_be_translated) :
1599    #endif
1600                instr(to_be_translated))) {
1601                    fatal("INTERNAL ERROR: ic->f not set!\n");
1602                    goto bad;
1603            }
1604            if (ic->f == NULL) {
1605                    fatal("INTERNAL ERROR: ic->f == NULL!\n");
1606                    goto bad;
1607          }          }
1608    
1609          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1610          if (single_step_breakpoint) {          if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1611    #ifdef DYNTRANS_DELAYSLOT
1612                || in_crosspage_delayslot
1613    #endif
1614                ) {
1615                  /*                  /*
1616                   *  Special case when single-stepping: Execute the translated                   *  Special case when single-stepping: Execute the translated
1617                   *  instruction, but then replace it with a "to be translated"                   *  instruction, but then replace it with a "to be translated"
1618                   *  directly afterwards.                   *  directly afterwards.
1619                   */                   */
1620                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
1621    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1622                    cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1623    #endif
1624                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1625                  ic->f =                  ic->f =
1626  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1627                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
1628  #endif  #endif
1629                      instr(to_be_translated);                      instr(to_be_translated);
1630          } else  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1631                    ic->arg[0] = 0;
1632    #endif
1633            } else {
1634    #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH
1635                    cpu->cd.DYNTRANS_ARCH.next_ic = ic + ic->arg[0];
1636    
1637                    /*  Additional check, for variable length ISAs:  */
1638                    if (ic->arg[0] == 0) {
1639                            fatal("INTERNAL ERROR: instr len = 0!\n");
1640                            goto bad;
1641                    }
1642    #endif
1643    
1644                    /*  Finally finally :-), execute the instruction:  */
1645                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1646            }
1647    
1648          return;          return;
1649    
# Line 1373  bad:   /* Line 1657  bad:   /*
1657    
1658          if (cpu->machine->instruction_trace)          if (cpu->machine->instruction_trace)
1659  #ifdef MODE32  #ifdef MODE32
1660                  fatal(" at 0x%x\n", (int)cpu->pc);                  fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1661  #else  #else
1662                  fatal(" at 0x%llx\n", (long long)cpu->pc);                  fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1663  #endif  #endif
1664          else {          else {
1665                  fatal(":\n");                  fatal(":\n");
1666                  DISASSEMBLE(cpu, ib, 1, 0, 0);                  DISASSEMBLE(cpu, ib, 1, 0);
1667          }          }
1668    
1669          cpu->running = 0;          cpu->running = 0;

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

  ViewVC Help
Powered by ViewVC 1.1.26