/[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 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2007  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.165 2007/06/15 21:43:53 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31   */   */
32    
33    
34  #ifdef  DYNTRANS_CPU_RUN_INSTR  #ifndef STATIC_STUFF
35    #define STATIC_STUFF
36    /*
37     *  gather_statistics():
38     */
39  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
40  {  {
41            char ch, buf[60];
42            struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
43            int i = 0;
44          uint64_t a;          uint64_t a;
45          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)          int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
46              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
47          if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
48            if (cpu->machine->statistics_file == NULL) {
49                    fatal("statistics gathering with no filename set is"
50                        " meaningless\n");
51                  return;                  return;
52            }
53    
54  #if 0          /*  low_pc must be within the page!  */
55          /*  Use the physical address:  */          if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
56          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)                  return;
             cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
         a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;  
 #else  
         /*  Use the PC (virtual address):  */  
         a = cpu->pc;  
 #endif  
57    
58          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<          buf[0] = '\0';
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
59    
60          /*          while ((ch = cpu->machine->statistics_fields[i]) != '\0') {
61           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
62           */                          strlcat(buf, " ", sizeof(buf));
63  a &= 0x03ffffff;  
64  {                  switch (ch) {
65          static long long *array = NULL;                  case 'i':
66          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
67          static int n = 0;                              "%p", (void *)ic->f);
68          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
69          if (array == NULL)                  case 'p':
70                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
71          if (array_16kpage_in_use == NULL)                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
72                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
73          a &= (16384*1024-1);                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
74          array[a] ++;                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
75          array_16kpage_in_use[a / 16384] = 1;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
76          n++;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
77          if ((n & 0x3fffffff) == 0) {                          if (cpu->is_32bit)
78                  FILE *f = fopen("statistics.out", "w");                                  snprintf(buf + strlen(buf), sizeof(buf),
79                  int i, j;                                      "0x%08"PRIx32, (uint32_t)a);
80                  printf("Saving statistics... "); fflush(stdout);                          else
81                  for (i=0; i<1024; i++)                                  snprintf(buf + strlen(buf), sizeof(buf),
82                          if (array_16kpage_in_use[i]) {                                      "0x%016"PRIx64, (uint64_t)a);
83                                  for (j=0; j<16384; j++)                          break;
84                                          if (array[i*16384 + j] > 0)                  case 'v':
85                                                  fprintf(f, "%lli\t0x%016llx\n",                          /*  Virtual program counter address:  */
86                                                      (long long)array[i*16384+j],                          a = cpu->pc;
87                                                      (long long)((i*16384+j) <<                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
88                                  DYNTRANS_INSTR_ALIGNMENT_SHIFT));                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
89                          }                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
90                  fclose(f);                          if (cpu->is_32bit)
91                  printf("n=0x%08x\n", n);                                  snprintf(buf + strlen(buf), sizeof(buf),
92                                        "0x%08"PRIx32, (uint32_t)a);
93                            else
94                                    snprintf(buf + strlen(buf), sizeof(buf),
95                                        "0x%016"PRIx64, (uint64_t)a);
96                            break;
97                    }
98                    i++;
99          }          }
100  }  
101            fprintf(cpu->machine->statistics_file, "%s\n", buf);
102  }  }
103    
104    
105  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
106    
107  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
108  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  #if 1
109                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->len;       \  
110                          ic->f(cpu, ic);  /*  The normal instruction execution core:  */
111    #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
112    
113  #else  #else
114  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  
115    /*  For heavy debugging:  */
116    #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
117                    {       \
118                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
119                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
120                                sizeof(struct DYNTRANS_IC);                 \
121                            printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n",  \
122                                cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
123                                ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
124                    } \
125                    ic->f(cpu, ic);
126    
127  #endif  #endif
128    
129    /*  static long long nr_of_I_calls = 0;  */
130    
131    /*  Temporary hack for finding NULL bugs:  */
132    /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;                  \
133                    nr_of_I_calls ++;                                       \
134                    if (ic->f == NULL) {                                    \
135                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
136                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
137                                sizeof(struct DYNTRANS_IC);                 \
138                            cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \
139                                DYNTRANS_INSTR_ALIGNMENT_SHIFT);            \
140                            cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\
141                            printf("Crash at %016"PRIx64"\n", cpu->pc);     \
142                            printf("nr of I calls: %lli\n", nr_of_I_calls); \
143                            printf("Next ic = %p\n", cpu->cd.               \
144                                    DYNTRANS_ARCH.next_ic);                 \
145                            printf("cur ic page = %p\n", cpu->cd.           \
146                                    DYNTRANS_ARCH.cur_ic_page);             \
147                            cpu->running = 0;                               \
148                            return 0;                                       \
149                    }                                                       \
150                    ic->f(cpu, ic);  */
151    
152    /*  Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs:  */
153    /*  #define I           { int k; for (k=1; k<=31; k++)  \
154            cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\
155            if (cpu->cd.mips.gpr[0] != 0) {                 \
156                    fatal("NOOOOOO\n"); exit(1);            \
157            }                                               \
158            ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
159    */
160    #endif  /*  STATIC STUFF  */
161    
162    
163    
164    #ifdef  DYNTRANS_RUN_INSTR
165  /*  /*
166   *  XXX_cpu_run_instr():   *  XXX_run_instr():
167   *   *
168   *  Execute one or more instructions on a specific CPU, using dyntrans.   *  Execute one or more instructions on a specific CPU, using dyntrans.
169     *  (For dualmode archs, this function is included twice.)
170   *   *
171   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
172   *  0 if no instructions were executed.   *  0 if no instructions were executed.
173   */   */
174  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_RUN_INSTR(struct cpu *cpu)
175  {  {
176  #ifdef MODE32          MODE_uint_t cached_pc;
         uint32_t cached_pc;  
 #else  
         uint64_t cached_pc;  
 #endif  
177          int low_pc, n_instrs;          int low_pc, n_instrs;
178    
179            /*  Ugly... fix this some day.  */
180  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
181          if (cpu->is_32bit)  #ifdef MODE32
182                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
183          else  #else
184            DYNTRANS_PC_TO_POINTERS(cpu);
185  #endif  #endif
186    #else
187          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
188    #endif
189    
190          /*          /*
191           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
192           *  conversion; if the conversion caused an exception of some kind           *  conversion; if the conversion caused an exception of some kind
193           *  then interrupts are probably disabled, and the exception will get           *  then interrupts are probably disabled, and the exception will get
194           *  priority over device interrupts.)           *  priority over device interrupts.)
195             *
196             *  TODO: Turn this into a family-specific function somewhere...
197           */           */
198  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
199          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))
200                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
201  #endif  #endif
202    #ifdef DYNTRANS_MIPS
203            {
204                    int enabled, mask;
205                    int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
206                    if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
207                            /*  R3000:  */
208                            enabled = status & MIPS_SR_INT_IE;
209                    } else {
210                            /*  R4000 and others:  */
211                            enabled = (status & STATUS_IE)
212                                && !(status & STATUS_EXL) && !(status & STATUS_ERL);
213                            /*  Special case for R5900/C790/TX79:  */
214                            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
215                                !(status & R5900_STATUS_EIE))
216                                    enabled = 0;
217                    }
218                    mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]
219                        & STATUS_IM_MASK;
220    
221                    if (enabled && mask)
222                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0);
223            }
224    #endif
225  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
226          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) {
227                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
228                            ppc_exception(cpu, PPC_EXCEPTION_DEC);
229                  cpu->cd.ppc.dec_intr_pending = 0;                  cpu->cd.ppc.dec_intr_pending = 0;
230          }          }
231          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)          if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
232                  ppc_exception(cpu, PPC_EXCEPTION_EI);                  ppc_exception(cpu, PPC_EXCEPTION_EI);
233  #endif  #endif
234    #ifdef DYNTRANS_SH
235            if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
236                && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
237                < cpu->cd.sh.int_level)
238                    sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0);
239    #endif
240    
241          cached_pc = cpu->pc;          cached_pc = cpu->pc;
242    
243          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
         cpu->running_translated = 1;  
