/[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 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 44 by dpavlin, Mon Oct 8 16:22:56 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005-2006  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.54 2006/02/09 22:55:20 debug Exp $   *  $Id: cpu_dyntrans.c,v 1.186 2007/07/20 09:03:33 debug Exp $
29   *   *
30   *  Common dyntrans routines. Included from cpu_*.c.   *  Common dyntrans routines. Included from cpu_*.c.
31     *
32     *  Note: This might be a bit hard to follow, if you are reading this source
33     *  code for the first time. It is basically a hack to implement "templates"
34     *  with normal C code, by using suitable defines/macros, and then including
35     *  this file.
36   */   */
37    
38    
39  #ifdef  DYNTRANS_CPU_RUN_INSTR  #ifndef STATIC_STUFF
40  #if 1   /*  IC statistics:  */  #define STATIC_STUFF
41    /*
42     *  gather_statistics():
43     */
44  static void gather_statistics(struct cpu *cpu)  static void gather_statistics(struct cpu *cpu)
45  {  {
46            char ch, buf[60];
47          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;          struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
48          static long long n = 0;          int i = 0;
         static FILE *f = NULL;  
   
         n++;  
         if (n < 100000000)  
                 return;  
   
         if (f == NULL) {  
                 f = fopen("instruction_call_statistics.raw", "w");  
                 if (f == NULL) {  
                         fatal("Unable to open statistics file for output.\n");  
                         exit(1);  
                 }  
         }  
         fwrite(&ic->f, 1, sizeof(void *), f);  
 }  
 #else   /*  PC statistics:  */  
 static void gather_statistics(struct cpu *cpu)  
 {  
49          uint64_t a;          uint64_t a;
50          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)
51              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);              cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
52          if (low_pc < 0 || low_pc >= DYNTRANS_IC_ENTRIES_PER_PAGE)  
53            if (cpu->machine->statistics.file == NULL) {
54                    fatal("statistics gathering with no filename set is"
55                        " meaningless\n");
56                  return;                  return;
57            }
58    
59  #if 0          /*  low_pc must be within the page!  */
60          /*  Use the physical address:  */          if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
61          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  
62    
63          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<          buf[0] = '\0';
             DYNTRANS_INSTR_ALIGNMENT_SHIFT);  
         a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;  
64    
65          /*          while ((ch = cpu->machine->statistics.fields[i]) != '\0') {
66           *  TODO: Everything below this line should be cleaned up :-)                  if (i != 0)
67           */                          strlcat(buf, " ", sizeof(buf));
68  a &= 0x03ffffff;  
69  {                  switch (ch) {
70          static long long *array = NULL;                  case 'i':
71          static char *array_16kpage_in_use = NULL;                          snprintf(buf + strlen(buf), sizeof(buf),
72          static int n = 0;                              "%p", (void *)ic->f);
73          a >>= DYNTRANS_INSTR_ALIGNMENT_SHIFT;                          break;
74          if (array == NULL)                  case 'p':
75                  array = zeroed_alloc(sizeof(long long) * 16384*1024);                          /*  Physical program counter address:  */
76          if (array_16kpage_in_use == NULL)                          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
77                  array_16kpage_in_use = zeroed_alloc(sizeof(char) * 1024);                              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
78          a &= (16384*1024-1);                          a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
79          array[a] ++;                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
80          array_16kpage_in_use[a / 16384] = 1;                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
81          n++;                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
82          if ((n & 0x3fffffff) == 0) {                          if (cpu->is_32bit)
83                  FILE *f = fopen("statistics.out", "w");                                  snprintf(buf + strlen(buf), sizeof(buf),
84                  int i, j;                                      "0x%08"PRIx32, (uint32_t)a);
85                  printf("Saving statistics... "); fflush(stdout);                          else
86                  for (i=0; i<1024; i++)                                  snprintf(buf + strlen(buf), sizeof(buf),
87                          if (array_16kpage_in_use[i]) {                                      "0x%016"PRIx64, (uint64_t)a);
88                                  for (j=0; j<16384; j++)                          break;
89                                          if (array[i*16384 + j] > 0)                  case 'v':
90                                                  fprintf(f, "%lli\t0x%016llx\n",                          /*  Virtual program counter address:  */
91                                                      (long long)array[i*16384+j],                          a = cpu->pc;
92                                                      (long long)((i*16384+j) <<                          a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
93                                  DYNTRANS_INSTR_ALIGNMENT_SHIFT));                              DYNTRANS_INSTR_ALIGNMENT_SHIFT);
94                          }                          a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
95                  fclose(f);                          if (cpu->is_32bit)
96                  printf("n=0x%08x\n", n);                                  snprintf(buf + strlen(buf), sizeof(buf),
97                                        "0x%08"PRIx32, (uint32_t)a);
98                            else
99                                    snprintf(buf + strlen(buf), sizeof(buf),
100                                        "0x%016"PRIx64, (uint64_t)a);
101                            break;
102                    }
103                    i++;
104          }          }
105    
106            fprintf(cpu->machine->statistics.file, "%s\n", buf);
107  }  }
108  }  
 #endif  /*  PC statistics  */  