244    
245          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
246              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
247    
248          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace
249                || cpu->machine->register_dump) {
250                  /*                  /*
251                   *  Single-step:                   *  Single-step:
252                   */                   */
253                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
254  #ifndef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                  if (cpu->machine->register_dump) {
255                      ++                          debug("\n");
256  #endif                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
257                      ;                  }
258                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
259  #ifdef DYNTRANS_X86                          /*  TODO/Note: This must be large enough to hold
260                          unsigned char instr[17];                              any instruction for any ISA:  */
261                          cpu->cd.x86.cursegment = X86_S_CS;                          unsigned char instr[1 <<
262                          cpu->cd.x86.seg_override = 0;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT];
 #else  
 #ifdef DYNTRANS_M68K  
                         unsigned char instr[16];        /*  TODO: 16?  */  
 #else  
                         unsigned char instr[4];         /*  General case...  */  
 #endif  
 #endif  
263                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
264                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
265                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
266                                      "the instruction\n");                                      "the instruction\n");
267                          } else                          } else {
268                                  cpu_disassemble_instr(cpu->machine, cpu,  #ifdef DYNTRANS_DELAYSLOT
269                                      instr, 1, 0, 0);                                  int len =
                 }  
   
                 /*  When single-stepping, multiple instruction calls cannot  
                     be combined into one. This clears all translations:  */  
                 if (cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & COMBINATIONS) {  
                         int i;  
                         for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)  
                                 cpu->cd.DYNTRANS_ARCH.cur_physpage->ics[i].f =  
 #ifdef DYNTRANS_DUALMODE_32  
                                     cpu->is_32bit?  
                                         instr32(to_be_translated) :  
270  #endif  #endif
271                                          instr(to_be_translated);                                      cpu_disassemble_instr(
272                          fatal("[ Note: The translation of physical page 0x%llx"                                      cpu->machine, cpu, instr, 1, 0);
273                              " contained combinations of instructions; these "  #ifdef DYNTRANS_DELAYSLOT
274                              "are now flushed because we are single-stepping."                                  /*  Show the instruction in the delay slot,
275                              " ]\n", (long long)cpu->cd.DYNTRANS_ARCH.                                      if any:  */
276                              cur_physpage->physaddr);                                  if (cpu->instruction_has_delayslot == NULL)
277                          cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=                                          fatal("WARNING: ihd func not yet"
278                              ~(COMBINATIONS | TRANSLATIONS);                                              " implemented?\n");
279                                    else if (cpu->instruction_has_delayslot(cpu,
280                                        instr)) {
281                                            int saved_delayslot = cpu->delay_slot;
282                                            cpu->memory_rw(cpu, cpu->mem, cached_pc
283                                                + len, &instr[0],
284                                                sizeof(instr), MEM_READ,
285                                                CACHE_INSTRUCTION);
286                                            cpu->delay_slot = DELAYED;
287                                            cpu->pc += len;
288                                            cpu_disassemble_instr(cpu->machine,
289                                                cpu, instr, 1, 0);
290                                            cpu->delay_slot = saved_delayslot;
291                                            cpu->pc -= len;
292                                    }
293    #endif
294                            }
295                  }                  }
296    
297                  if (show_opcode_statistics)                  if (cpu->machine->statistics_enabled)
298                          S;                          S;
299    
300                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
301                  ic->f(cpu, ic);                  I;
302    
303                  n_instrs = 1;                  n_instrs = 1;
304          } else if (show_opcode_statistics) {          } else if (cpu->machine->statistics_enabled) {
305                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
306                  n_instrs = 0;                  n_instrs = 0;
307                  for (;;) {                  for (;;) {
# Line 222  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 314  int DYNTRANS_CPU_RUN_INSTR(struct emul *
314    
315                          n_instrs += 24;                          n_instrs += 24;
316    
317                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
318                              n_instrs + cpu->n_translated_instrs >= 16384)                              N_SAFE_DYNTRANS_LIMIT)
319                                  break;                                  break;
320                  }                  }
321          } else {          } else {
322                  /*  Execute multiple instructions:  */                  /*
323                     *  Execute multiple instructions:
324                     *
325                     *  (This is the core dyntrans loop.)
326                     */
327                  n_instrs = 0;                  n_instrs = 0;
328                    cpu->sampling = 1;
329    
330                  for (;;) {                  for (;;) {
331                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
332    
# Line 240  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 338  int DYNTRANS_CPU_RUN_INSTR(struct emul *
338    
339                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
340    
341                          n_instrs += 60;                          I; I; I; I; I;   I; I; I; I; I;
342                            I; I; I; I; I;   I; I; I; I; I;
343                            I; I; I; I; I;   I; I; I; I; I;
344                            I; I; I; I; I;   I; I; I; I; I;
345                            I; I; I; I; I;   I; I; I; I; I;
346    
347                            I; I; I; I; I;   I; I; I; I; I;
348    
349                          if (!cpu->running_translated ||                          cpu->n_translated_instrs += 120;
350                              n_instrs + cpu->n_translated_instrs >= 16384)                          if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)
351                                  break;                                  break;
352                  }                  }
353    
354                    cpu->sampling = 0;
355          }          }
356    
357          n_instrs += cpu->n_translated_instrs;          n_instrs += cpu->n_translated_instrs;
# Line 263  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 369  int DYNTRANS_CPU_RUN_INSTR(struct emul *
369                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
370                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<                  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
371                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
372            } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE + 1) {
373                    /*  Switch to next page and skip an instruction which was
374                        already executed (in a delay slot):  */
375                    cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
376                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
377                    cpu->pc += ((DYNTRANS_IC_ENTRIES_PER_PAGE + 1) <<
378                        DYNTRANS_INSTR_ALIGNMENT_SHIFT);
379          }          }
380    
381    #ifdef DYNTRANS_MIPS
382            /*  Update the count register (on everything except EXC3K):  */
383            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
384                    uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
385                    int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
386                    int32_t diff2;
387                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
388                        (int32_t) (old + n_instrs);
389                    diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
390                        cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
391    
392                    if (cpu->cd.mips.compare_register_set) {
393    #if 1
394    /*  Not yet.  TODO  */
395                            if (cpu->machine->emulated_hz > 0) {
396                                    if (cpu->cd.mips.compare_interrupts_pending > 0)
397                                            INTERRUPT_ASSERT(
398                                                cpu->cd.mips.irq_compare);
399                            } else
400    #endif
401                            {
402                                    if (diff1 > 0 && diff2 <= 0)
403                                            INTERRUPT_ASSERT(
404                                                cpu->cd.mips.irq_compare);
405                            }
406                    }
407            }
408    #endif
409  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
410          /*  Update the Decrementer and Time base registers:  */          /*  Update the Decrementer and Time base registers:  */
411          {          {
412                  uint32_t old = cpu->cd.ppc.spr[SPR_DEC];                  uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
413                  cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);                  cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
414                  if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1)                  if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
415                        && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
416                          cpu->cd.ppc.dec_intr_pending = 1;                          cpu->cd.ppc.dec_intr_pending = 1;
   
417                  old = cpu->cd.ppc.spr[SPR_TBL];                  old = cpu->cd.ppc.spr[SPR_TBL];
418                  cpu->cd.ppc.spr[SPR_TBL] += n_instrs;                  cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
419                  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 280  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 421  int DYNTRANS_CPU_RUN_INSTR(struct emul *
421          }          }
422  #endif  #endif
423    
424            cpu->ninstrs += n_instrs;
425    
426            /*
427             *  Check if there are enough samples to decide whether or not to
428             *  perform native code generation:
429             */
430            if (cpu->sampling_curindex == N_PADDR_SAMPLES) {
431                    /*  TODO: Check against known blocks, etc.  */
432    
433                    cpu->sampling_curindex = 0;
434            }
435    
436          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
437          return n_instrs;          return n_instrs;
438  }  }
439  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
440    
441    
442    
# Line 297  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 450  int DYNTRANS_CPU_RUN_INSTR(struct emul *
450   */   */
451  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)
452  {  {
453            int show_symbolic_function_name = 1;
454          char strbuf[50];          char strbuf[50];
455          char *symbol;          char *symbol;
456          uint64_t ot;          uint64_t ot;
457          int x, print_dots = 1, n_args_to_print =          int x, print_dots = 1, n_args_to_print =
458  #ifdef DYNTRANS_ALPHA  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
459              6              6
460  #else  #else
461  #ifdef DYNTRANS_SH  #if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K)
462              8              8   /*  Both for 32-bit and 64-bit SuperH, and M88K  */
463  #else  #else
464              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
465  #endif  #endif
# Line 317  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 471  void DYNTRANS_FUNCTION_TRACE(struct cpu
471                  n_args_to_print = n_args;                  n_args_to_print = n_args;
472          }          }
473    
474    #ifdef DYNTRANS_M88K
475            /*  Special hack for M88K userspace:  */
476            if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
477                    show_symbolic_function_name = 0;
478    #endif
479    
480          /*          /*
481           *  TODO: The type of each argument should be taken from the symbol           *  TODO: The type of each argument should be taken from the symbol
482           *  table, in some way.           *  table, in some way.
# Line 329  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 489  void DYNTRANS_FUNCTION_TRACE(struct cpu
489           *  than were passed in register.           *  than were passed in register.
490           */           */
491          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
492                  int64_t d;                  int64_t d = cpu->cd.DYNTRANS_ARCH.
 #ifdef DYNTRANS_X86  
                 d = 0;          /*  TODO  */  
 #else  
                 /*  Args in registers:  */  
                 d = cpu->cd.DYNTRANS_ARCH.  
493  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
494                      r[ALPHA_A0                      r[ALPHA_A0
495  #endif  #endif
# Line 346  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 501  void DYNTRANS_FUNCTION_TRACE(struct cpu
501                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
502                      r[24                      r[24
503  #endif  #endif
 #ifdef DYNTRANS_HPPA  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_I960  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_IA64  
                     r[0         /*  TODO  */  
 #endif  
 #ifdef DYNTRANS_M68K  
                     d[0         /*  TODO  */  
 #endif  
504  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
505                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
506  #endif  #endif
507  #ifdef DYNTRANS_NEWMIPS  #ifdef DYNTRANS_M88K
508                      r[0         /*  TODO  */                      r[2         /*  r2..r9  */
509  #endif  #endif
510  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
511                      gpr[3                      gpr[3
512  #endif  #endif
513  #ifdef DYNTRANS_SH  #ifdef DYNTRANS_SH
514                      r[2                      r[4         /*  NetBSD seems to use 4? But 2 seems
515                                            to be used by other code? TODO  */
516  #endif  #endif
517  #ifdef DYNTRANS_SPARC  #ifdef DYNTRANS_SPARC
518                      r_i[0                      r[8         /*  o0..o5  */
519  #endif  #endif
520                      + x];                      + x];
521  #endif  
522                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);                  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
523    
524                  if (d > -256 && d < 256)                  if (d > -256 && d < 256)
# Line 382  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 526  void DYNTRANS_FUNCTION_TRACE(struct cpu
526                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))                  else if (memory_points_to_string(cpu, cpu->mem, d, 1))
527                          fatal("\"%s\"", memory_conv_to_string(cpu,                          fatal("\"%s\"", memory_conv_to_string(cpu,
528                              cpu->mem, d, strbuf, sizeof(strbuf)));                              cpu->mem, d, strbuf, sizeof(strbuf)));
529                  else if (symbol != NULL && ot == 0)                  else if (symbol != NULL && ot == 0 &&
530                        show_symbolic_function_name)
531                          fatal("&%s", symbol);                          fatal("&%s", symbol);
532                  else {                  else {
533                          if (cpu->is_32bit)                          if (cpu->is_32bit)
534                                  fatal("0x%x", (int)d);                                  fatal("0x%"PRIx32, (uint32_t)d);
535                          else                          else
536                                  fatal("0x%llx", (long long)d);                                  fatal("0x%"PRIx64, (uint64_t)d);
537                  }                  }
538    
539                  if (x < n_args_to_print - 1)                  if (x < n_args_to_print - 1)
# Line 402  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 547  void DYNTRANS_FUNCTION_TRACE(struct cpu
547    
548    
549    
550    #ifdef DYNTRANS_TIMER_SAMPLE_TICK
551    /*
552     *  XXX_timer_sample_tick():
553     *
554     *  Gathers statistics about which translation blocks are being executed.
555     *  This can then be used to calculate if it is worth the effort to perform
556     *  native code generation (which is assumed to have a large overhead, but
557     *  will result in faster code).
558     */
559    void DYNTRANS_TIMER_SAMPLE_TICK(struct timer *timer, void *extra)
560    {
561            struct cpu *cpu = extra;
562            struct DYNTRANS_IC *next_ic;
563            size_t low_pc;
564            uint64_t paddr;
565    
566            /*
567             *  Don't sample if:
568             *
569             *  1)  Sampling is not enabled. It should only be enabled during
570             *      the core dyntrans loop.
571             *  2)  Enough samples have already been gathered.
572             */
573    
574            if (!cpu->sampling || cpu->sampling_curindex == N_PADDR_SAMPLES)
575                    return;
576    
577            /*  Get the physical address of the program counter:  */
578    
579            next_ic = cpu->cd.DYNTRANS_ARCH.next_ic;
580            low_pc = ((size_t)next_ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)
581                / sizeof(struct DYNTRANS_IC);
582    
583            /*  Not possible to represent as a physical address? Then abort.  */
584            if (low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
585                    return;
586    
587            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
588                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
589            paddr = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
590            paddr &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
591                DYNTRANS_INSTR_ALIGNMENT_SHIFT);
592            paddr += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
593    
594            /*  ... and finally add the sample to the sampling array:  */
595            cpu->sampling_paddr[cpu->sampling_curindex ++] = paddr;
596    }
597    #endif  /*  DYNTRANS_TIMER_SAMPLE_TICK  */
598    
599    
600    
601  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE
 /*  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  
602  /*  /*
603   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
604   *   *
# Line 420  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 609  static void DYNTRANS_TC_ALLOCATE_DEFAULT
609          uint64_t physaddr)          uint64_t physaddr)
610  {  {
611          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
612    
         /*  Create the physpage header:  */  
613          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
614              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
615    
616          /*  TODO: Is this faster than copying an entire template page?  */          /*  Copy the entire template page first:  */
617          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
618                  ppp->ics[i].f =              struct DYNTRANS_TC_PHYSPAGE));
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
619    
620          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);  
621    
622          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
623    
624          cpu->translation_cache_cur_ofs --;          cpu->translation_cache_cur_ofs --;
625          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 127;
626          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
627  }  }
628  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */
# Line 465  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 642  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
642  #else  #else
643          uint64_t          uint64_t
644  #endif  #endif
645              cached_pc, physaddr = 0;              cached_pc = cpu->pc, physaddr = 0;
646          uint32_t physpage_ofs;          uint32_t physpage_ofs;
647          int ok, pagenr, table_index;          int ok, pagenr, table_index;
648          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
649          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
650    
651  #ifdef MODE32  #ifdef MODE32
652          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];  
653  #else  #else
654  #ifdef DYNTRANS_IA64          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
655          fatal("IA64 todo\n");          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
656  #else          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
657          fatal("Neither alpha, ia64, nor 32-bit? 3\n");          uint32_t x1, x2, x3;
658          exit(1);          struct DYNTRANS_L2_64_TABLE *l2;
659  #endif          struct DYNTRANS_L3_64_TABLE *l3;
660  #endif  
661            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
662            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
663            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
664            /*  fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n",
665                (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3);  */
666            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
667            /*  fatal("  l2 = %p\n", l2);  */
668            l3 = l2->l3[x2];
669            /*  fatal("  l3 = %p\n", l3);  */
670  #endif  #endif
671    
672          /*  Virtual to physical address translation:  */          /*  Virtual to physical address translation:  */
# Line 506  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 677  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
677                  ok = 1;                  ok = 1;
678          }          }
679  #else  #else
680  #ifdef DYNTRANS_ALPHA          if (l3->host_load[x3] != NULL) {
681          if (vph_p->host_load[b] != NULL) {                  physaddr = l3->phys_addr[x3];
                 physaddr = vph_p->phys_addr[b];  
682                  ok = 1;                  ok = 1;
683          }          }
 #else  
 #ifdef DYNTRANS_IA64  
         fatal("IA64 todo\n");  
 #else  
         fatal("Neither alpha, ia64, nor 32-bit? 4\n");  
         exit(1);  
 #endif  
 #endif  