109    
110  #define S               gather_statistics(cpu)  #define S               gather_statistics(cpu)
111    
112  #ifdef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH  
113  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic;             \  #if 1
114                          cpu->cd.DYNTRANS_ARCH.next_ic += ic->arg[0];    \  
115                          ic->f(cpu, ic);  /*  The normal instruction execution core:  */
116    #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
117    
118  #else  #else
119  #define I               ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);  
120    /*  For heavy debugging:  */
121    #define I       ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;  \
122                    {       \
123                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
124                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
125                                sizeof(struct DYNTRANS_IC);                 \
126                            printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n",  \
127                                cpu->cd.DYNTRANS_ARCH.cur_ic_page,          \
128                                ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
129                    } \
130                    ic->f(cpu, ic);
131    
132  #endif  #endif
133    
134    /*  static long long nr_of_I_calls = 0;  */
135    
136    /*  Temporary hack for finding NULL bugs:  */
137    /*  #define I   ic = cpu->cd.DYNTRANS_ARCH.next_ic ++;                  \
138                    nr_of_I_calls ++;                                       \
139                    if (ic->f == NULL) {                                    \
140                            int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
141                                (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
142                                sizeof(struct DYNTRANS_IC);                 \
143                            cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \
144                                DYNTRANS_INSTR_ALIGNMENT_SHIFT);            \
145                            cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\
146                            printf("Crash at %016"PRIx64"\n", cpu->pc);     \
147                            printf("nr of I calls: %lli\n", nr_of_I_calls); \
148                            printf("Next ic = %p\n", cpu->cd.               \
149                                    DYNTRANS_ARCH.next_ic);                 \
150                            printf("cur ic page = %p\n", cpu->cd.           \
151                                    DYNTRANS_ARCH.cur_ic_page);             \
152                            cpu->running = 0;                               \
153                            return 0;                                       \
154                    }                                                       \
155                    ic->f(cpu, ic);  */
156    
157    /*  Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs:  */
158    /*  #define I           { int k; for (k=1; k<=31; k++)  \
159            cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\
160            if (cpu->cd.mips.gpr[0] != 0) {                 \
161                    fatal("NOOOOOO\n"); exit(1);            \
162            }                                               \
163            ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
164    */
165    #endif  /*  STATIC STUFF  */
166    
167    
168    
169    #ifdef  DYNTRANS_RUN_INSTR_DEF
170  /*  /*
171   *  XXX_cpu_run_instr():   *  XXX_run_instr():
172   *   *
173   *  Execute one or more instructions on a specific CPU, using dyntrans.   *  Execute one or more instructions on a specific CPU, using dyntrans.
174     *  (For dualmode archs, this function is included twice.)
175   *   *
176   *  Return value is the number of instructions executed during this call,   *  Return value is the number of instructions executed during this call,
177   *  0 if no instructions were executed.   *  0 if no instructions were executed.
178   */   */
179  int DYNTRANS_CPU_RUN_INSTR(struct emul *emul, struct cpu *cpu)  int DYNTRANS_RUN_INSTR_DEF(struct cpu *cpu)
180  {  {
181  #ifdef MODE32          MODE_uint_t cached_pc;
         uint32_t cached_pc;  
 #else  
         uint64_t cached_pc;  
 #endif  
182          int low_pc, n_instrs;          int low_pc, n_instrs;
183    
184            /*  Ugly... fix this some day.  */
185  #ifdef DYNTRANS_DUALMODE_32  #ifdef DYNTRANS_DUALMODE_32
186          if (cpu->is_32bit)  #ifdef MODE32
187                  DYNTRANS_PC_TO_POINTERS32(cpu);          DYNTRANS_PC_TO_POINTERS32(cpu);
188          else  #else
189            DYNTRANS_PC_TO_POINTERS(cpu);
190  #endif  #endif
191    #else
192          DYNTRANS_PC_TO_POINTERS(cpu);          DYNTRANS_PC_TO_POINTERS(cpu);
193    #endif
194    
195          /*          /*
196           *  Interrupt assertion?  (This is _below_ the initial PC to pointer           *  Interrupt assertion?  (This is _below_ the initial PC to pointer
197           *  conversion; if the conversion caused an exception of some kind           *  conversion; if the conversion caused an exception of some kind
198           *  then interrupts are probably disabled, and the exception will get           *  then interrupts are probably disabled, and the exception will get
199           *  priority over device interrupts.)           *  priority over device interrupts.)
200             *
201             *  TODO: Turn this into a family-specific function somewhere...
202           */           */
203  #ifdef DYNTRANS_ARM  #ifdef DYNTRANS_ARM
204          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))
205                  arm_exception(cpu, ARM_EXCEPTION_IRQ);                  arm_exception(cpu, ARM_EXCEPTION_IRQ);
206  #endif  #endif
207    #ifdef DYNTRANS_M88K
208            if (cpu->cd.m88k.irq_asserted &&
209                !(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_IND))
210                    m88k_exception(cpu, M88K_EXCEPTION_INTERRUPT, 0);
211    #endif
212    #ifdef DYNTRANS_MIPS
213            {
214                    int enabled, mask;
215                    int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
216                    if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
217                            /*  R3000:  */
218                            enabled = status & MIPS_SR_INT_IE;
219                    } else {
220                            /*  R4000 and others:  */
221                            enabled = (status & STATUS_IE)
222                                && !(status & STATUS_EXL) && !(status & STATUS_ERL);
223                            /*  Special case for R5900/C790/TX79:  */
224                            if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
225                                !(status & R5900_STATUS_EIE))
226                                    enabled = 0;
227                    }
228                    mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]
229                        & STATUS_IM_MASK;
230    
231                    if (enabled && mask)
232                            mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0);
233            }
234    #endif
235  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
236          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) {
237                  ppc_exception(cpu, PPC_EXCEPTION_DEC);                  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
238                            ppc_exception(cpu, PPC_EXCEPTION_DEC);
239                  cpu->cd.ppc.dec_intr_pending = 0;                  cpu->cd.ppc.dec_intr_pending = 0;
240          }          }
241          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)
242                  ppc_exception(cpu, PPC_EXCEPTION_EI);                  ppc_exception(cpu, PPC_EXCEPTION_EI);
243  #endif  #endif
244    #ifdef DYNTRANS_SH
245            if (cpu->cd.sh.int_to_assert > 0 && !(cpu->cd.sh.sr & SH_SR_BL)
246                && ((cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT)
247                < cpu->cd.sh.int_level)
248                    sh_exception(cpu, 0, cpu->cd.sh.int_to_assert, 0);
249    #endif
250    
251          cached_pc = cpu->pc;          cached_pc = cpu->pc;
252    
253          cpu->n_translated_instrs = 0;          cpu->n_translated_instrs = 0;
         cpu->running_translated = 1;  
254    
255          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
256              cpu->cd.DYNTRANS_ARCH.cur_ic_page;              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
257    
258          if (single_step || cpu->machine->instruction_trace) {          if (single_step || cpu->machine->instruction_trace
259                || cpu->machine->register_dump) {
260                  /*                  /*
261                   *  Single-step:                   *  Single-step:
262                   */                   */
263                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic                  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
264  #ifndef DYNTRANS_VARIABLE_INSTRUCTION_LENGTH                  if (cpu->machine->register_dump) {
265                      ++                          debug("\n");
266  #endif                          cpu_register_dump(cpu->machine, cpu, 1, 0x1);
267                      ;                  }
268                  if (cpu->machine->instruction_trace) {                  if (cpu->machine->instruction_trace) {
269  #ifdef DYNTRANS_X86                          /*  TODO/Note: This must be large enough to hold
270                          unsigned char instr[17];                              any instruction for any ISA:  */
271                          cpu->cd.x86.cursegment = X86_S_CS;                          unsigned char instr[1 <<
272                          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  
273                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],                          if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
274                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {                              sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
275                                  fatal("XXX_cpu_run_instr(): could not read "                                  fatal("XXX_run_instr(): could not read "
276                                      "the instruction\n");                                      "the instruction\n");
277                          } else {                          } else {
278                                  cpu_disassemble_instr(cpu->machine, cpu,  #ifdef DYNTRANS_DELAYSLOT
279                                      instr, 1, 0, 0);                                  int len =
280  #ifdef DYNTRANS_MIPS  #endif
281  /*  TODO: generalize, not just MIPS  */                                      cpu_disassemble_instr(
282                                        cpu->machine, cpu, instr, 1, 0);
283    #ifdef DYNTRANS_DELAYSLOT
284                                  /*  Show the instruction in the delay slot,                                  /*  Show the instruction in the delay slot,
285                                      if any:  */                                      if any:  */
286                                  fatal("TODO: check for delay slot!\n");                                  if (cpu->instruction_has_delayslot == NULL)
287                                            fatal("WARNING: ihd func not yet"
288                                                " implemented?\n");
289                                    else if (cpu->instruction_has_delayslot(cpu,
290                                        instr)) {
291                                            int saved_delayslot = cpu->delay_slot;
292                                            cpu->memory_rw(cpu, cpu->mem, cached_pc
293                                                + len, &instr[0],
294                                                sizeof(instr), MEM_READ,
295                                                CACHE_INSTRUCTION);
296                                            cpu->delay_slot = DELAYED;
297                                            cpu->pc += len;
298                                            cpu_disassemble_instr(cpu->machine,
299                                                cpu, instr, 1, 0);
300                                            cpu->delay_slot = saved_delayslot;
301                                            cpu->pc -= len;
302                                    }
303  #endif  #endif
304                          }                          }
305                  }                  }
306    
307                  /*  When single-stepping, multiple instruction calls cannot                  if (cpu->machine->statistics.enabled)
                     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) :  
 #endif  
                                         instr(to_be_translated);  
                         fatal("[ Note: The translation of physical page 0x%llx"  
                             " contained combinations of instructions; these "  
                             "are now flushed because we are single-stepping."  
                             " ]\n", (long long)cpu->cd.DYNTRANS_ARCH.  
                             cur_physpage->physaddr);  
                         cpu->cd.DYNTRANS_ARCH.cur_physpage->flags &=  
                             ~(COMBINATIONS | TRANSLATIONS);  
                 }  
   
                 if (show_opcode_statistics)  
308                          S;                          S;
309    
310                  /*  Execute just one instruction:  */                  /*  Execute just one instruction:  */
311                  ic->f(cpu, ic);                  I;
312    
313                  n_instrs = 1;                  n_instrs = 1;
314          } else if (show_opcode_statistics) {          } else if (cpu->machine->statistics.enabled) {
315                  /*  Gather statistics while executing multiple instructions:  */                  /*  Gather statistics while executing multiple instructions:  */
316                  n_instrs = 0;                  n_instrs = 0;
317                  for (;;) {                  for (;;) {
# Line 250  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 324  int DYNTRANS_CPU_RUN_INSTR(struct emul *
324    
325                          n_instrs += 24;                          n_instrs += 24;
326    
327                          if (!cpu->running_translated ||                          if (n_instrs + cpu->n_translated_instrs >=
328                              n_instrs + cpu->n_translated_instrs >= 16384)                              N_SAFE_DYNTRANS_LIMIT)
329                                  break;                                  break;
330                  }                  }
331          } else {          } else {
332                  /*  Execute multiple instructions:  */                  /*
333                     *  Execute multiple instructions:
334                     *
335                     *  (This is the core dyntrans loop.)
336                     */
337                  n_instrs = 0;                  n_instrs = 0;
338    
339                  for (;;) {                  for (;;) {
340                          struct DYNTRANS_IC *ic;                          struct DYNTRANS_IC *ic;
341    
# Line 268  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 347  int DYNTRANS_CPU_RUN_INSTR(struct emul *
347    
348                          I; I; I; I; I;   I; I; I; I; I;                          I; I; I; I; I;   I; I; I; I; I;
349    
350                          n_instrs += 60;                          I; I; I; I; I;   I; I; I; I; I;
351                            I; I; I; I; I;   I; I; I; I; I;
352                            I; I; I; I; I;   I; I; I; I; I;
353                            I; I; I; I; I;   I; I; I; I; I;
354                            I; I; I; I; I;   I; I; I; I; I;
355    
356                            I; I; I; I; I;   I; I; I; I; I;
357    
358                          if (!cpu->running_translated ||                          cpu->n_translated_instrs += 120;
359                              n_instrs + cpu->n_translated_instrs >= 16384)                          if (cpu->n_translated_instrs >= N_SAFE_DYNTRANS_LIMIT)
360                                  break;                                  break;
361                  }                  }
362          }          }
# Line 300  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 385  int DYNTRANS_CPU_RUN_INSTR(struct emul *
385                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);                      DYNTRANS_INSTR_ALIGNMENT_SHIFT);
386          }          }
387    
388    #ifdef DYNTRANS_MIPS
389            /*  Update the count register (on everything except EXC3K):  */
390            if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
391                    uint32_t old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
392                    int32_t diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
393                    int32_t diff2;
394                    cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
395                        (int32_t) (old + n_instrs);
396                    diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
397                        cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
398    
399                    if (cpu->cd.mips.compare_register_set) {
400    #if 1
401    /*  Not yet.  TODO  */
402                            if (cpu->machine->emulated_hz > 0) {
403                                    if (cpu->cd.mips.compare_interrupts_pending > 0)
404                                            INTERRUPT_ASSERT(
405                                                cpu->cd.mips.irq_compare);
406                            } else
407    #endif
408                            {
409                                    if (diff1 > 0 && diff2 <= 0)
410                                            INTERRUPT_ASSERT(
411                                                cpu->cd.mips.irq_compare);
412                            }
413                    }
414            }
415    #endif
416  #ifdef DYNTRANS_PPC  #ifdef DYNTRANS_PPC
417          /*  Update the Decrementer and Time base registers:  */          /*  Update the Decrementer and Time base registers:  */
418          {          {
# Line 315  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 428  int DYNTRANS_CPU_RUN_INSTR(struct emul *
428          }          }
429  #endif  #endif
430    
431            cpu->ninstrs += n_instrs;
432    
433          /*  Return the nr of instructions executed:  */          /*  Return the nr of instructions executed:  */
434          return n_instrs;          return n_instrs;
435  }  }
436  #endif  /*  DYNTRANS_CPU_RUN_INSTR  */  #endif  /*  DYNTRANS_RUN_INSTR  */
437    
438    
439    
440  #ifdef DYNTRANS_FUNCTION_TRACE  #ifdef DYNTRANS_FUNCTION_TRACE_DEF
441  /*  /*
442   *  XXX_cpu_functioncall_trace():   *  XXX_cpu_functioncall_trace():
443   *   *
# Line 330  int DYNTRANS_CPU_RUN_INSTR(struct emul * Line 445  int DYNTRANS_CPU_RUN_INSTR(struct emul *
445   *  like    <f()>  or  <0x1234()>   on a function call. It is up to this   *  like    <f()>  or  <0x1234()>   on a function call. It is up to this
446   *  function to print the arguments passed.   *  function to print the arguments passed.
447   */   */
448  void DYNTRANS_FUNCTION_TRACE(struct cpu *cpu, uint64_t f, int n_args)  void DYNTRANS_FUNCTION_TRACE_DEF(struct cpu *cpu, uint64_t f, int n_args)
449  {  {
450            int show_symbolic_function_name = 1;
451          char strbuf[50];          char strbuf[50];
452          char *symbol;          char *symbol;
453          uint64_t ot;          uint64_t ot;
454          int x, print_dots = 1, n_args_to_print =          int x, print_dots = 1, n_args_to_print =
455  #ifdef DYNTRANS_ALPHA  #if defined(DYNTRANS_ALPHA) || defined(DYNTRANS_SPARC)
456              6              6
457  #else  #else
458  #ifdef DYNTRANS_SH  #if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K)
459              8              8   /*  Both for 32-bit and 64-bit SuperH, and M88K  */
460  #else  #else
461              4   /*  Default value for most archs  */              4   /*  Default value for most archs  */
462  #endif  #endif
# Line 352  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 468  void DYNTRANS_FUNCTION_TRACE(struct cpu
468                  n_args_to_print = n_args;                  n_args_to_print = n_args;
469          }          }
470    
471    #ifdef DYNTRANS_M88K
472            /*  Special hack for M88K userspace:  */
473            if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
474                    show_symbolic_function_name = 0;
475    #endif
476    
477          /*          /*
478           *  TODO: The type of each argument should be taken from the symbol           *  TODO: The type of each argument should be taken from the symbol
479           *  table, in some way.           *  table, in some way.
# Line 364  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 486  void DYNTRANS_FUNCTION_TRACE(struct cpu
486           *  than were passed in register.           *  than were passed in register.
487           */           */
488          for (x=0; x<n_args_to_print; x++) {          for (x=0; x<n_args_to_print; x++) {
489                  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.  
490  #ifdef DYNTRANS_ALPHA  #ifdef DYNTRANS_ALPHA
491                      r[ALPHA_A0                      r[ALPHA_A0
492  #endif  #endif
# Line 381  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 498  void DYNTRANS_FUNCTION_TRACE(struct cpu
498                          they go downwards, ie. 22,23 and so on  */                          they go downwards, ie. 22,23 and so on  */
499                      r[24                      r[24
500  #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  
501  #ifdef DYNTRANS_MIPS  #ifdef DYNTRANS_MIPS
502                      gpr[MIPS_GPR_A0                      gpr[MIPS_GPR_A0
503  #endif  #endif
504    #ifdef DYNTRANS_M32R
505                        r[0         /*  r0..r3?  */
506    #endif
507    #ifdef DYNTRANS_M88K
508                        r[2         /*  r2..r9  */
509    #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[24                      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 414  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 430  void DYNTRANS_FUNCTION_TRACE(struct cpu Line 543  void DYNTRANS_FUNCTION_TRACE(struct cpu
543          if (print_dots)          if (print_dots)
544                  fatal(",..");                  fatal(",..");
545  }  }
546  #endif  #endif  /*  DYNTRANS_FUNCTION_TRACE_DEF  */
547    
548    
549    
550  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF
   
 /*  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  
   
 #ifdef DYNTRANS_DELAYSLOT  
 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #ifdef DYNTRANS_DUALMODE_32  
 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);  
 #endif  
 #endif  
   
551  /*  /*
552   *  XXX_tc_allocate_default_page():   *  XXX_tc_allocate_default_page():
553   *   *
554   *  Create a default page (with just pointers to instr(to_be_translated)   *  Create a default page (with just pointers to instr(to_be_translated)
555   *  at cpu->translation_cache_cur_ofs.   *  at cpu->translation_cache_cur_ofs.
556   */   */
557  static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE(struct cpu *cpu,  static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF(struct cpu *cpu,
558          uint64_t physaddr)          uint64_t physaddr)
559  {  {
560          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
         int i;  
561    
         /*  Create the physpage header:  */  
562          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache          ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
563              + cpu->translation_cache_cur_ofs);              + cpu->translation_cache_cur_ofs);
         ppp->next_ofs = 0;  
         ppp->physaddr = physaddr;  
   
         /*  TODO: Is this faster than copying an entire template page?  */  
         for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)  
                 ppp->ics[i].f =  
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
564    
565          ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =          /*  Copy the entire template page first:  */
566  #ifdef DYNTRANS_DUALMODE_32          memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
567              cpu->is_32bit? instr32(end_of_page) :              struct DYNTRANS_TC_PHYSPAGE));
 #endif  
             instr(end_of_page);  
568    
569  #ifdef DYNTRANS_DELAYSLOT          ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
         ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =  
 #ifdef DYNTRANS_DUALMODE_32  
             cpu->is_32bit? instr32(end_of_page2) :  
 #endif  
             instr(end_of_page2);  
 #endif  
570    
571          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);          cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
572    
# Line 497  static void DYNTRANS_TC_ALLOCATE_DEFAULT Line 574  static void DYNTRANS_TC_ALLOCATE_DEFAULT
574          cpu->translation_cache_cur_ofs |= 63;          cpu->translation_cache_cur_ofs |= 63;
575          cpu->translation_cache_cur_ofs ++;          cpu->translation_cache_cur_ofs ++;
576  }  }
577  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE  */  #endif  /*  DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF  */
578    
579    
580    
# Line 514  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 591  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
591  #else  #else
592          uint64_t          uint64_t
593  #endif  #endif
594              cached_pc, physaddr = 0;              cached_pc = cpu->pc, physaddr = 0;
595          uint32_t physpage_ofs;          uint32_t physpage_ofs;
596          int ok, pagenr, table_index;          int ok, pagenr, table_index;
597          uint32_t *physpage_entryp;          uint32_t *physpage_entryp;
598          struct DYNTRANS_TC_PHYSPAGE *ppp;          struct DYNTRANS_TC_PHYSPAGE *ppp;
599    
600  #ifdef MODE32  #ifdef MODE32
601          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];  
602  #else  #else
603          fatal("Neither alpha nor 32-bit? 3\n");          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
604          exit(1);          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
605  #endif          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
606            uint32_t x1, x2, x3;
607            struct DYNTRANS_L2_64_TABLE *l2;
608            struct DYNTRANS_L3_64_TABLE *l3;
609    
610            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
611            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
612            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
613            /*  fatal("X3: cached_pc=%016"PRIx64" x1=%x x2=%x x3=%x\n",
614                (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3);  */
615            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
616            /*  fatal("  l2 = %p\n", l2);  */
617            l3 = l2->l3[x2];
618            /*  fatal("  l3 = %p\n", l3);  */
619  #endif  #endif
620    
621          /*  Virtual to physical address translation:  */          /*  Virtual to physical address translation:  */
# Line 551  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 626  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
626                  ok = 1;                  ok = 1;
627          }          }
628  #else  #else
629  #ifdef DYNTRANS_ALPHA          if (l3->host_load[x3] != NULL) {
630          if (vph_p->host_load[b] != NULL) {                  physaddr = l3->phys_addr[x3];
                 physaddr = vph_p->phys_addr[b];  
631                  ok = 1;                  ok = 1;
632          }          }
 #else  
         fatal("Neither alpha nor 32-bit? 4\n");  
         exit(1);  
 #endif  