684  #endif  #endif
685    
686          if (!ok) {          if (!ok) {
687                  uint64_t paddr;                  uint64_t paddr;
688                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
689                          ok = cpu->translate_address(cpu, cached_pc,                          uint64_t vaddr =
690                              &paddr, FLAG_INSTR);  #if defined(MODE32) && defined(DYNTRANS_MIPS)
691                  else {                          /*  32-bit MIPS is _sign_ extend, not zero.  */
692                                (int32_t)
693    #endif
694                                cached_pc;
695                            ok = cpu->translate_v2p(
696                                cpu, vaddr, &paddr, FLAG_INSTR);
697                    } else {
698                          paddr = cached_pc;                          paddr = cached_pc;
699                          ok = 1;                          ok = 1;
700                  }                  }
701                  if (!ok) {                  if (!ok) {
702                          /*  fatal("TODO: instruction vaddr=>paddr translation"                          /*
703                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                           *  The PC is now set to the exception handler.
704                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */                           *  Try to find the paddr in the translation arrays,
705                             *  or if that fails, call translate_v2p for the
706                             *  exception handler.
707                             */
708                            /*  fatal("TODO: instruction vaddr=>paddr translation "
709                                "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
710                            fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
711    
712                            /*  If there was an exception, the PC has changed.
713                                Update cached_pc:  */
714                            cached_pc = cpu->pc;
715    
716    #ifdef MODE32
717                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
718                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
719                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
720                                    ok = 1;
721                            }
722    #else
723                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
724                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
725                                & mask2;
726                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
727                                - DYNTRANS_L3N)) & mask3;
728                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
729                            l3 = l2->l3[x2];
730                            if (l3->host_load[x3] != NULL) {
731                                    paddr = l3->phys_addr[x3];
732                                    ok = 1;
733                            }
734    #endif
735    
736                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          if (!ok) {
737                              FLAG_INSTR);                                  ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
738                                        FLAG_INSTR);
739                            }
740    
741                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
742                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
743                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */                          fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
744    
745                          if (!ok) {                          if (!ok) {
746                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
# Line 548  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 748  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
748                                  exit(1);                                  exit(1);
749                          }                          }
750                  }                  }
751                  cached_pc = cpu->pc;  
 #ifdef MODE32  
                 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
 #endif  
752                  physaddr = paddr;                  physaddr = paddr;
753          }          }
754    
755            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
756    
757  #ifdef MODE32  #ifdef MODE32
758          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
759    #else
760            if (l3->host_load[x3] == NULL) {
761    #endif
762                    int q = DYNTRANS_PAGESIZE - 1;
763                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
764                      physaddr, MEM_READ);                      physaddr, MEM_READ);
765                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
766                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
767                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr);
768                  }                  }
769          }          }
 #endif  
770    
771          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) {
772                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
773                    fatal("[ dyntrans: resetting the translation cache ]\n");
774    #endif
775                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
776          }          }
777    
# Line 585  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 786  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
786          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
787                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
788                      + physpage_ofs);                      + physpage_ofs);
789    
790                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
791                  if (ppp->physaddr == physaddr)                  if (ppp->physaddr == physaddr)
792                          break;                          break;
793    
794                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
795                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
796          }          }
797    
798          /*  If the offset is 0 (or ppp is NULL), then we need to create a          /*
799              new "default" empty translation page.  */           *  If the offset is 0, then no translation exists yet for this
800             *  physical address. Let's create a new page, and add it first in
801             *  the chain.
802             */
803            if (physpage_ofs == 0) {
804                    uint32_t previous_first_page_in_chain;
805    
806          if (ppp == NULL) {                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
807                  /*  fatal("CREATING page %lli (physaddr 0x%llx), table index "                      "index %i\n", (long long)pagenr, (uint64_t)physaddr,
                     "%i\n", (long long)pagenr, (long long)physaddr,  
808                      (int)table_index);  */                      (int)table_index);  */
809    
810                    previous_first_page_in_chain = *physpage_entryp;
811    
812                    /*  Insert the new page first in the chain:  */
813                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
814                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
815    
# Line 607  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 818  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
818    
819                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
820                      + physpage_ofs);                      + physpage_ofs);
821    
822                    /*  Point to the other pages in the same chain:  */
823                    ppp->next_ofs = previous_first_page_in_chain;
824          }          }
825    
826            /*  Here, ppp points to a valid physical page struct.  */
827    
828  #ifdef MODE32  #ifdef MODE32
829          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
830                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
831    #else
832            if (l3->host_load[x3] != NULL)
833                    l3->phys_page[x3] = ppp;
834  #endif  #endif
835    
836  #ifdef DYNTRANS_ALPHA          /*
837          if (vph_p->host_load[b] != NULL)           *  If there are no translations yet on this page, then mark it
838                  vph_p->phys_page[b] = ppp;           *  as non-writable. If there are already translations, then it
839  #endif           *  should already have been marked as non-writable.
840             */
841  #ifdef MODE32          if (ppp->translations == 0) {
842          /*  Small optimization: only mark the physical page as non-writable                  cpu->invalidate_translation_caches(cpu, physaddr,
843              if it did not contain translations. (Because if it does contain                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
844              translations, it is already non-writable.)  */          }
         if (!cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &  
             (1 << (pagenr & 31)))  
 #endif  
         cpu->invalidate_translation_caches(cpu, physaddr,  
             JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);  
845    
846          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
847    
848          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 +
849              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
850    
851          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
852              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
853              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
854  }  }
855    
856    
# Line 660  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 874  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
874  #else  #else
875          uint64_t          uint64_t
876  #endif  #endif
877              cached_pc;              cached_pc = cpu->pc;
878          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
879    
880  #ifdef MODE32  #ifdef MODE32
881          int index;          int index;
         cached_pc = cpu->pc;  
882          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);          index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
883          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];          ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
884          if (ppp != NULL)          if (ppp != NULL)
885                  goto have_it;                  goto have_it;
886  #else  #else
887  #ifdef DYNTRANS_ALPHA          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
888          uint32_t a, b;          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
889          int kernel = 0;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
890          struct alpha_vph_page *vph_p;          uint32_t x1, x2, x3;
891          cached_pc = cpu->pc;          struct DYNTRANS_L2_64_TABLE *l2;
892          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          struct DYNTRANS_L3_64_TABLE *l3;
893          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);  
894          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
895                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
896                  kernel = 1;          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
897          } else          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
898                  vph_p = cpu->cd.alpha.vph_table0[a];          l3 = l2->l3[x2];
899          if (vph_p != cpu->cd.alpha.vph_default_page) {          ppp = l3->phys_page[x3];
900                  ppp = vph_p->phys_page[b];          if (ppp != NULL)
901                  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  
902  #endif  #endif
903    
904          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
905          return;          return;
906    
907          /*  Quick return path:  */          /*  Quick return path:  */
 #if defined(MODE32) || defined(DYNTRANS_ALPHA)  
908  have_it:  have_it:
909          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
910          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 +
911              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
912    
913          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
914              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
915              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
 #endif  
916  }  }
917  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
918    
919    
920    
921    #ifdef DYNTRANS_INIT_TABLES
922    
923    /*  forward declaration of to_be_translated and end_of_page:  */
924    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
925    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
926    #ifdef DYNTRANS_DUALMODE_32
927    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
928    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
929    #endif
930    
931    #ifdef DYNTRANS_DELAYSLOT
932    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
933    #ifdef DYNTRANS_DUALMODE_32
934    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
935    #endif
936    #endif
937    
938    /*
939     *  XXX_init_tables():
940     *
941     *  Initializes the default translation page (for newly allocated pages), and
942     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
943     */
944    void DYNTRANS_INIT_TABLES(struct cpu *cpu)
945    {
946    #ifndef MODE32
947            struct DYNTRANS_L2_64_TABLE *dummy_l2;
948            struct DYNTRANS_L3_64_TABLE *dummy_l3;
949            int x1, x2;
950    #endif
951            int i;
952            struct DYNTRANS_TC_PHYSPAGE *ppp;
953    
954            CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
955    
956            ppp->next_ofs = 0;
957            ppp->translations = 0;
958            /*  ppp->physaddr is filled in by the page allocator  */
959    
960            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++) {
961                    ppp->ics[i].f =
962    #ifdef DYNTRANS_DUALMODE_32
963                        cpu->is_32bit? instr32(to_be_translated) :
964    #endif
965                        instr(to_be_translated);
966            }
967    
968            /*  End-of-page:  */
969            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
970    #ifdef DYNTRANS_DUALMODE_32
971                cpu->is_32bit? instr32(end_of_page) :
972    #endif
973                instr(end_of_page);
974    
975            /*  End-of-page-2, for delay-slot architectures:  */
976    #ifdef DYNTRANS_DELAYSLOT
977            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
978    #ifdef DYNTRANS_DUALMODE_32
979                cpu->is_32bit? instr32(end_of_page2) :
980    #endif
981                instr(end_of_page2);
982    #endif
983    
984            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
985    
986    
987            /*  Prepare 64-bit virtual address translation tables:  */
988    #ifndef MODE32
989            if (cpu->is_32bit)
990                    return;
991    
992            dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
993            dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
994    
995            cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
996            cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
997    
998            for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
999                    cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
1000    
1001            for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
1002                    dummy_l2->l3[x2] = dummy_l3;
1003    #endif
1004    }
1005    #endif  /*  DYNTRANS_INIT_TABLES  */
1006    
1007    
1008    
1009  #ifdef DYNTRANS_INVAL_ENTRY  #ifdef DYNTRANS_INVAL_ENTRY
1010  /*  /*
1011   *  XXX_invalidate_tlb_entry():   *  XXX_invalidate_tlb_entry():
# Line 750  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1036  static void DYNTRANS_INVALIDATE_TLB_ENTR
1036                      (int)vaddr_page);  */                      (int)vaddr_page);  */
1037                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1038          } else {          } else {
1039                    int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
1040                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
1041                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1042                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
1043                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1044                    if (tlbi > 0)
1045                            cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1046                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1047          }          }
1048  #else  #else
1049          /*  2-level:  */          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1050  #ifdef DYNTRANS_ALPHA          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1051          struct alpha_vph_page *vph_p;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1052          uint32_t a, b;          uint32_t x1, x2, x3;
1053          int kernel = 0;          struct DYNTRANS_L2_64_TABLE *l2;
1054            struct DYNTRANS_L3_64_TABLE *l3;
1055          a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
1056          b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1057          if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1058                  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];  
1059    
1060          if (vph_p == cpu->cd.alpha.vph_default_page) {          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1061                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n");          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1062                  exit(1);                  return;
1063          }  
1064            l3 = l2->l3[x2];
1065            if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1066                    return;
1067    
1068          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
1069                  vph_p->host_store[b] = NULL;                  l3->host_store[x3] = NULL;
1070                  return;                  return;
1071          }          }
1072          vph_p->host_load[b] = NULL;  
1073          vph_p->host_store[b] = NULL;  #ifdef BUGHUNT
1074          vph_p->phys_addr[b] = 0;  
1075          vph_p->phys_page[b] = NULL;  {
1076          vph_p->refcount --;          /*  Consistency check, for debugging:  */
1077          if (vph_p->refcount < 0) {          int x1, x1b; // x2, x3;
1078                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n");          struct DYNTRANS_L2_64_TABLE *l2;
1079            //struct DYNTRANS_L3_64_TABLE *l3;
1080    
1081            for (x1 = 0; x1 <= mask1; x1 ++) {
1082                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1083                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1084                            continue;
1085                    /*  Make sure that this l2 isn't used more than 1 time!  */
1086                    for (x1b = 0; x1b <= mask1; x1b ++)
1087                            if (x1 != x1b &&
1088                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1089                                    fatal("L2 reuse: %p\n", l2);
1090                                    exit(1);
1091                            }
1092            }
1093    }
1094    
1095    /*  Count how many pages are actually in use:  */
1096    {
1097            int n=0, i;
1098            for (i=0; i<=mask3; i++)
1099                    if (l3->vaddr_to_tlbindex[i])
1100                            n++;
1101            if (n != l3->refcount) {
1102                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1103                  exit(1);                  exit(1);
1104          }          }
1105          if (vph_p->refcount == 0) {  
1106                  vph_p->next = cpu->cd.alpha.vph_next_free_page;          n = 0;
1107                  cpu->cd.alpha.vph_next_free_page = vph_p;          for (i=0; i<=mask3; i++)
1108                  if (kernel)                  if (l3->host_load[i] != NULL)
1109                          cpu->cd.alpha.vph_table0_kernel[a] =                          n++;
1110                              cpu->cd.alpha.vph_default_page;          if (n != l3->refcount) {
1111                  else                  printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1112                          cpu->cd.alpha.vph_table0[a] =                  exit(1);
1113                              cpu->cd.alpha.vph_default_page;          }
1114    }
1115    #endif
1116    
1117            l3->host_load[x3] = NULL;
1118            l3->host_store[x3] = NULL;
1119            l3->phys_addr[x3] = 0;
1120            l3->phys_page[x3] = NULL;
1121            if (l3->vaddr_to_tlbindex[x3] != 0) {
1122                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1123                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1124                    l3->refcount --;
1125            }
1126            l3->vaddr_to_tlbindex[x3] = 0;
1127    
1128            if (l3->refcount < 0) {
1129                    fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1130                    exit(1);
1131            }
1132    
1133            if (l3->refcount == 0) {
1134                    l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1135                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1136                    l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1137    
1138    #ifdef BUGHUNT
1139    /*  Make sure that we're placing a CLEAN page on the
1140        freelist:  */
1141    {
1142            int i;
1143            for (i=0; i<=mask3; i++)
1144                    if (l3->host_load[i] != NULL) {
1145                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1146                            exit(1);
1147                    }
1148    }
1149    #endif
1150                    l2->refcount --;
1151                    if (l2->refcount < 0) {
1152                            fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1153                            exit(1);
1154                    }
1155                    if (l2->refcount == 0) {
1156                            l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1157                            cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1158                            cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1159                                cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1160                    }
1161          }          }
 #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  */  