633  #endif  #endif
634    
635          if (!ok) {          if (!ok) {
636                  uint64_t paddr;                  uint64_t paddr;
637                  if (cpu->translate_address != NULL)                  if (cpu->translate_v2p != NULL) {
638                          ok = cpu->translate_address(cpu, cached_pc,                          uint64_t vaddr =
639                              &paddr, FLAG_INSTR);  #if defined(MODE32) && defined(DYNTRANS_MIPS)
640                  else {                          /*  32-bit MIPS is _sign_ extend, not zero.  */
641                                (int32_t)
642    #endif
643                                cached_pc;
644                            ok = cpu->translate_v2p(
645                                cpu, vaddr, &paddr, FLAG_INSTR);
646                    } else {
647                          paddr = cached_pc;                          paddr = cached_pc;
648                          ok = 1;                          ok = 1;
649                  }                  }
650                  if (!ok) {                  if (!ok) {
651                          /*  fatal("TODO: instruction vaddr=>paddr translation"                          /*
652                              " failed. vaddr=0x%llx\n", (long long)cached_pc);                           *  The PC is now set to the exception handler.
653                          fatal("!! cpu->pc=0x%llx\n", (long long)cpu->pc);  */                           *  Try to find the paddr in the translation arrays,
654                             *  or if that fails, call translate_v2p for the
655                             *  exception handler.
656                             */
657                            /*  fatal("TODO: instruction vaddr=>paddr translation "
658                                "failed. vaddr=0x%"PRIx64"\n", (uint64_t)cached_pc);
659                            fatal("!! cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
660    
661                            /*  If there was an exception, the PC has changed.
662                                Update cached_pc:  */
663                            cached_pc = cpu->pc;
664    
665    #ifdef MODE32
666                            index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
667                            if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
668                                    paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
669                                    ok = 1;
670                            }
671    #else
672                            x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
673                            x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
674                                & mask2;
675                            x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
676                                - DYNTRANS_L3N)) & mask3;
677                            l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
678                            l3 = l2->l3[x2];
679                            if (l3->host_load[x3] != NULL) {
680                                    paddr = l3->phys_addr[x3];
681                                    ok = 1;
682                            }
683    #endif
684    
685                          ok = cpu->translate_address(cpu, cpu->pc, &paddr,                          if (!ok) {
686                              FLAG_INSTR);                                  ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
687                                        FLAG_INSTR);
688                            }
689    
690                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "                          /*  printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
691                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);                              "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
692                          fatal("!? cpu->pc=0x%llx\n", (long long)cpu->pc);  */                          fatal("!? cpu->pc=0x%"PRIx64"\n", (uint64_t)cpu->pc); */
693    
694                          if (!ok) {                          if (!ok) {
695                                  fatal("FATAL: could not find physical"                                  fatal("FATAL: could not find physical"
# Line 589  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 697  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
697                                  exit(1);                                  exit(1);
698                          }                          }
699                  }                  }
700                  cached_pc = cpu->pc;  
 #ifdef MODE32  
                 index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);  
 #endif  
701                  physaddr = paddr;                  physaddr = paddr;
702          }          }
703    
704            physaddr &= ~(DYNTRANS_PAGESIZE - 1);
705    
706  #ifdef MODE32  #ifdef MODE32
707          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {          if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
708    #else
709            if (l3->host_load[x3] == NULL) {
710    #endif
711                    int q = DYNTRANS_PAGESIZE - 1;
712                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,                  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
713                      physaddr, MEM_READ);                      physaddr, MEM_READ);
714                  if (host_page != NULL) {                  if (host_page != NULL) {
                         int q = DYNTRANS_PAGESIZE - 1;  
                         host_page += (physaddr &  
                             ((1 << BITS_PER_MEMBLOCK) - 1) & ~q);  
715                          cpu->update_translation_table(cpu, cached_pc & ~q,                          cpu->update_translation_table(cpu, cached_pc & ~q,
716                              host_page, TLB_CODE, physaddr & ~q);                              host_page, 0, physaddr);
717                  }                  }
718          }          }
 #endif  
719    
720          if (cpu->translation_cache_cur_ofs >= DYNTRANS_CACHE_SIZE) {          if (cpu->translation_cache_cur_ofs >= dyntrans_cache_size) {
721                  debug("[ dyntrans: resetting the translation cache ]\n");  #ifdef UNSTABLE_DEVEL
722                    fatal("[ dyntrans: resetting the translation cache ]\n");
723    #endif
724                  cpu_create_or_reset_tc(cpu);                  cpu_create_or_reset_tc(cpu);
725          }          }
726    
# Line 626  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 735  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
735          while (physpage_ofs != 0) {          while (physpage_ofs != 0) {
736                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
737                      + physpage_ofs);                      + physpage_ofs);
738    
739                  /*  If we found the page in the cache, then we're done:  */                  /*  If we found the page in the cache, then we're done:  */
740                  if (ppp->physaddr == physaddr)                  if (ppp->physaddr == physaddr)
741                          break;                          break;
742    
743                  /*  Try the next page in the chain:  */                  /*  Try the next page in the chain:  */
744                  physpage_ofs = ppp->next_ofs;                  physpage_ofs = ppp->next_ofs;
745          }          }
746    
747          /*  If the offset is 0 (or ppp is NULL), then we need to create a          /*
748              new "default" empty translation page.  */           *  If the offset is 0, then no translation exists yet for this
749             *  physical address. Let's create a new page, and add it first in
750             *  the chain.
751             */
752            if (physpage_ofs == 0) {
753                    uint32_t previous_first_page_in_chain;
754    
755          if (ppp == NULL) {                  /*  fatal("CREATING page %lli (physaddr 0x%"PRIx64"), table "
756                  /*  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,  
757                      (int)table_index);  */                      (int)table_index);  */
758    
759                    previous_first_page_in_chain = *physpage_entryp;
760    
761                    /*  Insert the new page first in the chain:  */
762                  *physpage_entryp = physpage_ofs =                  *physpage_entryp = physpage_ofs =
763                      cpu->translation_cache_cur_ofs;                      cpu->translation_cache_cur_ofs;
764    
# Line 648  void DYNTRANS_PC_TO_POINTERS_GENERIC(str Line 767  void DYNTRANS_PC_TO_POINTERS_GENERIC(str
767    
768                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache                  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
769                      + physpage_ofs);                      + physpage_ofs);
770    
771                    /*  Point to the other pages in the same chain:  */
772                    ppp->next_ofs = previous_first_page_in_chain;
773          }          }
774    
775            /*  Here, ppp points to a valid physical page struct.  */
776    
777  #ifdef MODE32  #ifdef MODE32
778          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)          if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
779                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
780    #else
781            if (l3->host_load[x3] != NULL)
782                    l3->phys_page[x3] = ppp;
783  #endif  #endif
784    
785  #ifdef DYNTRANS_ALPHA          /*
786          if (vph_p->host_load[b] != NULL)           *  If there are no translations yet on this page, then mark it
787                  vph_p->phys_page[b] = ppp;           *  as non-writable. If there are already translations, then it
788  #endif           *  should already have been marked as non-writable.
789             */
790  #ifdef MODE32          if (ppp->translations_bitmap == 0) {
791          /*  Small optimization: only mark the physical page as non-writable                  cpu->invalidate_translation_caches(cpu, physaddr,
792              if it did not contain translations. (Because if it does contain                      JUST_MARK_AS_NON_WRITABLE | INVALIDATE_PADDR);
793              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);  
794    
795          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
796    
797          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 +
798              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
799    
800          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
801              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
802              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
803  }  }
804    
805    
# Line 711  void DYNTRANS_PC_TO_POINTERS_FUNC(struct Line 833  void DYNTRANS_PC_TO_POINTERS_FUNC(struct
833          if (ppp != NULL)          if (ppp != NULL)
834                  goto have_it;                  goto have_it;
835  #else  #else
836  #ifdef DYNTRANS_ALPHA          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
837          uint32_t a, b;          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
838          int kernel = 0;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
839          struct alpha_vph_page *vph_p;          uint32_t x1, x2, x3;
840          a = (cached_pc >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);          struct DYNTRANS_L2_64_TABLE *l2;
841          b = (cached_pc >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          struct DYNTRANS_L3_64_TABLE *l3;
842          if ((cached_pc >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {  
843                  vph_p = cpu->cd.alpha.vph_table0_kernel[a];          x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
844                  kernel = 1;          x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
845          } else          x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
846                  vph_p = cpu->cd.alpha.vph_table0[a];          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
847          if (vph_p != cpu->cd.alpha.vph_default_page) {          l3 = l2->l3[x2];
848                  ppp = vph_p->phys_page[b];          ppp = l3->phys_page[x3];
849                  if (ppp != NULL)          if (ppp != NULL)
850                          goto have_it;                  goto have_it;
         }  
 #else  
         fatal("X1: cached_pc=%016llx\n", (long long)cached_pc);  
         /*  Temporary, to avoid a compiler warning:  */  
         ppp = NULL;  
         fatal("Neither alpha nor 32-bit? 1\n");  
         exit(1);  
 #endif  
851  #endif  #endif
852    
853          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);          DYNTRANS_PC_TO_POINTERS_GENERIC(cpu);
854          return;          return;
855    
856          /*  Quick return path:  */          /*  Quick return path:  */
 #if defined(MODE32) || defined(DYNTRANS_ALPHA)  
857  have_it:  have_it:
858          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];          cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
859          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 +
860              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);              DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
861    
862          /*  printf("cached_pc=0x%016llx  pagenr=%lli  table_index=%lli, "          /*  printf("cached_pc=0x%016"PRIx64"  pagenr=%lli  table_index=%lli, "
863              "physpage_ofs=0x%016llx\n", (long long)cached_pc, (long long)pagenr,              "physpage_ofs=0x%016"PRIx64"\n", (uint64_t)cached_pc, (long long)
864              (long long)table_index, (long long)physpage_ofs);  */              pagenr, (long long)table_index, (uint64_t)physpage_ofs);  */
 #endif  