1162  #endif  #endif
1163  }  }
1164  #endif  #endif
# Line 821  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1174  static void DYNTRANS_INVALIDATE_TLB_ENTR
1174   *  flags should be one of   *  flags should be one of
1175   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL   *      INVALIDATE_PADDR  INVALIDATE_VADDR  or  INVALIDATE_ALL
1176   *   *
1177     *  In addition, for INVALIDATE_ALL, INVALIDATE_VADDR_UPPER4 may be set and
1178     *  bit 31..28 of addr are used to select the virtual addresses to invalidate.
1179     *  (This is useful for PowerPC emulation, when segment registers are updated.)
1180     *
1181   *  In the case when all translations are invalidated, paddr doesn't need   *  In the case when all translations are invalidated, paddr doesn't need
1182   *  to be supplied.   *  to be supplied.
1183   *   *
# Line 828  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 1185  static void DYNTRANS_INVALIDATE_TLB_ENTR
1185   *             the quick translation array, not from the linear   *             the quick translation array, not from the linear
1186   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.   *             vph_tlb_entry[] array.  Hopefully this is enough anyway.
1187   */   */
1188  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t paddr, int flags)  void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
1189  {  {
1190          int r;          int r;
1191  #ifdef MODE32  #ifdef MODE32
# Line 836  void DYNTRANS_INVALIDATE_TC(struct cpu * Line 1193  void DYNTRANS_INVALIDATE_TC(struct cpu *
1193  #else  #else
1194          uint64_t          uint64_t
1195  #endif  #endif
1196              addr_page = paddr & ~(DYNTRANS_PAGESIZE - 1);              addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
1197    
1198          /*  fatal("invalidate(): ");  */          /*  fatal("invalidate(): ");  */
1199    
1200          /*  Quick case for virtual addresses: see note above.  */          /*  Quick case for _one_ virtual addresses: see note above.  */
1201          if (flags & INVALIDATE_VADDR) {          if (flags & INVALIDATE_VADDR) {
1202                  /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */                  /*  fatal("vaddr 0x%08x\n", (int)addr_page);  */
1203                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);                  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
1204                  return;                  return;
1205          }          }
1206    
1207            /*  Invalidate everything:  */
1208    #ifdef DYNTRANS_PPC
1209            if (flags & INVALIDATE_ALL && flags & INVALIDATE_VADDR_UPPER4) {
1210                    /*  fatal("all, upper4 (PowerPC segment)\n");  */
1211                    for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1212                            if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
1213                                (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page
1214                                & 0xf0000000) == addr_page) {
1215                                    DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, cpu->cd.
1216                                        DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1217                                        0);
1218                                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1219                            }
1220                    }
1221                    return;
1222            }
1223    #endif
1224          if (flags & INVALIDATE_ALL) {          if (flags & INVALIDATE_ALL) {
1225                  /*  fatal("all\n");  */                  /*  fatal("all\n");  */
1226                  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 1234  void DYNTRANS_INVALIDATE_TC(struct cpu *
1234                  return;                  return;
1235          }          }
1236    
1237          /*  fatal("paddr 0x%08x\n", (int)addr_page);  */          /*  Invalidate a physical page:  */
1238    
1239            if (!(flags & INVALIDATE_PADDR))
1240                    fatal("HUH? Invalidate: Not vaddr, all, or paddr?\n");
1241    
1242            /*  fatal("addr 0x%08x\n", (int)addr_page);  */
1243    
1244          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {          for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1245                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && (                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
1246                      (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) ) {  
1247                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
1248                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,                              cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1249                              flags);                              flags);
# Line 911  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1288  void DYNTRANS_INVALIDATE_TC_CODE(struct
1288                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1289    
1290                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);                  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
   
 #ifdef MODE32  
                 /*  If this page isn't marked as having any translations,  
                     then return immediately.  */  
                 if (!(cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5]  
                     & 1 << (pagenr & 31)))  
                         return;  
                 /*  Remove the mark:  */  
                 cpu->cd.DYNTRANS_ARCH.phystranslation[pagenr >> 5] &=  
                     ~ (1 << (pagenr & 31));  
 #endif  
   
1291                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1292    
1293                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
1294                      translation_cache)[table_index]);                      translation_cache)[table_index]);
1295                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
1296    
1297                    /*  Return immediately if there is no code translation
1298                        for this page.  */
1299                    if (physpage_ofs == 0)
1300                            return;
1301    
1302                  prev_ppp = ppp = NULL;                  prev_ppp = ppp = NULL;
1303    
1304                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
# Line 935  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1306  void DYNTRANS_INVALIDATE_TC_CODE(struct
1306                          prev_ppp = ppp;                          prev_ppp = ppp;
1307                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1308                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1309    
1310                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1311                              then we're done:  */                              then we're done:  */
1312                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1313                                  break;                                  break;
1314    
1315                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1316                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1317                  }                  }
1318    
1319                    /*  If there is no translation, there is no need to go
1320                        on and try to remove it from the vph_tlb_entry array:  */
1321                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1322                          ppp = NULL;                          return;
1323    
1324  #if 1  #if 0
1325                  /*                  /*
1326                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1327                   *                   *
# Line 968  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1343  void DYNTRANS_INVALIDATE_TC_CODE(struct
1343                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1344                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1345                   */                   */
1346                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations != 0) {
1347                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations; /*  TODO:
1348                              template page?  */                                  urk Should be same type as ppp->translations */
1349                          int i;                          int i, j, n, m;
1350                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1351                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1352    
1353                            for (i=0; i<n; i++) {
1354                                    if (x & 1) {
1355                                            for (j=0; j<m; j++)
1356                                                    ppp->ics[i*m + j].f =
1357  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
1358                                      cpu->is_32bit? instr32(to_be_translated) :                                                      cpu->is_32bit?
1359                                                        instr32(to_be_translated) :
1360  #endif  #endif
1361                                      instr(to_be_translated);                                                      instr(to_be_translated);
1362                                    }
1363    
1364                                    x >>= 1;
1365                            }
1366    
1367                            ppp->translations = 0;
1368                  }                  }
1369  #endif  #endif
1370          }          }
1371    
1372          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1373          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 ++) {  
1374                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1375                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1376                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 998  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1384  void DYNTRANS_INVALIDATE_TC_CODE(struct
1384                                  uint32_t index =                                  uint32_t index =
1385                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1386                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
                                 /*  Remove the mark:  */  
                                 index = DYNTRANS_ADDR_TO_PAGENR(paddr_page);  
                                 cpu->cd.DYNTRANS_ARCH.phystranslation[  
                                     index >> 5] &= ~ (1 << (index & 31));  
1387  #else  #else
1388                                  /*  2-level:  */                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1389  #ifdef DYNTRANS_ALPHA                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1390                                  struct alpha_vph_page *vph_p;                                  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1391                                  uint32_t a, b;                                  uint32_t x1, x2, x3;
1392                                  int kernel = 0;                                  struct DYNTRANS_L2_64_TABLE *l2;
1393                                    struct DYNTRANS_L3_64_TABLE *l3;
1394                                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT)  
1395                                      & (ALPHA_LEVEL0 - 1);                                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1396                                  b = (vaddr_page >> ALPHA_LEVEL1_SHIFT)                                  x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1397                                      & (ALPHA_LEVEL1 - 1);                                      DYNTRANS_L2N)) & mask2;
1398                                  if ((vaddr_page >> ALPHA_TOPSHIFT) ==                                  x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1399                                      ALPHA_TOP_KERNEL) {                                      DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1400                                          vph_p = cpu->cd.alpha.                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1401                                              vph_table0_kernel[a];                                  l3 = l2->l3[x2];
1402                                          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  */  
1403  #endif  #endif
1404                          }                          }
1405                  }                  }
# Line 1047  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1418  void DYNTRANS_INVALIDATE_TC_CODE(struct
1418  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1419          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1420  {  {
1421  #ifndef MODE32          int found, r, useraccess = 0;
         int64_t lowest, highest = -1;  
 #endif  
         int found, r, lowest_index, start, end, useraccess = 0;  
1422    
 #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  
1423  #ifdef MODE32  #ifdef MODE32
1424          uint32_t index;          uint32_t index;
1425          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
1426          paddr_page &= 0xffffffffULL;  
1427            if (paddr_page > 0xffffffffULL) {
1428                    fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1429                        " p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag,
1430                        paddr_page);
1431                    exit(1);
1432            }
1433    
1434          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1435              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1436              (int)paddr_page);  */              (int)paddr_page);  */
1437  #else   /*  !MODE32  */  #else   /*  !MODE32  */
1438  #ifdef DYNTRANS_IA64          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1439          fatal("IA64 update todo\n");          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1440  #else          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1441          fatal("Neither 32-bit, IA64, nor Alpha? 2\n");          uint32_t x1, x2, x3;
1442          exit(1);          struct DYNTRANS_L2_64_TABLE *l2;
1443  #endif          struct DYNTRANS_L3_64_TABLE *l3;
1444  #endif  
1445            /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1446                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1447                (uint64_t)paddr_page);  */
1448  #endif  #endif
1449    
1450            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1451            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1452    
1453          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1454                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1455                  useraccess = 1;                  useraccess = 1;
1456          }          }
1457    
1458          start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  #ifdef DYNTRANS_M88K
1459  #if 1          /*  TODO  */
1460          /*  Half of the TLB used for data, half for code:  */          if (useraccess)
1461          if (writeflag & TLB_CODE) {                  return;
                 writeflag &= ~TLB_CODE;  
                 start = end; end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
         }  
 #else  
         /*  Data and code entries are mixed.  */  
         end = DYNTRANS_MAX_VPH_TLB_ENTRIES;  