865  }  }
866  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */  #endif  /*  DYNTRANS_PC_TO_POINTERS_FUNC  */
867    
868    
869    
870    #ifdef DYNTRANS_INIT_TABLES
871    
872    /*  forward declaration of to_be_translated and end_of_page:  */
873    static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
874    static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
875    #ifdef DYNTRANS_DUALMODE_32
876    static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
877    static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
878    #endif
879    
880    #ifdef DYNTRANS_DUALMODE_32
881    #define TO_BE_TRANSLATED    ( cpu->is_32bit? instr32(to_be_translated) : \
882                                  instr(to_be_translated) )
883    #else
884    #define TO_BE_TRANSLATED    ( instr(to_be_translated) )
885    #endif
886    
887    #ifdef DYNTRANS_DELAYSLOT
888    static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
889    #ifdef DYNTRANS_DUALMODE_32
890    static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
891    #endif
892    #endif
893    
894    /*
895     *  XXX_init_tables():
896     *
897     *  Initializes the default translation page (for newly allocated pages), and
898     *  for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
899     */
900    void DYNTRANS_INIT_TABLES(struct cpu *cpu)
901    {
902    #ifndef MODE32
903            struct DYNTRANS_L2_64_TABLE *dummy_l2;
904            struct DYNTRANS_L3_64_TABLE *dummy_l3;
905            int x1, x2;
906    #endif
907            int i;
908            struct DYNTRANS_TC_PHYSPAGE *ppp;
909    
910            CHECK_ALLOCATION(ppp = malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
911    
912            ppp->next_ofs = 0;
913            ppp->translations_bitmap = 0;
914            ppp->translation_ranges_ofs = 0;
915            /*  ppp->physaddr is filled in by the page allocator  */
916    
917            for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
918                    ppp->ics[i].f = TO_BE_TRANSLATED;
919    
920            /*  End-of-page:  */
921            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
922    #ifdef DYNTRANS_DUALMODE_32
923                cpu->is_32bit? instr32(end_of_page) :
924    #endif
925                instr(end_of_page);
926    
927            /*  End-of-page-2, for delay-slot architectures:  */
928    #ifdef DYNTRANS_DELAYSLOT
929            ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
930    #ifdef DYNTRANS_DUALMODE_32
931                cpu->is_32bit? instr32(end_of_page2) :
932    #endif
933                instr(end_of_page2);
934    #endif
935    
936            cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
937    
938    
939            /*  Prepare 64-bit virtual address translation tables:  */
940    #ifndef MODE32
941            if (cpu->is_32bit)
942                    return;
943    
944            dummy_l2 = zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
945            dummy_l3 = zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
946    
947            cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
948            cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
949    
950            for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
951                    cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
952    
953            for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
954                    dummy_l2->l3[x2] = dummy_l3;
955    #endif
956    }
957    #endif  /*  DYNTRANS_INIT_TABLES  */
958    
959    
960    
961  #ifdef DYNTRANS_INVAL_ENTRY  #ifdef DYNTRANS_INVAL_ENTRY
962  /*  /*
963   *  XXX_invalidate_tlb_entry():   *  XXX_invalidate_tlb_entry():
# Line 785  static void DYNTRANS_INVALIDATE_TLB_ENTR Line 988  static void DYNTRANS_INVALIDATE_TLB_ENTR
988                      (int)vaddr_page);  */                      (int)vaddr_page);  */
989                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
990          } else {          } else {
991                    int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
992                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
993                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
994                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;                  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
995                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
996                    if (tlbi > 0)
997                            cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
998                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;                  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
999          }          }
1000  #else  #else
1001          /*  2-level:  */          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1002  #ifdef DYNTRANS_ALPHA          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1003          struct alpha_vph_page *vph_p;          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1004          uint32_t a, b;          uint32_t x1, x2, x3;
1005          int kernel = 0;          struct DYNTRANS_L2_64_TABLE *l2;
1006            struct DYNTRANS_L3_64_TABLE *l3;
1007          a = (vaddr_page >> ALPHA_LEVEL0_SHIFT) & (ALPHA_LEVEL0 - 1);  
1008          b = (vaddr_page >> ALPHA_LEVEL1_SHIFT) & (ALPHA_LEVEL1 - 1);          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1009          if ((vaddr_page >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1010                  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];  
1011    
1012          if (vph_p == cpu->cd.alpha.vph_default_page) {          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1013                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 1.\n");          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1014                  exit(1);                  return;
1015          }  
1016            l3 = l2->l3[x2];
1017            if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1018                    return;
1019    
1020          if (flags & JUST_MARK_AS_NON_WRITABLE) {          if (flags & JUST_MARK_AS_NON_WRITABLE) {
1021                  vph_p->host_store[b] = NULL;                  l3->host_store[x3] = NULL;
1022                  return;                  return;
1023          }          }
1024          vph_p->host_load[b] = NULL;  
1025          vph_p->host_store[b] = NULL;  #ifdef BUGHUNT
1026          vph_p->phys_addr[b] = 0;  
1027          vph_p->phys_page[b] = NULL;  {
1028          vph_p->refcount --;          /*  Consistency check, for debugging:  */
1029          if (vph_p->refcount < 0) {          int x1, x1b; // x2, x3;
1030                  fatal("alpha_invalidate_tlb_entry(): huh? Problem 2.\n");          struct DYNTRANS_L2_64_TABLE *l2;
1031            //struct DYNTRANS_L3_64_TABLE *l3;
1032    
1033            for (x1 = 0; x1 <= mask1; x1 ++) {
1034                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1035                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1036                            continue;
1037                    /*  Make sure that this l2 isn't used more than 1 time!  */
1038                    for (x1b = 0; x1b <= mask1; x1b ++)
1039                            if (x1 != x1b &&
1040                                l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1041                                    fatal("L2 reuse: %p\n", l2);
1042                                    exit(1);
1043                            }
1044            }
1045    }
1046    
1047    /*  Count how many pages are actually in use:  */
1048    {
1049            int n=0, i;
1050            for (i=0; i<=mask3; i++)
1051                    if (l3->vaddr_to_tlbindex[i])
1052                            n++;
1053            if (n != l3->refcount) {
1054                    printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1055                  exit(1);                  exit(1);
1056          }          }
1057          if (vph_p->refcount == 0) {  
1058                  vph_p->next = cpu->cd.alpha.vph_next_free_page;          n = 0;
1059                  cpu->cd.alpha.vph_next_free_page = vph_p;          for (i=0; i<=mask3; i++)
1060                  if (kernel)                  if (l3->host_load[i] != NULL)
1061                          cpu->cd.alpha.vph_table0_kernel[a] =                          n++;
1062                              cpu->cd.alpha.vph_default_page;          if (n != l3->refcount) {
1063                  else                  printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1064                          cpu->cd.alpha.vph_table0[a] =                  exit(1);
1065                              cpu->cd.alpha.vph_default_page;          }
1066    }
1067    #endif
1068    
1069            l3->host_load[x3] = NULL;
1070            l3->host_store[x3] = NULL;
1071            l3->phys_addr[x3] = 0;
1072            l3->phys_page[x3] = NULL;
1073            if (l3->vaddr_to_tlbindex[x3] != 0) {
1074                    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1075                        l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1076                    l3->refcount --;
1077            }
1078            l3->vaddr_to_tlbindex[x3] = 0;
1079    
1080            if (l3->refcount < 0) {
1081                    fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1082                    exit(1);
1083            }
1084    
1085            if (l3->refcount == 0) {
1086                    l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1087                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1088                    l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1089    
1090    #ifdef BUGHUNT
1091    /*  Make sure that we're placing a CLEAN page on the
1092        freelist:  */
1093    {
1094            int i;
1095            for (i=0; i<=mask3; i++)
1096                    if (l3->host_load[i] != NULL) {
1097                            fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1098                            exit(1);
1099                    }
1100    }
1101    #endif
1102                    l2->refcount --;
1103                    if (l2->refcount < 0) {
1104                            fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1105                            exit(1);
1106                    }
1107                    if (l2->refcount == 0) {
1108                            l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1109                            cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1110                            cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1111                                cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1112                    }
1113          }          }
 #else   /*  !DYNTRANS_ALPHA  */  
         fatal("Not yet for non-1-level, non-Alpha\n");  
 #endif  /*  !DYNTRANS_ALPHA  */  
1114  #endif  #endif
1115  }  }
1116  #endif  #endif
# Line 966  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1240  void DYNTRANS_INVALIDATE_TC_CODE(struct
1240                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;                  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1241    
1242                  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  
   