1462  #endif  #endif
1463    
1464          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
         lowest_index = start;  
1465    
1466  #ifdef MODE32  #ifdef MODE32
1467          /*          /*
# Line 1108  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1474  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1474           */           */
1475          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1476              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;              DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
         if (found < 0) {  
                 static unsigned int x = 0;  
                 lowest_index = (x % (end-start)) + start;  
                 x ++;  
         }  
1477  #else  #else
1478          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1479          found = -1;          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1480          for (r=start; r<end; r++) {          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1481                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {              & mask3;
1482                          lowest = cpu->cd.DYNTRANS_ARCH.  
1483                              vph_tlb_entry[r].timestamp;          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1484                          lowest_index = r;          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1485                  }                  found = -1;
1486                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)          else {
1487                          highest = cpu->cd.DYNTRANS_ARCH.                  l3 = l2->l3[x2];
1488                              vph_tlb_entry[r].timestamp;                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1489                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&                          found = -1;
1490                      cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==                  else
1491                      vaddr_page) {                          found = (int)l3->vaddr_to_tlbindex[x3] - 1;
                         found = r;  
                         break;  
                 }  
1492          }          }
1493  #endif  #endif
1494    
1495          if (found < 0) {          if (found < 0) {
1496                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting a "random" entry:  */
1497                  r = lowest_index;                  static unsigned int x = 0;
1498                    r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1499    
1500                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1501                          /*  This one has to be invalidated first:  */                          /*  This one has to be invalidated first:  */
1502                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
# Line 1150  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1510  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1510                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1511                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1512                      writeflag & MEM_WRITE;                      writeflag & MEM_WRITE;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1513    
1514                  /*  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  
1515  #ifdef MODE32  #ifdef MODE32
1516                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1517                  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 1525  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1525                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1526                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1527  #endif  #endif
1528  #endif  /*  32  */  #else   /* !MODE32  */
1529  #endif  /*  !ALPHA  */                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1530                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1531                            if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1532                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1533                                        cpu->cd.DYNTRANS_ARCH.next_free_l2;
1534                                    cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1535                            } else {
1536                                    int i;
1537                                    CHECK_ALLOCATION(l2 =
1538                                        cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(
1539                                        sizeof(struct DYNTRANS_L2_64_TABLE)));
1540                                    l2->refcount = 0;
1541                                    for (i=0; i<(1 << DYNTRANS_L2N); i++)
1542                                            l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1543                                                l3_64_dummy;
1544                            }
1545                            if (l2->refcount != 0) {
1546                                    fatal("Huh? l2 Refcount problem.\n");
1547                                    exit(1);
1548                            }
1549                    }
1550                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1551                            fatal("INTERNAL ERROR L2 reuse\n");
1552                            exit(1);
1553                    }
1554                    l3 = l2->l3[x2];
1555                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1556                            if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1557                                    l3 = l2->l3[x2] =
1558                                        cpu->cd.DYNTRANS_ARCH.next_free_l3;
1559                                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1560                            } else {
1561                                    l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1562                                        struct DYNTRANS_L3_64_TABLE));
1563                            }
1564                            if (l3->refcount != 0) {
1565                                    fatal("Huh? l3 Refcount problem.\n");
1566                                    exit(1);
1567                            }
1568                            l2->refcount ++;
1569                    }
1570                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1571                            fatal("INTERNAL ERROR L3 reuse\n");
1572                            exit(1);
1573                    }
1574    
1575                    l3->host_load[x3] = host_page;
1576                    l3->host_store[x3] = writeflag? host_page : NULL;
1577                    l3->phys_addr[x3] = paddr_page;
1578                    l3->phys_page[x3] = NULL;
1579                    l3->vaddr_to_tlbindex[x3] = r + 1;
1580                    l3->refcount ++;
1581    
1582    #ifdef BUGHUNT
1583    /*  Count how many pages are actually in use:  */
1584    {
1585            int n=0, i;
1586            for (i=0; i<=mask3; i++)
1587                    if (l3->vaddr_to_tlbindex[i])
1588                            n++;
1589            if (n != l3->refcount) {
1590                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1591                    exit(1);
1592            }
1593    
1594            n = 0;
1595            for (i=0; i<=mask3; i++)
1596                    if (l3->host_load[i] != NULL)
1597                            n++;
1598            if (n != l3->refcount) {
1599                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1600                    exit(1);
1601            }
1602    }
1603    #endif
1604    
1605    #endif  /* !MODE32  */
1606          } else {          } else {
1607                  /*                  /*
1608                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
# Line 1214  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1611  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1611                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1612                   */                   */
1613                  r = found;                  r = found;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1614                  if (writeflag & MEM_WRITE)                  if (writeflag & MEM_WRITE)
1615                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1616                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
1617                          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  
1618  #ifdef MODE32  #ifdef MODE32
1619                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1620                  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 1637  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1637                              writeflag? host_page : NULL;                              writeflag? host_page : NULL;
1638                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1639                  }                  }
1640  #endif  /*  32  */  #else   /*  !MODE32  */
1641  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1642                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1643                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1644                        & mask3;
1645                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1646                    l3 = l2->l3[x2];
1647                    if (l3->phys_addr[x3] == paddr_page) {
1648                            if (writeflag & MEM_WRITE)
1649                                    l3->host_store[x3] = host_page;
1650                            if (writeflag & MEM_DOWNGRADE)
1651                                    l3->host_store[x3] = NULL;
1652                    } else {
1653                            /*  Change the entire physical/host mapping:  */
1654    printf("HOST LOAD 2 set to %p\n", host_page);
1655                            l3->host_load[x3] = host_page;
1656                            l3->host_store[x3] = writeflag? host_page : NULL;
1657                            l3->phys_addr[x3] = paddr_page;
1658                    }
1659    
1660    #ifdef BUGHUNT
1661    /*  Count how many pages are actually in use:  */
1662    {
1663            int n=0, i;
1664            for (i=0; i<=mask3; i++)
1665                    if (l3->vaddr_to_tlbindex[i])
1666                            n++;
1667            if (n != l3->refcount) {
1668                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1669                    exit(1);
1670            }
1671    
1672            n = 0;
1673            for (i=0; i<=mask3; i++)
1674                    if (l3->host_load[i] != NULL)
1675                            n++;
1676            if (n != l3->refcount) {
1677                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1678                    printf("Entry r = %i\n", r);
1679                    printf("Valid = %i\n",
1680    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1681                    exit(1);
1682            }
1683    }
1684    #endif
1685    
1686    #endif  /*  !MODE32  */
1687          }          }
1688  }  }
1689  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */
# Line 1278  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1696  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1696          /*          /*
1697           *  Check for breakpoints.           *  Check for breakpoints.
1698           */           */
1699          if (!single_step_breakpoint) {          if (!single_step_breakpoint && !cpu->translation_readahead) {
1700  #ifdef MODE32                  MODE_uint_t curpc = cpu->pc;
                 uint32_t curpc = cpu->pc;  
 #else  
                 uint64_t curpc = cpu->pc;  
 #endif  
1701                  int i;                  int i;
1702                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->breakpoints.n; i++)
1703                          if (curpc ==                          if (curpc == (MODE_uint_t)
1704  #ifdef MODE32                              cpu->machine->breakpoints.addr[i]) {
                             (uint32_t)  
 #endif  
                             cpu->machine->breakpoint_addr[i]) {  
1705                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1706                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1707                                          quiet_mode = 0;                                          quiet_mode = 0;
1708                                          DISASSEMBLE(cpu, ib, 1, 0, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1709                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1710                                  }                                  }
1711                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "  #ifdef MODE32
1712                                    fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The "
1713                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1714                                      (long long)cpu->pc);                                      (uint32_t)cpu->pc);
1715    #else
1716                                    fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1717                                        "instruction has not yet executed.)\n",
1718                                        (uint64_t)cpu->pc);
1719    #endif
1720    #ifdef DYNTRANS_DELAYSLOT
1721                                    if (cpu->delay_slot != NOT_DELAYED)
1722                                            fatal("ERROR! Breakpoint in a delay"
1723                                                " slot! Not yet supported.\n");
1724    #endif
1725                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1726                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1727                                  goto stop_running_translated;                                  goto stop_running_translated;
1728                          }                          }
1729          }          }
# Line 1313  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1735  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1735    
1736  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1737          /*          /*
1738           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1739           *  Mark the page as containing a translation.           *  the page as containing a translation at this part of the page.
          *  
          *  (Special case for 32-bit mode: set the corresponding bit in the  
          *  phystranslation[] array.)  
1740           */           */
 #ifdef MODE32  
         if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {  
                 uint32_t index = DYNTRANS_ADDR_TO_PAGENR(addr);  
                 cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=  
                     (1 << (index & 31));  
         }  
 #endif  
         cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;  