1243                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);                  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1244    
1245                  physpage_entryp = &(((uint32_t *)cpu->                  physpage_entryp = &(((uint32_t *)cpu->
1246                      translation_cache)[table_index]);                      translation_cache)[table_index]);
1247                  physpage_ofs = *physpage_entryp;                  physpage_ofs = *physpage_entryp;
1248    
1249                    /*  Return immediately if there is no code translation
1250                        for this page.  */
1251                    if (physpage_ofs == 0)
1252                            return;
1253    
1254                  prev_ppp = ppp = NULL;                  prev_ppp = ppp = NULL;
1255    
1256                  /*  Traverse the physical page chain:  */                  /*  Traverse the physical page chain:  */
# Line 990  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1258  void DYNTRANS_INVALIDATE_TC_CODE(struct
1258                          prev_ppp = ppp;                          prev_ppp = ppp;
1259                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)                          ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1260                              (cpu->translation_cache + physpage_ofs);                              (cpu->translation_cache + physpage_ofs);
1261    
1262                          /*  If we found the page in the cache,                          /*  If we found the page in the cache,
1263                              then we're done:  */                              then we're done:  */
1264                          if (ppp->physaddr == addr)                          if (ppp->physaddr == addr)
1265                                  break;                                  break;
1266    
1267                          /*  Try the next page in the chain:  */                          /*  Try the next page in the chain:  */
1268                          physpage_ofs = ppp->next_ofs;                          physpage_ofs = ppp->next_ofs;
1269                  }                  }
1270    
1271                    /*  If there is no translation, there is no need to go
1272                        on and try to remove it from the vph_tlb_entry array:  */
1273                  if (physpage_ofs == 0)                  if (physpage_ofs == 0)
1274                          ppp = NULL;                          return;
1275    
1276  #if 1  #if 0
1277                  /*                  /*
1278                   *  "Bypass" the page, removing it from the code cache.                   *  "Bypass" the page, removing it from the code cache.
1279                   *                   *
# Line 1023  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1295  void DYNTRANS_INVALIDATE_TC_CODE(struct
1295                   *  it might be faster since we don't risk wasting cache                   *  it might be faster since we don't risk wasting cache
1296                   *  memory as quickly (which would force unnecessary Restarts).                   *  memory as quickly (which would force unnecessary Restarts).
1297                   */                   */
1298                  if (ppp != NULL) {                  if (ppp != NULL && ppp->translations_bitmap != 0) {
1299                          /*  TODO: Is this faster than copying an entire                          uint32_t x = ppp->translations_bitmap;  /*  TODO:
1300                              template page?  */                                  urk Should be same type as the bitmap */
1301                          int i;                          int i, j, n, m;
1302                          for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)                          n = 8 * sizeof(x);
1303                                  ppp->ics[i].f =                          m = DYNTRANS_IC_ENTRIES_PER_PAGE / n;
1304  #ifdef DYNTRANS_DUALMODE_32  
1305                                      cpu->is_32bit? instr32(to_be_translated) :                          for (i=0; i<n; i++) {
1306  #endif                                  if (x & 1) {
1307                                      instr(to_be_translated);                                          for (j=0; j<m; j++)
1308                                                    ppp->ics[i*m + j].f =
1309                                                        TO_BE_TRANSLATED;
1310                                    }
1311    
1312                                    x >>= 1;
1313                            }
1314    
1315                            ppp->translations_bitmap = 0;
1316    
1317                            /*  Clear the list of translatable ranges:  */
1318                            if (ppp->translation_ranges_ofs != 0) {
1319                                    struct physpage_ranges *physpage_ranges =
1320                                        (struct physpage_ranges *)
1321                                        (cpu->translation_cache +
1322                                        ppp->translation_ranges_ofs);
1323                                    physpage_ranges->next_ofs = 0;
1324                                    physpage_ranges->n_entries_used = 0;
1325                            }
1326                  }                  }
1327  #endif  #endif
1328          }          }
1329    
1330          /*  Invalidate entries (NOTE: only code entries) in the VPH table:  */          /*  Invalidate entries in the VPH table:  */
1331          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 ++) {  
1332                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1333                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]                          vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1334                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);                              .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
# Line 1053  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1342  void DYNTRANS_INVALIDATE_TC_CODE(struct
1342                                  uint32_t index =                                  uint32_t index =
1343                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                                      DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1344                                  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));  
1345  #else  #else
1346                                  /*  2-level:  */                                  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1347  #ifdef DYNTRANS_ALPHA                                  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1348                                  struct alpha_vph_page *vph_p;                                  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1349                                  uint32_t a, b;                                  uint32_t x1, x2, x3;
1350                                  int kernel = 0;                                  struct DYNTRANS_L2_64_TABLE *l2;
1351                                    struct DYNTRANS_L3_64_TABLE *l3;
1352                                  a = (vaddr_page >> ALPHA_LEVEL0_SHIFT)  
1353                                      & (ALPHA_LEVEL0 - 1);                                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1354                                  b = (vaddr_page >> ALPHA_LEVEL1_SHIFT)                                  x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1355                                      & (ALPHA_LEVEL1 - 1);                                      DYNTRANS_L2N)) & mask2;
1356                                  if ((vaddr_page >> ALPHA_TOPSHIFT) ==                                  x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1357                                      ALPHA_TOP_KERNEL) {                                      DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1358                                          vph_p = cpu->cd.alpha.                                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1359                                              vph_table0_kernel[a];                                  l3 = l2->l3[x2];
1360                                          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  */  
                                 fatal("Not yet for non-1-level, non-Alpha\n");  
 #endif  /*  !DYNTRANS_ALPHA  */  
1361  #endif  #endif
1362                          }                          }
1363                  }                  }
# Line 1097  void DYNTRANS_INVALIDATE_TC_CODE(struct Line 1376  void DYNTRANS_INVALIDATE_TC_CODE(struct
1376  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,  void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1377          unsigned char *host_page, int writeflag, uint64_t paddr_page)          unsigned char *host_page, int writeflag, uint64_t paddr_page)
1378  {  {
1379  #ifndef MODE32          int found, r, useraccess = 0;
         int64_t lowest, highest = -1;  
 #endif  
         int found, r, lowest_index, start, end, useraccess = 0;  
1380    
 #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  
1381  #ifdef MODE32  #ifdef MODE32
1382          uint32_t index;          uint32_t index;
1383          vaddr_page &= 0xffffffffULL;          vaddr_page &= 0xffffffffULL;
1384          paddr_page &= 0xffffffffULL;  
1385            if (paddr_page > 0xffffffffULL) {
1386                    fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1387                        " p=0x%016"PRIx64"\n", vaddr_page, host_page, writeflag,
1388                        paddr_page);
1389                    exit(1);
1390            }
1391    
1392          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"          /*  fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1393              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,              " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1394              (int)paddr_page);  */              (int)paddr_page);  */
1395  #else   /*  !MODE32  */  #else   /*  !MODE32  */
1396          fatal("Neither 32-bit nor Alpha? 2\n");          const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1397          exit(1);          const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1398  #endif          const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1399            uint32_t x1, x2, x3;
1400            struct DYNTRANS_L2_64_TABLE *l2;
1401            struct DYNTRANS_L3_64_TABLE *l3;
1402    
1403            /*  fatal("update_translation_table(): v=0x%016"PRIx64", h=%p w=%i"
1404                " p=0x%016"PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1405                (uint64_t)paddr_page);  */
1406  #endif  #endif
1407    
1408            assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1409            assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1410    
1411          if (writeflag & MEMORY_USER_ACCESS) {          if (writeflag & MEMORY_USER_ACCESS) {
1412                  writeflag &= ~MEMORY_USER_ACCESS;                  writeflag &= ~MEMORY_USER_ACCESS;
1413                  useraccess = 1;                  useraccess = 1;
1414          }          }
1415    
1416          start = 0; end = DYNTRANS_MAX_VPH_TLB_ENTRIES / 2;  #ifdef DYNTRANS_M88K
1417  #if 1          /*  TODO  */
1418          /*  Half of the TLB used for data, half for code:  */          if (useraccess)
1419          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;  
1420  #endif  #endif
1421    
1422          /*  Scan the current TLB entries:  */          /*  Scan the current TLB entries:  */
         lowest_index = start;  
1423    
1424  #ifdef MODE32  #ifdef MODE32
1425          /*          /*
# Line 1154  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1432  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1432           */           */
1433          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[          found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1434              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 ++;  
         }  
1435  #else  #else
1436          lowest = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[0].timestamp;          x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1437          found = -1;          x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1438          for (r=start; r<end; r++) {          x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1439                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp < lowest) {              & mask3;
1440                          lowest = cpu->cd.DYNTRANS_ARCH.  
1441                              vph_tlb_entry[r].timestamp;          l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1442                          lowest_index = r;          if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1443                  }                  found = -1;
1444                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp > highest)          else {
1445                          highest = cpu->cd.DYNTRANS_ARCH.                  l3 = l2->l3[x2];
1446                              vph_tlb_entry[r].timestamp;                  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1447                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&                          found = -1;
1448                      cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page ==                  else
1449                      vaddr_page) {                          found = (int)l3->vaddr_to_tlbindex[x3] - 1;
                         found = r;  
                         break;  
                 }  
1450          }          }
1451  #endif  #endif
1452    
1453          if (found < 0) {          if (found < 0) {
1454                  /*  Create the new TLB entry, overwriting the oldest one:  */                  /*  Create the new TLB entry, overwriting a "random" entry:  */
1455                  r = lowest_index;                  static unsigned int x = 0;
1456                    r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1457    
1458                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {                  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1459                          /*  This one has to be invalidated first:  */                          /*  This one has to be invalidated first:  */
1460                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,                          DYNTRANS_INVALIDATE_TLB_ENTRY(cpu,
# Line 1196  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1468  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1468                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1469                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =                  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1470                      writeflag & MEM_WRITE;                      writeflag & MEM_WRITE;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1471    
1472                  /*  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  
1473  #ifdef MODE32  #ifdef MODE32
1474                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1475                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;                  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
# Line 1250  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1483  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1483                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]                          cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1484                              |= 1 << (index & 31);                              |= 1 << (index & 31);
1485  #endif  #endif
1486  #endif  /*  32  */  #else   /* !MODE32  */
1487  #endif  /*  !ALPHA  */                  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1488                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1489                            if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1490                                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1491                                        cpu->cd.DYNTRANS_ARCH.next_free_l2;
1492                                    cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1493                            } else {
1494                                    int i;
1495                                    CHECK_ALLOCATION(l2 =
1496                                        cpu->cd.DYNTRANS_ARCH.l1_64[x1] = malloc(
1497                                        sizeof(struct DYNTRANS_L2_64_TABLE)));
1498                                    l2->refcount = 0;
1499                                    for (i=0; i<(1 << DYNTRANS_L2N); i++)
1500                                            l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1501                                                l3_64_dummy;
1502                            }
1503                            if (l2->refcount != 0) {
1504                                    fatal("Huh? l2 Refcount problem.\n");
1505                                    exit(1);
1506                            }
1507                    }
1508                    if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1509                            fatal("INTERNAL ERROR L2 reuse\n");
1510                            exit(1);
1511                    }
1512                    l3 = l2->l3[x2];
1513                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1514                            if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1515                                    l3 = l2->l3[x2] =
1516                                        cpu->cd.DYNTRANS_ARCH.next_free_l3;
1517                                    cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1518                            } else {
1519                                    l3 = l2->l3[x2] = zeroed_alloc(sizeof(
1520                                        struct DYNTRANS_L3_64_TABLE));
1521                            }
1522                            if (l3->refcount != 0) {
1523                                    fatal("Huh? l3 Refcount problem.\n");
1524                                    exit(1);
1525                            }
1526                            l2->refcount ++;
1527                    }
1528                    if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1529                            fatal("INTERNAL ERROR L3 reuse\n");
1530                            exit(1);
1531                    }
1532    
1533                    l3->host_load[x3] = host_page;
1534                    l3->host_store[x3] = writeflag? host_page : NULL;
1535                    l3->phys_addr[x3] = paddr_page;
1536                    l3->phys_page[x3] = NULL;
1537                    l3->vaddr_to_tlbindex[x3] = r + 1;
1538                    l3->refcount ++;
1539    
1540    #ifdef BUGHUNT
1541    /*  Count how many pages are actually in use:  */
1542    {
1543            int n=0, i;
1544            for (i=0; i<=mask3; i++)
1545                    if (l3->vaddr_to_tlbindex[i])
1546                            n++;
1547            if (n != l3->refcount) {
1548                    printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1549                    exit(1);
1550            }
1551    
1552            n = 0;
1553            for (i=0; i<=mask3; i++)
1554                    if (l3->host_load[i] != NULL)
1555                            n++;
1556            if (n != l3->refcount) {
1557                    printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1558                    exit(1);
1559            }
1560    }
1561    #endif
1562    
1563    #endif  /* !MODE32  */
1564          } else {          } else {
1565                  /*                  /*
1566                   *  The translation was already in the TLB.                   *  The translation was already in the TLB.
# Line 1260  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1569  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1569                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.                   *      Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1570                   */                   */
1571                  r = found;                  r = found;
 #ifndef MODE32  
                 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].timestamp = highest + 1;  
 #endif  
1572                  if (writeflag & MEM_WRITE)                  if (writeflag & MEM_WRITE)
1573                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;                          cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1574                  if (writeflag & MEM_DOWNGRADE)                  if (writeflag & MEM_DOWNGRADE)
1575                          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  
1576  #ifdef MODE32  #ifdef MODE32
1577                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);                  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1578                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;                  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
# Line 1310  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1595  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1595                              writeflag? host_page : NULL;                              writeflag? host_page : NULL;
1596                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;                          cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1597                  }                  }
1598  #endif  /*  32  */  #else   /*  !MODE32  */
1599  #endif  /*  !ALPHA  */                  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1600                    x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1601                    x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1602                        & mask3;
1603                    l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1604                    l3 = l2->l3[x2];
1605                    if (l3->phys_addr[x3] == paddr_page) {
1606                            if (writeflag & MEM_WRITE)
1607                                    l3->host_store[x3] = host_page;
1608                            if (writeflag & MEM_DOWNGRADE)
1609                                    l3->host_store[x3] = NULL;
1610                    } else {
1611                            /*  Change the entire physical/host mapping:  */
1612    printf("HOST LOAD 2 set to %p\n", host_page);
1613                            l3->host_load[x3] = host_page;
1614                            l3->host_store[x3] = writeflag? host_page : NULL;
1615                            l3->phys_addr[x3] = paddr_page;
1616                    }
1617    
1618    #ifdef BUGHUNT
1619    /*  Count how many pages are actually in use:  */
1620    {
1621            int n=0, i;
1622            for (i=0; i<=mask3; i++)
1623                    if (l3->vaddr_to_tlbindex[i])
1624                            n++;
1625            if (n != l3->refcount) {
1626                    printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1627                    exit(1);
1628            }
1629    
1630            n = 0;
1631            for (i=0; i<=mask3; i++)
1632                    if (l3->host_load[i] != NULL)
1633                            n++;
1634            if (n != l3->refcount) {
1635                    printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1636                    printf("Entry r = %i\n", r);
1637                    printf("Valid = %i\n",
1638    cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1639                    exit(1);
1640            }
1641    }
1642    #endif
1643    
1644    #endif  /*  !MODE32  */
1645          }          }
1646  }  }
1647  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */  #endif  /*  DYNTRANS_UPDATE_TRANSLATION_TABLE  */
# Line 1324  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1654  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1654          /*          /*
1655           *  Check for breakpoints.           *  Check for breakpoints.
1656           */           */
1657          if (!single_step_breakpoint) {          if (!single_step_breakpoint && !cpu->translation_readahead) {
1658  #ifdef MODE32                  MODE_uint_t curpc = cpu->pc;
                 uint32_t curpc = cpu->pc;  
 #else  
                 uint64_t curpc = cpu->pc;  
 #endif  
1659                  int i;                  int i;
1660                  for (i=0; i<cpu->machine->n_breakpoints; i++)                  for (i=0; i<cpu->machine->breakpoints.n; i++)
1661                          if (curpc ==                          if (curpc == (MODE_uint_t)
1662  #ifdef MODE32                              cpu->machine->breakpoints.addr[i]) {
                             (uint32_t)  
 #endif  
                             cpu->machine->breakpoint_addr[i]) {  
1663                                  if (!cpu->machine->instruction_trace) {                                  if (!cpu->machine->instruction_trace) {
1664                                          int old_quiet_mode = quiet_mode;                                          int old_quiet_mode = quiet_mode;
1665                                          quiet_mode = 0;                                          quiet_mode = 0;
1666                                          DISASSEMBLE(cpu, ib, 1, 0, 0);                                          DISASSEMBLE(cpu, ib, 1, 0);
1667                                          quiet_mode = old_quiet_mode;                                          quiet_mode = old_quiet_mode;
1668                                  }                                  }
1669                                  fatal("BREAKPOINT: pc = 0x%llx\n(The "  #ifdef MODE32
1670                                    fatal("BREAKPOINT: pc = 0x%"PRIx32"\n(The "
1671                                        "instruction has not yet executed.)\n",
1672                                        (uint32_t)cpu->pc);
1673    #else
1674                                    fatal("BREAKPOINT: pc = 0x%"PRIx64"\n(The "
1675                                      "instruction has not yet executed.)\n",                                      "instruction has not yet executed.)\n",
1676                                      (long long)cpu->pc);                                      (uint64_t)cpu->pc);
1677    #endif
1678  #ifdef DYNTRANS_DELAYSLOT  #ifdef DYNTRANS_DELAYSLOT
1679                                  if (cpu->cd.DYNTRANS_ARCH.delay_slot !=                                  if (cpu->delay_slot != NOT_DELAYED)
                                     NOT_DELAYED)  
1680                                          fatal("ERROR! Breakpoint in a delay"                                          fatal("ERROR! Breakpoint in a delay"
1681                                              " slot! Not yet supported.\n");                                              " slot! Not yet supported.\n");
1682  #endif  #endif
1683                                  single_step_breakpoint = 1;                                  single_step_breakpoint = 1;
1684                                  single_step = 1;                                  single_step = ENTER_SINGLE_STEPPING;
1685                                  goto stop_running_translated;                                  goto stop_running_translated;
1686                          }                          }
1687          }          }
# Line 1365  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s Line 1693  void DYNTRANS_UPDATE_TRANSLATION_TABLE(s
1693    
1694  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL  #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1695          /*          /*
1696           *  If we end up here, then an instruction was translated.           *  If we end up here, then an instruction was translated. Let's mark
1697           *  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.)  
1698           */           */
1699  #ifdef MODE32  
1700          if (!(cpu->cd.DYNTRANS_ARCH.cur_physpage->flags & TRANSLATIONS)) {          /*  Make sure cur_physpage is in synch:  */
1701                  uint32_t index = DYNTRANS_ADDR_TO_PAGENR((uint32_t)addr);          cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)
1702                  cpu->cd.DYNTRANS_ARCH.phystranslation[index >> 5] |=              cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1703                      (1 << (index & 31));  
1704            {
1705                    int x = addr & (DYNTRANS_PAGESIZE - 1);
1706                    int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1707                        sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->
1708                        translations_bitmap));
1709                    x /= addr_per_translation_range;
1710    
1711                    cpu->cd.DYNTRANS_ARCH.cur_physpage->
1712                        translations_bitmap |= (1 << x);
1713          }          }
 #endif  
         cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= TRANSLATIONS;  
1714    
1715    
 #ifdef DYNTRANS_BACKEND  
1716          /*          /*
1717           *  "Empty"/simple native dyntrans backend stuff:           *  Now it is time to check for combinations of instructions that can
1718           *           *  be converted into a single function call.
          *  1) If no translation is currently being done, but the translated  
          *     instruction was simple enough, then let's start making a new  
          *     native translation block.  
          *  
          *  2) If a native translation block is currently being constructed,  
          *     but this instruction wasn't simple enough, then end the block  
          *     (without including this instruction).  
1719           *           *
1720           *  3) If a native translation block is currently being constructed,           *  Note: Single-stepping or instruction tracing doesn't work with
1721           *     and this is a simple instruction, then add it.           *  instruction combinations. For architectures with delay slots,
1722             *  we also ignore combinations if the delay slot is across a page
1723             *  boundary.
1724           */           */
1725          if (simple && cpu->translation_context.p == NULL &&          if (!single_step && !cpu->machine->instruction_trace
1726              dyntrans_backend_enable) {  #ifdef DYNTRANS_DELAYSLOT
1727                  size_t s = 0;              && !in_crosspage_delayslot
1728    #endif
1729                && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1730                && cpu->machine->allow_instruction_combinations) {
1731                    cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1732                        addr & (DYNTRANS_PAGESIZE - 1));
1733            }
1734    
1735                  if (cpu->translation_context.translation_buffer == NULL) {          cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
                         cpu->translation_context.translation_buffer =  
                             zeroed_alloc(DTB_TRANSLATION_SIZE_MAX +  
                             DTB_TRANSLATION_SIZE_MARGIN);  
                 }  