1741    
1742            /*  Make sure cur_physpage is in synch:  */
1743            cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1744                cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1745    
1746            {
1747                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1748                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1749                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->translations));
1750                    x /= addr_per_translation_range;
1751    
1752                    cpu->cd.DYNTRANS_ARCH.cur_physpage->translations |= (1 << x);
1753            }
1754    
1755          /*          /*
1756           *  Now it is time to check for combinations of instructions that can           *  Now it is time to check for combinations of instructions that can
1757           *  be converted into a single function call.           *  be converted into a single function call.
1758           *           *
1759           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: Single-stepping or instruction tracing doesn't work with
1760           *  instruction combination.           *  instruction combinations. For architectures with delay slots,
1761             *  we also ignore combinations if the delay slot is across a page
1762             *  boundary.
1763           */           */
1764          if (!single_step && !cpu->machine->instruction_trace) {          if (!single_step && !cpu->machine->instruction_trace
1765                  if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&  #ifdef DYNTRANS_DELAYSLOT
1766                      cpu->machine->speed_tricks)              && !in_crosspage_delayslot
1767                          cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,  #endif
1768                              addr & (DYNTRANS_PAGESIZE - 1));              && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1769                  cpu->cd.DYNTRANS_ARCH.combination_check = NULL;              && cpu->machine->allow_instruction_combinations) {
1770                    cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1771                        addr & (DYNTRANS_PAGESIZE - 1));
1772            }
1773    
1774            cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1775    
1776            /*  An additional check, to catch some bugs:  */
1777            if (ic->f == (
1778    #ifdef DYNTRANS_DUALMODE_32
1779                cpu->is_32bit? instr32(to_be_translated) :
1780    #endif
1781                instr(to_be_translated))) {
1782                    fatal("INTERNAL ERROR: ic->f not set!\n");
1783                    goto bad;
1784            }
1785            if (ic->f == NULL) {
1786                    fatal("INTERNAL ERROR: ic->f == NULL!\n");
1787                    goto bad;
1788          }          }
1789    
1790          /*  ... and finally execute the translated instruction:  */          /*  ... and finally execute the translated instruction:  */
1791          if (single_step_breakpoint) {  
1792                  /*          /*  (Except when doing read-ahead!)  */
1793                   *  Special case when single-stepping: Execute the translated          if (cpu->translation_readahead)
1794                   *  instruction, but then replace it with a "to be translated"                  return;
1795                   *  directly afterwards.  
1796                   */          /*
1797             *  Special case when single-stepping: Execute the translated
1798             *  instruction, but then replace it with a "to be translated"
1799             *  directly afterwards.
1800             */
1801            if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1802    #ifdef DYNTRANS_DELAYSLOT
1803                || in_crosspage_delayslot
1804    #endif
1805                ) {
1806                  single_step_breakpoint = 0;                  single_step_breakpoint = 0;
1807                  ic->f(cpu, ic);                  ic->f(cpu, ic);
1808                  ic->f =                  ic->f =
# Line 1358  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1810  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1810                      cpu->is_32bit? instr32(to_be_translated) :                      cpu->is_32bit? instr32(to_be_translated) :
1811  #endif  #endif
1812                      instr(to_be_translated);                      instr(to_be_translated);
1813          } else  
1814                  ic->f(cpu, ic);                  return;
1815            }
1816    
1817            /*  Translation read-ahead:  */
1818            if (!single_step && !cpu->machine->instruction_trace) {
1819                    /*  Do readahead:  */
1820                    int i = 1;
1821                    uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(cpu->pc);
1822                    uint64_t baseaddr = cpu->pc;
1823    
1824                    cpu->translation_readahead = MAX_DYNTRANS_READAHEAD;
1825    
1826                    while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1827                        (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1828                        cpu->translation_readahead > 0) {
1829                            void (*old_f)(struct cpu *,
1830                                struct DYNTRANS_IC *) = ic[i].f;
1831    
1832                            /*  Already translated? Then abort:  */
1833                            if (old_f != (
1834    #ifdef DYNTRANS_DUALMODE_32
1835                                cpu->is_32bit? instr32(to_be_translated) :
1836    #endif
1837                                instr(to_be_translated)))
1838                                    break;
1839    
1840                            /*  Translate the instruction:  */
1841                            ic[i].f(cpu, ic+i);
1842    
1843                            /*  Translation failed? Then abort.  */
1844                            if (ic[i].f == old_f)
1845                                    break;
1846    
1847                            cpu->translation_readahead --;
1848                            ++i;
1849                    }
1850    
1851                    cpu->translation_readahead = 0;
1852            }
1853    
1854    
1855            /*
1856             *  Finally finally :-), execute the instruction.
1857             *
1858             *  Note: The instruction might have changed during read-ahead, if
1859             *  instruction combinations are used.
1860             */
1861    
1862            ic->f(cpu, ic);
1863    
1864          return;          return;
1865    
# Line 1368  bad:   /* Line 1868  bad:   /*
1868           *  Nothing was translated. (Unimplemented or illegal instruction.)           *  Nothing was translated. (Unimplemented or illegal instruction.)
1869           */           */
1870    
1871            /*  Clear the translation, in case it was "half-way" done:  */
1872            ic->f =
1873    #ifdef DYNTRANS_DUALMODE_32
1874                cpu->is_32bit? instr32(to_be_translated) :
1875    #endif
1876                instr(to_be_translated);
1877    
1878            if (cpu->translation_readahead)
1879                    return;
1880    
1881          quiet_mode = 0;          quiet_mode = 0;
1882          fatal("to_be_translated(): TODO: unimplemented instruction");          fatal("to_be_translated(): TODO: unimplemented instruction");
1883    
1884          if (cpu->machine->instruction_trace)          if (cpu->machine->instruction_trace)
1885  #ifdef MODE32  #ifdef MODE32
1886                  fatal(" at 0x%x\n", (int)cpu->pc);                  fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1887  #else  #else
1888                  fatal(" at 0x%llx\n", (long long)cpu->pc);                  fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1889  #endif  #endif
1890          else {          else {
1891                  fatal(":\n");                  fatal(":\n");
1892                  DISASSEMBLE(cpu, ib, 1, 0, 0);                  DISASSEMBLE(cpu, ib, 1, 0);
1893          }          }
1894    
1895          cpu->running = 0;          cpu->running = 0;
1896          cpu->dead = 1;  
1897            /*  Note: Single-stepping can jump here.  */
1898  stop_running_translated:  stop_running_translated:
1899    
1900          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1901          cpu->running_translated = 0;  
1902          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1903          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1904    
1905    #ifdef DYNTRANS_DELAYSLOT
1906            /*  Special hack: If the bad instruction was in a delay slot,
1907                make sure that execution does not continue anyway:  */
1908            if (cpu->delay_slot)
1909                    cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT;
1910    #endif
1911    
1912          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1913          ic->f(cpu, ic);          ic->f(cpu, ic);
1914    
1915  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */
1916    

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

  ViewVC Help
Powered by ViewVC 1.1.26