1736    
1737                  cpu->translation_context.p =          /*  An additional check, to catch some bugs:  */
1738                      cpu->translation_context.translation_buffer;          if (ic->f == TO_BE_TRANSLATED) {
1739                    fatal("INTERNAL ERROR: ic->f not set!\n");
1740                    goto bad;
1741            }
1742            if (ic->f == NULL) {
1743                    fatal("INTERNAL ERROR: ic->f == NULL!\n");
1744                    goto bad;
1745            }
1746    
                 cpu->translation_context.ic_page =  
                     cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
                 cpu->translation_context.start_instr_call_index =  
                     ((size_t)ic - (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page)  
                     / (sizeof(*ic));  
1747    
1748                  dtb_function_prologue(&cpu->translation_context, &s);          /*
1749                  cpu->translation_context.p += s;           *  ... and finally execute the translated instruction:
1750                  cpu->translation_context.n_simple = 0;           */
1751    
1752            /*  (Except when doing read-ahead!)  */
1753            if (cpu->translation_readahead)
1754                    return;
1755    
1756            /*
1757             *  Special case when single-stepping: Execute the translated
1758             *  instruction, but then replace it with a "to be translated"
1759             *  directly afterwards.
1760             */
1761            if ((single_step_breakpoint && cpu->delay_slot == NOT_DELAYED)
1762    #ifdef DYNTRANS_DELAYSLOT
1763                || in_crosspage_delayslot
1764    #endif
1765                ) {
1766                    single_step_breakpoint = 0;
1767                    ic->f(cpu, ic);
1768                    ic->f = TO_BE_TRANSLATED;
1769                    return;
1770          }          }
1771    
1772          /*  If this is not a continuation of a simple translation, then          /*  Translation read-ahead:  */
1773              stop now!  */          if (!single_step && !cpu->machine->instruction_trace) {
1774          if (cpu->translation_context.ic_page != cpu->cd.DYNTRANS_ARCH.                  uint64_t baseaddr = cpu->pc;
1775              cur_ic_page || ic != &cpu->cd.DYNTRANS_ARCH.cur_ic_page[                  uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(baseaddr);
1776              cpu->translation_context.start_instr_call_index +                  int i = 1;
1777              cpu->translation_context.n_simple])  
1778                  simple = 0;                  cpu->translation_readahead = MAX_DYNTRANS_READAHEAD;
1779    
1780                    while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1781                        (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1782                        cpu->translation_readahead > 0) {
1783                            void (*old_f)(struct cpu *,
1784                                struct DYNTRANS_IC *) = ic[i].f;
1785    
1786          if (cpu->translation_context.p != NULL && !simple) {                          /*  Already translated? Then abort:  */
1787                  size_t s = 0, total;                          if (old_f != TO_BE_TRANSLATED)
1788                                    break;
1789    
1790                  if (cpu->translation_context.n_simple > 1) {                          /*  Translate the instruction:  */
1791                          dtb_generate_ptr_inc(cpu, &cpu->translation_context,                          ic[i].f(cpu, ic+i);
                             &s, &cpu->cd.DYNTRANS_ARCH.next_ic,  
                             (cpu->translation_context.n_simple - 1) *  
                             sizeof(*(cpu->cd.DYNTRANS_ARCH.next_ic)));  
                         cpu->translation_context.p += s;  
                 }  
1792    
1793                  dtb_function_epilogue(&cpu->translation_context, &s);                          /*  Translation failed? Then abort.  */
1794                  cpu->translation_context.p += s;                          if (ic[i].f == old_f)
1795                                    break;
1796    
1797                  cpu_dtb_do_fixups(cpu);                          cpu->translation_readahead --;
1798  #if 0                          ++i;
1799  {                  }
 int i;  
 unsigned char *addr = cpu->translation_context.translation_buffer;  
 printf("index = %i\n", cpu->translation_context.start_instr_call_index);  
 quiet_mode = 0;  
 for (i=0; i<4*32; i+=4)  
         alpha_cpu_disassemble_instr(cpu, (unsigned char *)addr + i,  
         0, i, 0);  
 }  
 #endif  
                 total = (size_t)cpu->translation_context.p -  
                     (size_t)cpu->translation_context.translation_buffer;  
1800    
1801                  /*  Copy the translated block to the translation cache:  */                  cpu->translation_readahead = 0;
                 /*  Align first:  */  
                 cpu->translation_cache_cur_ofs --;  
                 cpu->translation_cache_cur_ofs |= 31;  
                 cpu->translation_cache_cur_ofs ++;  
   
                 memcpy(cpu->translation_cache + cpu->translation_cache_cur_ofs,  
                     cpu->translation_context.translation_buffer, total);  
   
                 /*  Set the ic pointer:  */  
                 ((struct DYNTRANS_IC *)cpu->translation_context.ic_page)  
                     [cpu->translation_context.start_instr_call_index].f =  
                     (void *)  
                     (cpu->translation_cache + cpu->translation_cache_cur_ofs);  
   
                 /*  Align cur_ofs afterwards as well, just to be safe.  */  
                 cpu->translation_cache_cur_ofs += total;  
                 cpu->translation_cache_cur_ofs --;  
                 cpu->translation_cache_cur_ofs |= 31;  
                 cpu->translation_cache_cur_ofs ++;  
   
                 /*  Set the "combined instruction" flag for this page:  */  
                 cpu->cd.DYNTRANS_ARCH.cur_physpage = (void *)  
                     cpu->cd.DYNTRANS_ARCH.cur_ic_page;  
                 cpu->cd.DYNTRANS_ARCH.cur_physpage->flags |= COMBINATIONS;  
   
                 dtb_host_cacheinvalidate(0,0); /* p , size ... ); */  
   
                 cpu->translation_context.p = NULL;  
         }  
         if (cpu->translation_context.p != NULL) {  
                 size_t s = 0;  
                 dtb_generate_fcall(cpu, &cpu->translation_context,  
                     &s, (size_t)ic->f, (size_t)ic);  
                 cpu->translation_context.p += s;  
                 cpu->translation_context.n_simple ++;  
1802          }          }
 #endif  /*  DYNTRANS_BACKEND  */  
1803    
1804    
1805          /*          /*
1806           *  Now it is time to check for combinations of instructions that can           *  Finally finally :-), execute the instruction.
          *  be converted into a single function call.  
1807           *           *
1808           *  Note: Single-stepping or instruction tracing doesn't work with           *  Note: The instruction might have changed during read-ahead, if
1809           *  instruction combination.           *  instruction combinations are used.
1810           */           */
         if (!single_step && !cpu->machine->instruction_trace) {  
                 if (cpu->cd.DYNTRANS_ARCH.combination_check != NULL &&  
                     cpu->machine->speed_tricks)  
                         cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,  
                             addr & (DYNTRANS_PAGESIZE - 1));  
                 cpu->cd.DYNTRANS_ARCH.combination_check = NULL;  
         }  
1811    
1812          /*  ... and finally execute the translated instruction:  */          ic->f(cpu, ic);
         if (single_step_breakpoint) {  
                 /*  
                  *  Special case when single-stepping: Execute the translated  
                  *  instruction, but then replace it with a "to be translated"  
                  *  directly afterwards.  
                  */  
                 single_step_breakpoint = 0;  
                 ic->f(cpu, ic);  
                 ic->f =  
 #ifdef DYNTRANS_DUALMODE_32  
                     cpu->is_32bit? instr32(to_be_translated) :  
 #endif  
                     instr(to_be_translated);  
         } else  
                 ic->f(cpu, ic);  
1813    
1814          return;          return;
1815    
# Line 1536  bad:   /* Line 1818  bad:   /*
1818           *  Nothing was translated. (Unimplemented or illegal instruction.)           *  Nothing was translated. (Unimplemented or illegal instruction.)
1819           */           */
1820    
1821            /*  Clear the translation, in case it was "half-way" done:  */
1822            ic->f = TO_BE_TRANSLATED;
1823    
1824            if (cpu->translation_readahead)
1825                    return;
1826    
1827          quiet_mode = 0;          quiet_mode = 0;
1828          fatal("to_be_translated(): TODO: unimplemented instruction");          fatal("to_be_translated(): TODO: unimplemented instruction");
1829    
1830          if (cpu->machine->instruction_trace)          if (cpu->machine->instruction_trace) {
1831  #ifdef MODE32                  if (cpu->is_32bit)
1832                  fatal(" at 0x%x\n", (int)cpu->pc);                          fatal(" at 0x%"PRIx32"\n", (uint32_t)cpu->pc);
1833  #else                  else
1834                  fatal(" at 0x%llx\n", (long long)cpu->pc);                          fatal(" at 0x%"PRIx64"\n", (uint64_t)cpu->pc);
1835  #endif          } else {
         else {  
1836                  fatal(":\n");                  fatal(":\n");
1837                  DISASSEMBLE(cpu, ib, 1, 0, 0);                  DISASSEMBLE(cpu, ib, 1, 0);
1838          }          }
1839    
1840          cpu->running = 0;          cpu->running = 0;
1841          cpu->dead = 1;  
1842            /*  Note: Single-stepping can jump here.  */
1843  stop_running_translated:  stop_running_translated:
1844    
1845          debugger_n_steps_left_before_interaction = 0;          debugger_n_steps_left_before_interaction = 0;
1846          cpu->running_translated = 0;  
1847          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;          ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1848          cpu->cd.DYNTRANS_ARCH.next_ic ++;          cpu->cd.DYNTRANS_ARCH.next_ic ++;
1849    
1850    #ifdef DYNTRANS_DELAYSLOT
1851            /*  Special hack: If the bad instruction was in a delay slot,
1852                make sure that execution does not continue anyway:  */
1853            if (cpu->delay_slot)
1854                    cpu->delay_slot |= EXCEPTION_IN_DELAY_SLOT;
1855    #endif
1856    
1857          /*  Execute the "nothing" instruction:  */          /*  Execute the "nothing" instruction:  */
1858          ic->f(cpu, ic);          ic->f(cpu, ic);
1859    
1860  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */  #endif  /*  DYNTRANS_TO_BE_TRANSLATED_TAIL  */
1861    

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

  ViewVC Help
Powered by ViewVC 1.1.26