cpu_dyntrans.cc Source File

Back to the index.

cpu_dyntrans.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2018 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * Common dyntrans routines. Included from cpu_*.c.
29  *
30  * Note: This might be a bit hard to follow, if you are reading this source
31  * code for the first time. It is basically a hack to implement "templates"
32  * with normal C code, by using suitable defines/macros, and then including
33  * this file.
34  */
35 
36 
37 #ifndef STATIC_STUFF
38 #define STATIC_STUFF
39 /*
40  * gather_statistics():
41  */
42 static void gather_statistics(struct cpu *cpu)
43 {
44  char ch, buf[60];
45  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
46  int i = 0;
47  uint64_t a;
48  int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
49  cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
50 
51  if (cpu->machine->statistics.file == NULL) {
52  fatal("statistics gathering with no filename set is"
53  " meaningless\n");
54  return;
55  }
56 
57  /* low_pc must be within the page! */
58  if (low_pc < 0 || low_pc > DYNTRANS_IC_ENTRIES_PER_PAGE)
59  return;
60 
61  buf[0] = '\0';
62 
63  while ((ch = cpu->machine->statistics.fields[i]) != '\0') {
64  if (i != 0)
65  strlcat(buf, " ", sizeof(buf));
66 
67  switch (ch) {
68  case 'i':
69  snprintf(buf + strlen(buf), sizeof(buf),
70  "%p", (void *)ic->f);
71  break;
72  case 'p':
73  /* Physical program counter address: */
74  cpu->cd.DYNTRANS_ARCH.cur_physpage = (struct DYNTRANS_TC_PHYSPAGE *)
75  cpu->cd.DYNTRANS_ARCH.cur_ic_page;
76  a = cpu->cd.DYNTRANS_ARCH.cur_physpage->physaddr;
77  a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
79  a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
80  if (cpu->is_32bit)
81  snprintf(buf + strlen(buf), sizeof(buf),
82  "0x%08" PRIx32, (uint32_t)a);
83  else
84  snprintf(buf + strlen(buf), sizeof(buf),
85  "0x%016" PRIx64, (uint64_t)a);
86  break;
87  case 'v':
88  /* Virtual program counter address: */
89  a = cpu->pc;
90  a &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
91  DYNTRANS_INSTR_ALIGNMENT_SHIFT);
92  a += low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT;
93  if (cpu->is_32bit)
94  snprintf(buf + strlen(buf), sizeof(buf),
95  "0x%08" PRIx32, (uint32_t)a);
96  else
97  snprintf(buf + strlen(buf), sizeof(buf),
98  "0x%016" PRIx64, (uint64_t)a);
99  break;
100  }
101  i++;
102  }
103 
104  fprintf(cpu->machine->statistics.file, "%s\n", buf);
105 }
106 
107 
108 #define S gather_statistics(cpu)
109 
110 
111 #if 1
112 
113 /* The normal instruction execution core: */
114 #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic);
115 
116 #else
117 
118 /* For heavy debugging: */
119 #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \
120  { \
121  int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
122  (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
123  sizeof(struct DYNTRANS_IC); \
124  printf("cur_ic_page=%p ic=%p (low_pc=0x%x)\n", \
125  cpu->cd.DYNTRANS_ARCH.cur_ic_page, \
126  ic, low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
127  } \
128  ic->f(cpu, ic);
129 
130 #endif
131 
132 /* static long long nr_of_I_calls = 0; */
133 
134 /* Temporary hack for finding NULL bugs: */
135 /* #define I ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; \
136  nr_of_I_calls ++; \
137  if (ic->f == NULL) { \
138  int low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - \
139  (size_t)cpu->cd.DYNTRANS_ARCH.cur_ic_page) / \
140  sizeof(struct DYNTRANS_IC); \
141  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) << \
142  DYNTRANS_INSTR_ALIGNMENT_SHIFT); \
143  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);\
144  printf("Crash at %016" PRIx64"\n", cpu->pc); \
145  printf("nr of I calls: %lli\n", nr_of_I_calls); \
146  printf("Next ic = %p\n", cpu->cd. \
147  DYNTRANS_ARCH.next_ic); \
148  printf("cur ic page = %p\n", cpu->cd. \
149  DYNTRANS_ARCH.cur_ic_page); \
150  cpu->running = 0; \
151  return 0; \
152  } \
153  ic->f(cpu, ic); */
154 
155 /* Temporary hack for MIPS, to hunt for 32-bit/64-bit sign-extension bugs: */
156 /* #define I { int k; for (k=1; k<=31; k++) \
157  cpu->cd.mips.gpr[k] = (int32_t)cpu->cd.mips.gpr[k];\
158  if (cpu->cd.mips.gpr[0] != 0) { \
159  fatal("NOOOOOO\n"); exit(1); \
160  } \
161  ic = cpu->cd.DYNTRANS_ARCH.next_ic ++; ic->f(cpu, ic); }
162 */
163 #endif /* STATIC STUFF */
164 
165 
166 
167 #ifdef DYNTRANS_RUN_INSTR_DEF
168 /*
169  * XXX_run_instr():
170  *
171  * Execute one or more instructions on a specific CPU, using dyntrans.
172  * (For dualmode archs, this function is included twice.)
173  *
174  * Return value is the number of instructions executed during this call,
175  * 0 if no instructions were executed.
176  */
177 int DYNTRANS_RUN_INSTR_DEF(struct cpu *cpu)
178 {
179  MODE_uint_t cached_pc;
180  int low_pc, n_instrs;
181 
182  /* Ugly... fix this some day. */
183 #ifdef DYNTRANS_DUALMODE_32
184 #ifdef MODE32
185  DYNTRANS_PC_TO_POINTERS32(cpu);
186 #else
188 #endif
189 #else
191 #endif
192 
193  /*
194  * Interrupt assertion? (This is _below_ the initial PC to pointer
195  * conversion; if the conversion caused an exception of some kind
196  * then interrupts are probably disabled, and the exception will get
197  * priority over device interrupts.)
198  *
199  * TODO: Turn this into a family-specific function somewhere...
200  */
201 
202  /* Note: Do not cause interrupts while single-stepping. It is
203  so horribly annoying. */
204  if (!single_step) {
205 #ifdef DYNTRANS_ARM
206  if (cpu->cd.arm.irq_asserted && !(cpu->cd.arm.cpsr & ARM_FLAG_I))
208 #endif
209 #ifdef DYNTRANS_M88K
210  if (cpu->cd.m88k.irq_asserted &&
211  !(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_IND))
213 #endif
214 #ifdef DYNTRANS_MIPS
215  int enabled, mask;
216  int status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
217  if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
218  /* R3000: */
219  enabled = status & MIPS_SR_INT_IE;
220  } else {
221  /* R4000 and others: */
222  enabled = (status & STATUS_IE)
223  && !(status & STATUS_EXL) && !(status & STATUS_ERL);
224  /* Special case for R5900/C790/TX79: */
225  if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
226  !(status & R5900_STATUS_EIE))
227  enabled = 0;
228  }
229  mask = status & cpu->cd.mips.coproc[0]->reg[COP0_CAUSE]
230  & STATUS_IM_MASK;
231 
232  if (enabled && mask)
233  mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0,0);
234 #endif
235 #ifdef DYNTRANS_PPC
236  if (cpu->cd.ppc.dec_intr_pending && cpu->cd.ppc.msr & PPC_MSR_EE) {
237  if (!(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
239  cpu->cd.ppc.dec_intr_pending = 0;
240  }
241  if (cpu->cd.ppc.irq_asserted && cpu->cd.ppc.msr & PPC_MSR_EE)
243 #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 
252 #ifdef DYNTRANS_ARM
253  if (cpu->cd.arm.cpsr & ARM_FLAG_T) {
254  fatal("THUMB execution not implemented.\n");
255  cpu->running = false;
256  return 0;
257  }
258 #endif
259 
260  cached_pc = cpu->pc;
261 
262  cpu->n_translated_instrs = 0;
263 
264  cpu->cd.DYNTRANS_ARCH.cur_physpage = (struct DYNTRANS_TC_PHYSPAGE *)
265  cpu->cd.DYNTRANS_ARCH.cur_ic_page;
266 
268  || cpu->machine->register_dump) {
269  /*
270  * Single-step:
271  */
272  struct DYNTRANS_IC *ic = cpu->cd.DYNTRANS_ARCH.next_ic;
273  if (cpu->machine->register_dump) {
274  debug("\n");
275  cpu_register_dump(cpu->machine, cpu, 1, 0x1);
276  }
277  if (cpu->machine->instruction_trace) {
278  /* TODO/Note: This must be large enough to hold
279  any instruction for any ISA: */
280  unsigned char instr[1 <<
282  if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
283  sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
284  fatal("XXX_run_instr(): could not read "
285  "the instruction\n");
286  } else {
287 #ifdef DYNTRANS_DELAYSLOT
288  int len =
289 #endif
291  cpu->machine, cpu, instr, 1, 0);
292 #ifdef DYNTRANS_DELAYSLOT
293  /* Show the instruction in the delay slot,
294  if any: */
295  if (cpu->instruction_has_delayslot == NULL)
296  fatal("WARNING: ihd func not yet"
297  " implemented?\n");
298  else if (cpu->instruction_has_delayslot(cpu,
299  instr)) {
300  int saved_delayslot = cpu->delay_slot;
301  cpu->memory_rw(cpu, cpu->mem, cached_pc
302  + len, &instr[0],
303  sizeof(instr), MEM_READ,
305  cpu->delay_slot = DELAYED;
306  cpu->pc += len;
308  cpu, instr, 1, 0);
309  cpu->delay_slot = saved_delayslot;
310  cpu->pc -= len;
311  }
312 #endif
313  }
314  }
315 
316  if (cpu->machine->statistics.enabled)
317  S;
318 
319  /* Execute just one instruction: */
320  I;
321 
322  n_instrs = 1;
323  } else if (cpu->machine->statistics.enabled) {
324  /* Gather statistics while executing multiple instructions: */
325  n_instrs = 0;
326  for (;;) {
327  struct DYNTRANS_IC *ic;
328 
329  S; I; S; I; S; I; S; I; S; I; S; I;
330  S; I; S; I; S; I; S; I; S; I; S; I;
331  S; I; S; I; S; I; S; I; S; I; S; I;
332  S; I; S; I; S; I; S; I; S; I; S; I;
333 
334  n_instrs += 24;
335 
336  if (n_instrs + cpu->n_translated_instrs >=
338  break;
339  }
340  } else {
341  /*
342  * Execute multiple instructions:
343  *
344  * (This is the core dyntrans loop.)
345  */
346  n_instrs = 0;
347 
348  for (;;) {
349  struct DYNTRANS_IC *ic;
350 
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  I; I; I; I; I; I; I; I; I; I;
356 
357  I; I; I; I; I; I; I; I; I; I;
358 
359  I; I; I; I; I; I; I; I; I; I;
360  I; I; I; I; I; I; I; I; I; I;
361  I; I; I; I; I; I; I; I; I; I;
362  I; I; I; I; I; I; I; I; I; I;
363  I; I; I; I; I; I; I; I; I; I;
364 
365  I; I; I; I; I; I; I; I; I; I;
366 
367  cpu->n_translated_instrs += 120;
369  break;
370  }
371  }
372 
373  n_instrs += cpu->n_translated_instrs;
374 
375  /* Synchronize the program counter: */
376  low_pc = ((size_t)cpu->cd.DYNTRANS_ARCH.next_ic - (size_t)
377  cpu->cd.DYNTRANS_ARCH.cur_ic_page) / sizeof(struct DYNTRANS_IC);
378  if (low_pc >= 0 && low_pc < DYNTRANS_IC_ENTRIES_PER_PAGE) {
379  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
381  cpu->pc += (low_pc << DYNTRANS_INSTR_ALIGNMENT_SHIFT);
382  } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE) {
383  /* Switch to next page: */
384  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
386  cpu->pc += (DYNTRANS_IC_ENTRIES_PER_PAGE <<
388  } else if (low_pc == DYNTRANS_IC_ENTRIES_PER_PAGE + 1) {
389  /* Switch to next page and skip an instruction which was
390  already executed (in a delay slot): */
391  cpu->pc &= ~((DYNTRANS_IC_ENTRIES_PER_PAGE-1) <<
393  cpu->pc += ((DYNTRANS_IC_ENTRIES_PER_PAGE + 1) <<
395  }
396 
397 #ifdef DYNTRANS_MIPS
398  /* Update the count register (on everything except EXC3K): */
399  if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
400  uint32_t old;
401  int32_t diff1, diff2;
404  old = cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
405  diff1 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] - old;
406  cpu->cd.mips.coproc[0]->reg[COP0_COUNT] =
407  (int32_t) (old + n_instrs);
408  diff2 = cpu->cd.mips.coproc[0]->reg[COP0_COMPARE] -
409  cpu->cd.mips.coproc[0]->reg[COP0_COUNT];
410 
411  if (cpu->cd.mips.compare_register_set) {
412 #if 1
413 /* Not yet. TODO */
414  if (cpu->machine->emulated_hz > 0) {
415  if (cpu->cd.mips.compare_interrupts_pending > 0)
417  cpu->cd.mips.irq_compare);
418  } else
419 #endif
420  {
421  if (diff1 > 0 && diff2 <= 0)
423  cpu->cd.mips.irq_compare);
424  }
425  }
426  }
427 #endif
428 #ifdef DYNTRANS_PPC
429  /* Update the Decrementer and Time base registers: */
430  {
431  uint32_t old = cpu->cd.ppc.spr[SPR_DEC];
432  cpu->cd.ppc.spr[SPR_DEC] = (uint32_t) (old - n_instrs);
433  if ((old >> 31) == 0 && (cpu->cd.ppc.spr[SPR_DEC] >> 31) == 1
434  && !(cpu->cd.ppc.cpu_type.flags & PPC_NO_DEC))
435  cpu->cd.ppc.dec_intr_pending = 1;
436  old = cpu->cd.ppc.spr[SPR_TBL];
437  cpu->cd.ppc.spr[SPR_TBL] += n_instrs;
438  if ((old >> 31) == 1 && (cpu->cd.ppc.spr[SPR_TBL] >> 31) == 0)
439  cpu->cd.ppc.spr[SPR_TBU] ++;
440  }
441 #endif
442 
443  cpu->ninstrs += n_instrs;
444 
445  /* Return the nr of instructions executed: */
446  return n_instrs;
447 }
448 #endif /* DYNTRANS_RUN_INSTR */
449 
450 
451 
452 #ifdef DYNTRANS_FUNCTION_TRACE_DEF
453 /*
454  * XXX_cpu_functioncall_trace():
455  *
456  * Without this function, the main trace tree function prints something
457  * like <f()> or <0x1234()> on a function call. It is up to this
458  * function to print the arguments passed.
459  */
460 void DYNTRANS_FUNCTION_TRACE_DEF(struct cpu *cpu, int n_args)
461 {
462  int show_symbolic_function_name = 1;
463  char strbuf[50];
464  char *symbol;
465  uint64_t ot;
466  int x, print_dots = 1, n_args_to_print =
467 #if defined(DYNTRANS_ALPHA)
468  6
469 #else
470 #if defined(DYNTRANS_SH) || defined(DYNTRANS_M88K)
471  8 /* Both for 32-bit and 64-bit SuperH, and M88K */
472 #else
473  4 /* Default value for most archs */
474 #endif
475 #endif
476  ;
477 
478  if (n_args >= 0 && n_args <= n_args_to_print) {
479  print_dots = 0;
480  n_args_to_print = n_args;
481  }
482 
483 #ifdef DYNTRANS_M88K
484  /* Special hack for M88K userspace: */
485  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
486  show_symbolic_function_name = 0;
487 #endif
488 
489 
490  /*
491  * TODO: The type of each argument should be taken from the symbol
492  * table, in some way.
493  *
494  * The code here does a kind of "heuristic guess" regarding what the
495  * argument values might mean. Sometimes the output looks weird, but
496  * usually it looks good enough.
497  *
498  * Print ".." afterwards to show that there might be more arguments
499  * than were passed in register.
500  */
501  for (x=0; x<n_args_to_print; x++) {
502  int64_t d = cpu->cd.DYNTRANS_ARCH.
503 #ifdef DYNTRANS_ALPHA
504  r[ALPHA_A0
505 #endif
506 #ifdef DYNTRANS_ARM
507  r[0
508 #endif
509 #ifdef DYNTRANS_MIPS
510  gpr[MIPS_GPR_A0
511 #endif
512 #ifdef DYNTRANS_M88K
513  r[2 /* r2..r9 */
514 #endif
515 #ifdef DYNTRANS_PPC
516  gpr[3
517 #endif
518 #ifdef DYNTRANS_SH
519  r[4 /* NetBSD seems to use 4? But 2 seems
520  to be used by other code? TODO */
521 #endif
522  + x];
523 
524  symbol = get_symbol_name(&cpu->machine->symbol_context, d, &ot);
525 
526  if (d > -256 && d < 256)
527  fatal("%i", (int)d);
528  else if (memory_points_to_string(cpu, cpu->mem, d, 1))
529  fatal("\"%s\"", memory_conv_to_string(cpu,
530  cpu->mem, d, strbuf, sizeof(strbuf)));
531  else if (symbol != NULL && ot == 0 &&
532  show_symbolic_function_name)
533  fatal("&%s", symbol);
534  else {
535  if (cpu->is_32bit)
536  fatal("0x%" PRIx32, (uint32_t)d);
537  else
538  fatal("0x%" PRIx64, (uint64_t)d);
539  }
540 
541  if (x < n_args_to_print - 1)
542  fatal(",");
543  }
544 
545  if (print_dots)
546  fatal(",..");
547 }
548 #endif /* DYNTRANS_FUNCTION_TRACE_DEF */
549 
550 
551 
552 #ifdef DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF
553 /*
554  * XXX_tc_allocate_default_page():
555  *
556  * Create a default page (with just pointers to instr(to_be_translated)
557  * at cpu->translation_cache_cur_ofs.
558  */
559 static void DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF(struct cpu *cpu,
560  uint64_t physaddr)
561 {
562  struct DYNTRANS_TC_PHYSPAGE *ppp;
563 
564  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
566 
567  /* Copy the entire template page first: */
568  memcpy(ppp, cpu->cd.DYNTRANS_ARCH.physpage_template, sizeof(
569  struct DYNTRANS_TC_PHYSPAGE));
570 
571  ppp->physaddr = physaddr & ~(DYNTRANS_PAGESIZE - 1);
572 
573  cpu->translation_cache_cur_ofs += sizeof(struct DYNTRANS_TC_PHYSPAGE);
574 
576  cpu->translation_cache_cur_ofs |= 63;
578 }
579 #endif /* DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF */
580 
581 
582 
583 #ifdef DYNTRANS_PC_TO_POINTERS_FUNC
584 /*
585  * XXX_pc_to_pointers_generic():
586  *
587  * Generic case. See DYNTRANS_PC_TO_POINTERS_FUNC below.
588  */
589 void DYNTRANS_PC_TO_POINTERS_GENERIC(struct cpu *cpu)
590 {
591 #ifdef MODE32
592  uint32_t
593 #else
594  uint64_t
595 #endif
596  cached_pc = cpu->pc, physaddr = 0;
597  uint32_t physpage_ofs;
598  int ok, pagenr, table_index;
599  uint32_t *physpage_entryp;
600  struct DYNTRANS_TC_PHYSPAGE *ppp;
601 
602 #ifdef MODE32
603  int index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
604 #else
605  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
606  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
607  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
608  uint32_t x1, x2, x3;
609  struct DYNTRANS_L2_64_TABLE *l2;
610  struct DYNTRANS_L3_64_TABLE *l3;
611 
612  x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
613  x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
614  x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
615  /* fatal("X3: cached_pc=%016" PRIx64" x1=%x x2=%x x3=%x\n",
616  (uint64_t)cached_pc, (int)x1, (int)x2, (int)x3); */
617  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
618  /* fatal(" l2 = %p\n", l2); */
619  l3 = l2->l3[x2];
620  /* fatal(" l3 = %p\n", l3); */
621 #endif
622 
623  /* Virtual to physical address translation: */
624  ok = 0;
625 #ifdef MODE32
626  if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
627  physaddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
628  ok = 1;
629  }
630 #else
631  if (l3->host_load[x3] != NULL) {
632  physaddr = l3->phys_addr[x3];
633  ok = 1;
634  }
635 #endif
636 
637  if (!ok) {
638  uint64_t paddr;
639  if (cpu->translate_v2p != NULL) {
640  uint64_t vaddr =
641 #if defined(MODE32) && defined(DYNTRANS_MIPS)
642  /* 32-bit MIPS is _sign_ extend, not zero. */
643  (int32_t)
644 #endif
645  cached_pc;
646  ok = cpu->translate_v2p(
647  cpu, vaddr, &paddr, FLAG_INSTR);
648  } else {
649  paddr = cached_pc;
650  ok = 1;
651  }
652  if (!ok) {
653  /*
654  * The PC is now set to the exception handler.
655  * Try to find the paddr in the translation arrays,
656  * or if that fails, call translate_v2p for the
657  * exception handler.
658  */
659  /* fatal("TODO: instruction vaddr=>paddr translation "
660  "failed. vaddr=0x%" PRIx64"\n", (uint64_t)cached_pc);
661  fatal("!! cpu->pc=0x%" PRIx64"\n", (uint64_t)cpu->pc); */
662 
663  /* If there was an exception, the PC has changed.
664  Update cached_pc: */
665  cached_pc = cpu->pc;
666 
667 #ifdef MODE32
668  index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
669  if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL) {
670  paddr = cpu->cd.DYNTRANS_ARCH.phys_addr[index];
671  ok = 1;
672  }
673 #else
674  x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
675  x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N))
676  & mask2;
677  x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N
678  - DYNTRANS_L3N)) & mask3;
679  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
680  l3 = l2->l3[x2];
681  if (l3->host_load[x3] != NULL) {
682  paddr = l3->phys_addr[x3];
683  ok = 1;
684  }
685 #endif
686 
687  if (!ok) {
688  ok = cpu->translate_v2p(cpu, cpu->pc, &paddr,
689  FLAG_INSTR);
690  }
691 
692  /* printf("EXCEPTION HANDLER: vaddr = 0x%x ==> "
693  "paddr = 0x%x\n", (int)cpu->pc, (int)paddr);
694  fatal("!? cpu->pc=0x%" PRIx64"\n", (uint64_t)cpu->pc); */
695 
696  if (!ok) {
697  fatal("FATAL: could not find physical"
698  " address of the exception handler?");
699  exit(1);
700  }
701  }
702 
703  physaddr = paddr;
704  }
705 
706  physaddr &= ~(DYNTRANS_PAGESIZE - 1);
707 
708 #ifdef MODE32
709  if (cpu->cd.DYNTRANS_ARCH.host_load[index] == NULL) {
710 #else
711  if (l3->host_load[x3] == NULL) {
712 #endif
713  int q = DYNTRANS_PAGESIZE - 1;
714  unsigned char *host_page = memory_paddr_to_hostaddr(cpu->mem,
715  physaddr, MEM_READ);
716  if (host_page != NULL) {
717  cpu->update_translation_table(cpu, cached_pc & ~q,
718  host_page, 0, physaddr);
719  }
720  }
721 
723 #ifdef UNSTABLE_DEVEL
724  fatal("[ dyntrans: resetting the translation cache ]\n");
725 #endif
727  }
728 
729  pagenr = DYNTRANS_ADDR_TO_PAGENR(physaddr);
730  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
731 
732  physpage_entryp = &(((uint32_t *)cpu->translation_cache)[table_index]);
733  physpage_ofs = *physpage_entryp;
734  ppp = NULL;
735 
736  /* Traverse the physical page chain: */
737  while (physpage_ofs != 0) {
738  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
739  + physpage_ofs);
740 
741  /* If we found the page in the cache, then we're done: */
742  if (ppp->physaddr == physaddr)
743  break;
744 
745  /* Try the next page in the chain: */
746  physpage_ofs = ppp->next_ofs;
747  }
748 
749  /*
750  * If the offset is 0, then no translation exists yet for this
751  * physical address. Let's create a new page, and add it first in
752  * the chain.
753  */
754  if (physpage_ofs == 0) {
755  uint32_t previous_first_page_in_chain;
756 
757  /* fatal("CREATING page %lli (physaddr 0x%" PRIx64"), table "
758  "index %i\n", (long long)pagenr, (uint64_t)physaddr,
759  (int)table_index); */
760 
761  previous_first_page_in_chain = *physpage_entryp;
762 
763  /* Insert the new page first in the chain: */
764  *physpage_entryp = physpage_ofs =
766 
767  /* Allocate a default page, with to_be_translated entries: */
768  DYNTRANS_TC_ALLOCATE(cpu, physaddr);
769 
770  ppp = (struct DYNTRANS_TC_PHYSPAGE *)(cpu->translation_cache
771  + physpage_ofs);
772 
773  /* Point to the other pages in the same chain: */
774  ppp->next_ofs = previous_first_page_in_chain;
775  }
776 
777  /* Here, ppp points to a valid physical page struct. */
778 
779 #ifdef MODE32
780  if (cpu->cd.DYNTRANS_ARCH.host_load[index] != NULL)
781  cpu->cd.DYNTRANS_ARCH.phys_page[index] = ppp;
782 #else
783  if (l3->host_load[x3] != NULL)
784  l3->phys_page[x3] = ppp;
785 #endif
786 
787  /*
788  * If there are no translations yet on this page, then mark it
789  * as non-writable. If there are already translations, then it
790  * should already have been marked as non-writable.
791  */
792  if (ppp->translations_bitmap == 0) {
793  cpu->invalidate_translation_caches(cpu, physaddr,
795  }
796 
797  cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
798 
799  cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
800  DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
801 
802  /* printf("cached_pc=0x%016" PRIx64" pagenr=%lli table_index=%lli, "
803  "physpage_ofs=0x%016" PRIx64"\n", (uint64_t)cached_pc, (long long)
804  pagenr, (long long)table_index, (uint64_t)physpage_ofs); */
805 }
806 
807 
808 /*
809  * XXX_pc_to_pointers():
810  *
811  * This function uses the current program counter (a virtual address) to
812  * find out which physical translation page to use, and then sets the current
813  * translation page pointers to that page.
814  *
815  * If there was no translation page for that physical page, then an empty
816  * one is created.
817  *
818  * NOTE: This is the quick lookup version. See
819  * DYNTRANS_PC_TO_POINTERS_GENERIC above for the generic case.
820  */
821 void DYNTRANS_PC_TO_POINTERS_FUNC(struct cpu *cpu)
822 {
823 #ifdef MODE32
824  uint32_t
825 #else
826  uint64_t
827 #endif
828  cached_pc = cpu->pc;
829  struct DYNTRANS_TC_PHYSPAGE *ppp;
830 
831 #ifdef MODE32
832  int index;
833  index = DYNTRANS_ADDR_TO_PAGENR(cached_pc);
834  ppp = cpu->cd.DYNTRANS_ARCH.phys_page[index];
835  if (ppp != NULL)
836  goto have_it;
837 #else
838  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
839  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
840  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
841  uint32_t x1, x2, x3;
842  struct DYNTRANS_L2_64_TABLE *l2;
843  struct DYNTRANS_L3_64_TABLE *l3;
844 
845  x1 = (cached_pc >> (64-DYNTRANS_L1N)) & mask1;
846  x2 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
847  x3 = (cached_pc >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N)) & mask3;
848  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
849  l3 = l2->l3[x2];
850  ppp = l3->phys_page[x3];
851  if (ppp != NULL)
852  goto have_it;
853 #endif
854 
856  return;
857 
858  /* Quick return path: */
859 have_it:
860  cpu->cd.DYNTRANS_ARCH.cur_ic_page = &ppp->ics[0];
861  cpu->cd.DYNTRANS_ARCH.next_ic = cpu->cd.DYNTRANS_ARCH.cur_ic_page +
862  DYNTRANS_PC_TO_IC_ENTRY(cached_pc);
863 
864  /* printf("cached_pc=0x%016" PRIx64" pagenr=%lli table_index=%lli, "
865  "physpage_ofs=0x%016" PRIx64"\n", (uint64_t)cached_pc, (long long)
866  pagenr, (long long)table_index, (uint64_t)physpage_ofs); */
867 }
868 #endif /* DYNTRANS_PC_TO_POINTERS_FUNC */
869 
870 
871 
872 #ifdef DYNTRANS_INIT_TABLES
873 
874 /* forward declaration of to_be_translated and end_of_page: */
875 static void instr(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
876 static void instr(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
877 #ifdef DYNTRANS_DUALMODE_32
878 static void instr32(to_be_translated)(struct cpu *, struct DYNTRANS_IC *);
879 static void instr32(end_of_page)(struct cpu *,struct DYNTRANS_IC *);
880 #endif
881 
882 #ifdef DYNTRANS_DUALMODE_32
883 #define TO_BE_TRANSLATED ( cpu->is_32bit? instr32(to_be_translated) : \
884  instr(to_be_translated) )
885 #else
886 #define TO_BE_TRANSLATED ( instr(to_be_translated) )
887 #endif
888 
889 #ifdef DYNTRANS_DELAYSLOT
890 static void instr(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
891 #ifdef DYNTRANS_DUALMODE_32
892 static void instr32(end_of_page2)(struct cpu *,struct DYNTRANS_IC *);
893 #endif
894 #endif
895 
896 /*
897  * XXX_init_tables():
898  *
899  * Initializes the default translation page (for newly allocated pages), and
900  * for 64-bit emulation it also initializes 64-bit dummy tables and pointers.
901  */
902 void DYNTRANS_INIT_TABLES(struct cpu *cpu)
903 {
904 #ifndef MODE32
905  struct DYNTRANS_L2_64_TABLE *dummy_l2;
906  struct DYNTRANS_L3_64_TABLE *dummy_l3;
907  int x1, x2;
908 #endif
909  int i;
910  struct DYNTRANS_TC_PHYSPAGE *ppp;
911 
912  CHECK_ALLOCATION(ppp =
913  (struct DYNTRANS_TC_PHYSPAGE *) malloc(sizeof(struct DYNTRANS_TC_PHYSPAGE)));
914 
915  ppp->next_ofs = 0;
916  ppp->translations_bitmap = 0;
917  ppp->translation_ranges_ofs = 0;
918  /* ppp->physaddr is filled in by the page allocator */
919 
920  for (i=0; i<DYNTRANS_IC_ENTRIES_PER_PAGE; i++)
921  ppp->ics[i].f = TO_BE_TRANSLATED;
922 
923  /* End-of-page: */
924  ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 0].f =
926  cpu->is_32bit? instr32(end_of_page) :
927 #endif
928  instr(end_of_page);
929 
930  /* End-of-page-2, for delay-slot architectures: */
931 #ifdef DYNTRANS_DELAYSLOT
932  ppp->ics[DYNTRANS_IC_ENTRIES_PER_PAGE + 1].f =
933 #ifdef DYNTRANS_DUALMODE_32
934  cpu->is_32bit? instr32(end_of_page2) :
935 #endif
936  instr(end_of_page2);
937 #endif
938 
939  cpu->cd.DYNTRANS_ARCH.physpage_template = ppp;
940 
941 
942  /* Prepare 64-bit virtual address translation tables: */
943 #ifndef MODE32
944  if (cpu->is_32bit)
945  return;
946 
947  dummy_l2 = (struct DYNTRANS_L2_64_TABLE *) zeroed_alloc(sizeof(struct DYNTRANS_L2_64_TABLE));
948  dummy_l3 = (struct DYNTRANS_L3_64_TABLE *) zeroed_alloc(sizeof(struct DYNTRANS_L3_64_TABLE));
949 
950  cpu->cd.DYNTRANS_ARCH.l2_64_dummy = dummy_l2;
951  cpu->cd.DYNTRANS_ARCH.l3_64_dummy = dummy_l3;
952 
953  for (x1 = 0; x1 < (1 << DYNTRANS_L1N); x1 ++)
954  cpu->cd.DYNTRANS_ARCH.l1_64[x1] = dummy_l2;
955 
956  for (x2 = 0; x2 < (1 << DYNTRANS_L2N); x2 ++)
957  dummy_l2->l3[x2] = dummy_l3;
958 #endif
959 }
960 #endif /* DYNTRANS_INIT_TABLES */
961 
962 
963 
964 #ifdef DYNTRANS_INVAL_ENTRY
965 /*
966  * XXX_invalidate_tlb_entry():
967  *
968  * Invalidate one translation entry (based on virtual address).
969  *
970  * If the JUST_MARK_AS_NON_WRITABLE flag is set, then the translation entry
971  * is just downgraded to non-writable (ie the host store page is set to
972  * NULL). Otherwise, the entire translation is removed.
973  */
974 static void DYNTRANS_INVALIDATE_TLB_ENTRY(struct cpu *cpu,
975 #ifdef MODE32
976  uint32_t
977 #else
978  uint64_t
979 #endif
980  vaddr_page, int flags)
981 {
982 #ifdef MODE32
983  uint32_t index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
984 
985 #ifdef DYNTRANS_ARM
986  cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5] &= ~(1 << (index & 31));
987 #endif
988 
989  if (flags & JUST_MARK_AS_NON_WRITABLE) {
990  /* printf("JUST MARKING NON-W: vaddr 0x%08x\n",
991  (int)vaddr_page); */
992  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
993  } else {
994  int tlbi = cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index];
995  cpu->cd.DYNTRANS_ARCH.host_load[index] = NULL;
996  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
997  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = 0;
998  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
999  if (tlbi > 0)
1000  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[tlbi-1].valid = 0;
1001  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = 0;
1002  }
1003 #else
1004  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1005  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1006  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1007  uint32_t x1, x2, x3;
1008  struct DYNTRANS_L2_64_TABLE *l2;
1009  struct DYNTRANS_L3_64_TABLE *l3;
1010 
1011  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1012  x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1013  x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))& mask3;
1014 
1015  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1016  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1017  return;
1018 
1019  l3 = l2->l3[x2];
1020  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1021  return;
1022 
1023  if (flags & JUST_MARK_AS_NON_WRITABLE) {
1024  l3->host_store[x3] = NULL;
1025  return;
1026  }
1027 
1028 #ifdef BUGHUNT
1029 
1030 {
1031  /* Consistency check, for debugging: */
1032  int x1, x1b; // x2, x3;
1033  struct DYNTRANS_L2_64_TABLE *l2;
1034  //struct DYNTRANS_L3_64_TABLE *l3;
1035 
1036  for (x1 = 0; x1 <= mask1; x1 ++) {
1037  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1038  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1039  continue;
1040  /* Make sure that this l2 isn't used more than 1 time! */
1041  for (x1b = 0; x1b <= mask1; x1b ++)
1042  if (x1 != x1b &&
1043  l2 == cpu->cd.DYNTRANS_ARCH.l1_64[x1b]) {
1044  fatal("L2 reuse: %p\n", l2);
1045  exit(1);
1046  }
1047  }
1048 }
1049 
1050 /* Count how many pages are actually in use: */
1051 {
1052  int n=0, i;
1053  for (i=0; i<=mask3; i++)
1054  if (l3->vaddr_to_tlbindex[i])
1055  n++;
1056  if (n != l3->refcount) {
1057  printf("Z: %i in use, but refcount = %i!\n", n, l3->refcount);
1058  exit(1);
1059  }
1060 
1061  n = 0;
1062  for (i=0; i<=mask3; i++)
1063  if (l3->host_load[i] != NULL)
1064  n++;
1065  if (n != l3->refcount) {
1066  printf("ZHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1067  exit(1);
1068  }
1069 }
1070 #endif
1071 
1072 /*
1073  int found = -1;
1074  for (int q = 0; q < 192; ++q)
1075  {
1076  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[q].vaddr_page == vaddr_page &&
1077  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[q].valid)
1078  {
1079  if (found >= 0)
1080  {
1081  printf("ALREADY FOUND = %i\n", found);
1082  int zz = found;
1083  printf("%03i: ", zz);
1084  printf("vaddr=%016llx\n", (long long)cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].vaddr_page);
1085  printf("valid=%i\n", cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].valid);
1086 
1087  zz = q;
1088  printf("%03i: ", zz);
1089  printf("vaddr=%016llx\n", (long long)cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].vaddr_page);
1090  printf("valid=%i\n", cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].valid);
1091 
1092  exit(1);
1093  }
1094 
1095  found = q;
1096  }
1097  }
1098 */
1099 
1100  l3->host_load[x3] = NULL;
1101  l3->host_store[x3] = NULL;
1102  l3->phys_addr[x3] = 0;
1103  l3->phys_page[x3] = NULL;
1104  if (l3->vaddr_to_tlbindex[x3] != 0) {
1105  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[
1106  l3->vaddr_to_tlbindex[x3] - 1].valid = 0;
1107  l3->refcount --;
1108  } else {/*
1109  printf("APA: vaddr_page=%016llx l3->refcount = %i\n", (long long)vaddr_page, l3->refcount);
1110  for (int zz = 0; zz < 128; ++zz)
1111  {
1112  printf("%03i: ", zz);
1113  printf("vaddr=%016llx\n", (long long)cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].vaddr_page);
1114  printf("valid=%i\n", cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[zz].valid);
1115  }
1116 
1117  exit(1);*/
1118  }
1119  l3->vaddr_to_tlbindex[x3] = 0;
1120 
1121  if (l3->refcount < 0) {
1122  fatal("xxx_invalidate_tlb_entry(): huh? Refcount bug.\n");
1123  exit(1);
1124  }
1125 
1126  if (l3->refcount == 0) {
1127  l3->next = cpu->cd.DYNTRANS_ARCH.next_free_l3;
1128  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3;
1129  l2->l3[x2] = cpu->cd.DYNTRANS_ARCH.l3_64_dummy;
1130 
1131 #ifdef BUGHUNT
1132 /* Make sure that we're placing a CLEAN page on the
1133  freelist: */
1134 {
1135  int i;
1136  for (i=0; i<=mask3; i++)
1137  if (l3->host_load[i] != NULL) {
1138  fatal("TRYING TO RETURN A NON-CLEAN L3 PAGE!\n");
1139  exit(1);
1140  }
1141 }
1142 #endif
1143  l2->refcount --;
1144  if (l2->refcount < 0) {
1145  fatal("xxx_invalidate_tlb_entry(): Refcount bug L2.\n");
1146  exit(1);
1147  }
1148  if (l2->refcount == 0) {
1149  l2->next = cpu->cd.DYNTRANS_ARCH.next_free_l2;
1150  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2;
1151  cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1152  cpu->cd.DYNTRANS_ARCH.l2_64_dummy;
1153  }
1154  }
1155 #endif
1156 }
1157 #endif
1158 
1159 
1160 #ifdef DYNTRANS_INVALIDATE_TC
1161 /*
1162  * XXX_invalidate_translation_caches():
1163  *
1164  * Invalidate all entries matching a specific physical address, a specific
1165  * virtual address, or ALL entries.
1166  *
1167  * flags should be one of
1168  * INVALIDATE_PADDR INVALIDATE_VADDR or INVALIDATE_ALL
1169  *
1170  * In addition, for INVALIDATE_ALL, INVALIDATE_VADDR_UPPER4 may be set and
1171  * bit 31..28 of addr are used to select the virtual addresses to invalidate.
1172  * (This is useful for PowerPC emulation, when segment registers are updated.)
1173  *
1174  * In the case when all translations are invalidated, paddr doesn't need
1175  * to be supplied.
1176  *
1177  * NOTE/TODO: When invalidating a virtual address, it is only cleared from
1178  * the quick translation array, not from the linear
1179  * vph_tlb_entry[] array. Hopefully this is enough anyway.
1180  */
1181 void DYNTRANS_INVALIDATE_TC(struct cpu *cpu, uint64_t addr, int flags)
1182 {
1183  int r;
1184 #ifdef MODE32
1185  uint32_t
1186 #else
1187  uint64_t
1188 #endif
1189  addr_page = addr & ~(DYNTRANS_PAGESIZE - 1);
1190 
1191  /* fatal("invalidate(): "); */
1192 
1193  /* Quick case for _one_ virtual addresses: see note above. */
1194  if (flags & INVALIDATE_VADDR) {
1195  /* fatal("vaddr 0x%08x\n", (int)addr_page); */
1196  DYNTRANS_INVALIDATE_TLB_ENTRY(cpu, addr_page, flags);
1197  return;
1198  }
1199 
1200  /* Invalidate everything: */
1201 #ifdef DYNTRANS_PPC
1202  if (flags & INVALIDATE_ALL && flags & INVALIDATE_VADDR_UPPER4) {
1203  /* fatal("all, upper4 (PowerPC segment)\n"); */
1204  for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1205  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid &&
1206  (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page
1207  & 0xf0000000) == addr_page) {
1209  DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1210  0);
1211  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1212  }
1213  }
1214  return;
1215  }
1216 #endif
1217  if (flags & INVALIDATE_ALL) {
1218  /* fatal("all\n"); */
1219  for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1220  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1222  DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1223  0);
1224  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid=0;
1225  }
1226  }
1227  return;
1228  }
1229 
1230  /* Invalidate a physical page: */
1231 
1232  if (!(flags & INVALIDATE_PADDR))
1233  fatal("HUH? Invalidate: Not vaddr, all, or paddr?\n");
1234 
1235  /* fatal("addr 0x%08x\n", (int)addr_page); */
1236 
1237  for (r=0; r<DYNTRANS_MAX_VPH_TLB_ENTRIES; r++) {
1238  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid && addr_page
1239  == cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page) {
1241  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1242  flags);
1243  if (flags & JUST_MARK_AS_NON_WRITABLE)
1244  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1245  .writeflag = 0;
1246  else
1247  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1248  .valid = 0;
1249  }
1250  }
1251 }
1252 #endif /* DYNTRANS_INVALIDATE_TC */
1253 
1254 
1255 
1256 #ifdef DYNTRANS_INVALIDATE_TC_CODE
1257 /*
1258  * XXX_invalidate_code_translation():
1259  *
1260  * Invalidate code translations for a specific physical address, a specific
1261  * virtual address, or for all entries in the cache.
1262  */
1263 void DYNTRANS_INVALIDATE_TC_CODE(struct cpu *cpu, uint64_t addr, int flags)
1264 {
1265  int r;
1266 #ifdef MODE32
1267  uint32_t
1268 #else
1269  uint64_t
1270 #endif
1271  vaddr_page, paddr_page;
1272 
1273  addr &= ~(DYNTRANS_PAGESIZE-1);
1274 
1275  /* printf("DYNTRANS_INVALIDATE_TC_CODE addr=0x%08x flags=%i\n",
1276  (int)addr, flags); */
1277 
1278  if (flags & INVALIDATE_PADDR) {
1279  int pagenr, table_index;
1280  uint32_t physpage_ofs, *physpage_entryp;
1281  struct DYNTRANS_TC_PHYSPAGE *ppp, *prev_ppp;
1282 
1283  pagenr = DYNTRANS_ADDR_TO_PAGENR(addr);
1284  table_index = PAGENR_TO_TABLE_INDEX(pagenr);
1285 
1286  physpage_entryp = &(((uint32_t *)cpu->
1287  translation_cache)[table_index]);
1288  physpage_ofs = *physpage_entryp;
1289 
1290  /* Return immediately if there is no code translation
1291  for this page. */
1292  if (physpage_ofs == 0)
1293  return;
1294 
1295  prev_ppp = ppp = NULL;
1296 
1297  /* Traverse the physical page chain: */
1298  while (physpage_ofs != 0) {
1299  prev_ppp = ppp;
1300  ppp = (struct DYNTRANS_TC_PHYSPAGE *)
1301  (cpu->translation_cache + physpage_ofs);
1302 
1303  /* If we found the page in the cache,
1304  then we're done: */
1305  if (ppp->physaddr == addr)
1306  break;
1307 
1308  /* Try the next page in the chain: */
1309  physpage_ofs = ppp->next_ofs;
1310  }
1311 
1312  /* If there is no translation, there is no need to go
1313  on and try to remove it from the vph_tlb_entry array: */
1314  if (physpage_ofs == 0)
1315  return;
1316 
1317 #if 0
1318  /*
1319  * "Bypass" the page, removing it from the code cache.
1320  *
1321  * NOTE/TODO: This gives _TERRIBLE_ performance with self-
1322  * modifying code, or when a single page is used for both
1323  * code and (writable) data.
1324  */
1325  if (ppp != NULL) {
1326  if (prev_ppp != NULL)
1327  prev_ppp->next_ofs = ppp->next_ofs;
1328  else
1329  *physpage_entryp = ppp->next_ofs;
1330  }
1331 #else
1332  (void)prev_ppp; // shut up compiler warning
1333 
1334  /*
1335  * Instead of removing the page from the code cache, each
1336  * entry can be set to "to_be_translated". This is slow in
1337  * the general case, but in the case of self-modifying code,
1338  * it might be faster since we don't risk wasting cache
1339  * memory as quickly (which would force unnecessary Restarts).
1340  */
1341  if (ppp != NULL && ppp->translations_bitmap != 0) {
1342  uint32_t x = ppp->translations_bitmap; /* TODO:
1343  urk Should be same type as the bitmap */
1344  int i, j, n, m;
1345 
1346 #ifdef DYNTRANS_ARM
1347  /*
1348  * Note: On ARM, PC-relative load instructions are
1349  * implemented as immediate mov instructions. When
1350  * setting parts of the page to "to be translated",
1351  * we cannot keep track of which of the immediate
1352  * movs that were affected, so we need to clear
1353  * the entire page. (ARM only; not for the general
1354  * case.)
1355  */
1356  x = 0xffffffff;
1357 #endif
1358  n = 8 * sizeof(x);
1360 
1361  for (i=0; i<n; i++) {
1362  if (x & 1) {
1363  for (j=0; j<m; j++)
1364  ppp->ics[i*m + j].f =
1365  TO_BE_TRANSLATED;
1366  }
1367 
1368  x >>= 1;
1369  }
1370 
1371  ppp->translations_bitmap = 0;
1372 
1373  /* Clear the list of translatable ranges: */
1374  if (ppp->translation_ranges_ofs != 0) {
1376  (struct physpage_ranges *)
1377  (cpu->translation_cache +
1378  ppp->translation_ranges_ofs);
1379  physpage_ranges->next_ofs = 0;
1380  physpage_ranges->n_entries_used = 0;
1381  }
1382  }
1383 #endif
1384  }
1385 
1386  /* Invalidate entries in the VPH table: */
1387  for (r = 0; r < DYNTRANS_MAX_VPH_TLB_ENTRIES; r ++) {
1388  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1389  vaddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1390  .vaddr_page & ~(DYNTRANS_PAGESIZE-1);
1391  paddr_page = cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r]
1392  .paddr_page & ~(DYNTRANS_PAGESIZE-1);
1393 
1394  if (flags & INVALIDATE_ALL ||
1395  (flags & INVALIDATE_PADDR && paddr_page == addr) ||
1396  (flags & INVALIDATE_VADDR && vaddr_page == addr)) {
1397 #ifdef MODE32
1398  uint32_t index =
1399  DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1400  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1401 #else
1402  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1403  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1404  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1405  uint32_t x1, x2, x3;
1406  struct DYNTRANS_L2_64_TABLE *l2;
1407  struct DYNTRANS_L3_64_TABLE *l3;
1408 
1409  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1410  x2 = (vaddr_page >> (64-DYNTRANS_L1N -
1411  DYNTRANS_L2N)) & mask2;
1412  x3 = (vaddr_page >> (64-DYNTRANS_L1N -
1413  DYNTRANS_L2N - DYNTRANS_L3N)) & mask3;
1414  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1415  l3 = l2->l3[x2];
1416  l3->phys_page[x3] = NULL;
1417 #endif
1418  }
1419  }
1420  }
1421 }
1422 #endif /* DYNTRANS_INVALIDATE_TC_CODE */
1423 
1424 
1425 
1426 #ifdef DYNTRANS_UPDATE_TRANSLATION_TABLE
1427 /*
1428  * XXX_update_translation_table():
1429  *
1430  * Update the virtual memory translation tables.
1431  */
1432 void DYNTRANS_UPDATE_TRANSLATION_TABLE(struct cpu *cpu, uint64_t vaddr_page,
1433  unsigned char *host_page, int writeflag, uint64_t paddr_page)
1434 {
1435  int found, r, useraccess = 0;
1436 
1437 #ifdef MODE32
1438  uint32_t index;
1439  vaddr_page &= 0xffffffffULL;
1440 
1441  if (paddr_page > 0xffffffffULL) {
1442  fatal("update_translation_table(): v=0x%016" PRIx64", h=%p w=%i"
1443  " p=0x%016" PRIx64"\n", vaddr_page, host_page, writeflag,
1444  paddr_page);
1445  exit(1);
1446  }
1447 
1448  /* fatal("update_translation_table(): v=0x%x, h=%p w=%i"
1449  " p=0x%x\n", (int)vaddr_page, host_page, writeflag,
1450  (int)paddr_page); */
1451 #else /* !MODE32 */
1452  const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
1453  const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
1454  const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
1455  uint32_t x1, x2, x3;
1456  struct DYNTRANS_L2_64_TABLE *l2;
1457  struct DYNTRANS_L3_64_TABLE *l3;
1458 
1459  /* fatal("update_translation_table(): v=0x%016" PRIx64", h=%p w=%i"
1460  " p=0x%016" PRIx64"\n", (uint64_t)vaddr_page, host_page, writeflag,
1461  (uint64_t)paddr_page); */
1462 #endif
1463 
1464  assert((vaddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1465  assert((paddr_page & (DYNTRANS_PAGESIZE-1)) == 0);
1466 
1467  if (writeflag & MEMORY_USER_ACCESS) {
1468  writeflag &= ~MEMORY_USER_ACCESS;
1469  useraccess = 1;
1470  }
1471 
1472  (void)useraccess; // shut up compiler warning about unused var
1473 
1474 #ifdef DYNTRANS_M88K
1475  /* TODO */
1476  if (useraccess)
1477  return;
1478 #endif
1479 
1480  /* Scan the current TLB entries: */
1481 
1482 #ifdef MODE32
1483  /*
1484  * NOTE 1: vaddr_to_tlbindex is one more than the index, so that
1485  * 0 becomes -1, which means a miss.
1486  *
1487  * NOTE 2: When a miss occurs, instead of scanning the entire tlb
1488  * for the entry with the lowest time stamp, just choosing
1489  * one at random will work as well.
1490  */
1491  found = (int)cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[
1492  DYNTRANS_ADDR_TO_PAGENR(vaddr_page)] - 1;
1493 #else
1494  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1495  x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1496  x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1497  & mask3;
1498 
1499  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1500  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy)
1501  found = -1;
1502  else {
1503  l3 = l2->l3[x2];
1504  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy)
1505  found = -1;
1506  else
1507  found = (int)l3->vaddr_to_tlbindex[x3] - 1;
1508  }
1509 #endif
1510 
1511  if (found < 0) {
1512  /* Create the new TLB entry, overwriting a "random" entry: */
1513  static unsigned int x = 0;
1514  r = (x++) % DYNTRANS_MAX_VPH_TLB_ENTRIES;
1515 
1516  if (cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid) {
1517  /* This one has to be invalidated first: */
1519  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page,
1520  0);
1521  }
1522 
1523  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid = 1;
1524  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].host_page = host_page;
1525  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].paddr_page = paddr_page;
1526  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].vaddr_page = vaddr_page;
1527  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag =
1528  writeflag & MEM_WRITE;
1529 
1530  /* Add the new translation to the table: */
1531 #ifdef MODE32
1532  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1533  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1534  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1535  writeflag? host_page : NULL;
1536  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1537  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1538  cpu->cd.DYNTRANS_ARCH.vaddr_to_tlbindex[index] = r + 1;
1539 #ifdef DYNTRANS_ARM
1540  if (useraccess)
1541  cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1542  |= 1 << (index & 31);
1543 #endif
1544 #else /* !MODE32 */
1545  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1546  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1547  if (cpu->cd.DYNTRANS_ARCH.next_free_l2 != NULL) {
1548  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1549  cpu->cd.DYNTRANS_ARCH.next_free_l2;
1550  cpu->cd.DYNTRANS_ARCH.next_free_l2 = l2->next;
1551  } else {
1552  int i;
1553  CHECK_ALLOCATION(l2 =
1554  cpu->cd.DYNTRANS_ARCH.l1_64[x1] =
1555  (struct DYNTRANS_L2_64_TABLE *) malloc(
1556  sizeof(struct DYNTRANS_L2_64_TABLE)));
1557  l2->refcount = 0;
1558  for (i=0; i<(1 << DYNTRANS_L2N); i++)
1559  l2->l3[i] = cpu->cd.DYNTRANS_ARCH.
1560  l3_64_dummy;
1561  }
1562  if (l2->refcount != 0) {
1563  fatal("Huh? l2 Refcount problem.\n");
1564  exit(1);
1565  }
1566  }
1567  if (l2 == cpu->cd.DYNTRANS_ARCH.l2_64_dummy) {
1568  fatal("INTERNAL ERROR L2 reuse\n");
1569  exit(1);
1570  }
1571  l3 = l2->l3[x2];
1572  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1573  if (cpu->cd.DYNTRANS_ARCH.next_free_l3 != NULL) {
1574  l3 = l2->l3[x2] =
1575  cpu->cd.DYNTRANS_ARCH.next_free_l3;
1576  cpu->cd.DYNTRANS_ARCH.next_free_l3 = l3->next;
1577  } else {
1578  l3 = l2->l3[x2] = (struct DYNTRANS_L3_64_TABLE *)
1579  zeroed_alloc(sizeof(
1580  struct DYNTRANS_L3_64_TABLE));
1581  }
1582  if (l3->refcount != 0) {
1583  fatal("Huh? l3 Refcount problem.\n");
1584  exit(1);
1585  }
1586  l2->refcount ++;
1587  }
1588  if (l3 == cpu->cd.DYNTRANS_ARCH.l3_64_dummy) {
1589  fatal("INTERNAL ERROR L3 reuse\n");
1590  exit(1);
1591  }
1592 
1593  l3->host_load[x3] = host_page;
1594  l3->host_store[x3] = writeflag? host_page : NULL;
1595  l3->phys_addr[x3] = paddr_page;
1596  l3->phys_page[x3] = NULL;
1597  l3->vaddr_to_tlbindex[x3] = r + 1;
1598  l3->refcount ++;
1599 
1600 #ifdef BUGHUNT
1601 /* Count how many pages are actually in use: */
1602 {
1603  int n=0, i;
1604  for (i=0; i<=mask3; i++)
1605  if (l3->vaddr_to_tlbindex[i])
1606  n++;
1607  if (n != l3->refcount) {
1608  printf("X: %i in use, but refcount = %i!\n", n, l3->refcount);
1609  exit(1);
1610  }
1611 
1612  n = 0;
1613  for (i=0; i<=mask3; i++)
1614  if (l3->host_load[i] != NULL)
1615  n++;
1616  if (n != l3->refcount) {
1617  printf("XHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1618  exit(1);
1619  }
1620 }
1621 #endif
1622 
1623 #endif /* !MODE32 */
1624  } else {
1625  /*
1626  * The translation was already in the TLB.
1627  * Writeflag = 0: Do nothing.
1628  * Writeflag = 1: Make sure the page is writable.
1629  * Writeflag = MEM_DOWNGRADE: Downgrade to readonly.
1630  */
1631  r = found;
1632  if (writeflag & MEM_WRITE)
1633  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 1;
1634  if (writeflag & MEM_DOWNGRADE)
1635  cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].writeflag = 0;
1636 #ifdef MODE32
1637  index = DYNTRANS_ADDR_TO_PAGENR(vaddr_page);
1638  cpu->cd.DYNTRANS_ARCH.phys_page[index] = NULL;
1639 #ifdef DYNTRANS_ARM
1640  cpu->cd.DYNTRANS_ARCH.is_userpage[index>>5] &= ~(1<<(index&31));
1641  if (useraccess)
1642  cpu->cd.DYNTRANS_ARCH.is_userpage[index >> 5]
1643  |= 1 << (index & 31);
1644 #endif
1645  if (cpu->cd.DYNTRANS_ARCH.phys_addr[index] == paddr_page) {
1646  if (writeflag & MEM_WRITE)
1647  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1648  host_page;
1649  if (writeflag & MEM_DOWNGRADE)
1650  cpu->cd.DYNTRANS_ARCH.host_store[index] = NULL;
1651  } else {
1652  /* Change the entire physical/host mapping: */
1653  cpu->cd.DYNTRANS_ARCH.host_load[index] = host_page;
1654  cpu->cd.DYNTRANS_ARCH.host_store[index] =
1655  writeflag? host_page : NULL;
1656  cpu->cd.DYNTRANS_ARCH.phys_addr[index] = paddr_page;
1657  }
1658 #else /* !MODE32 */
1659  x1 = (vaddr_page >> (64-DYNTRANS_L1N)) & mask1;
1660  x2 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
1661  x3 = (vaddr_page >> (64-DYNTRANS_L1N-DYNTRANS_L2N-DYNTRANS_L3N))
1662  & mask3;
1663  l2 = cpu->cd.DYNTRANS_ARCH.l1_64[x1];
1664  l3 = l2->l3[x2];
1665  if (l3->phys_addr[x3] == paddr_page) {
1666  if (writeflag & MEM_WRITE)
1667  l3->host_store[x3] = host_page;
1668  if (writeflag & MEM_DOWNGRADE)
1669  l3->host_store[x3] = NULL;
1670  } else {
1671  /* Change the entire physical/host mapping: */
1672  l3->host_load[x3] = host_page;
1673  l3->host_store[x3] = writeflag? host_page : NULL;
1674  l3->phys_addr[x3] = paddr_page;
1675  }
1676 
1677  /* HM! /2013-11-17 */
1678  /* Should this be here? 2014-08-02 */
1679  //l3->phys_page[x3] = NULL;
1680 
1681 #ifdef BUGHUNT
1682 /* Count how many pages are actually in use: */
1683 {
1684  int n=0, i;
1685  for (i=0; i<=mask3; i++)
1686  if (l3->vaddr_to_tlbindex[i])
1687  n++;
1688  if (n != l3->refcount) {
1689  printf("Y: %i in use, but refcount = %i!\n", n, l3->refcount);
1690  exit(1);
1691  }
1692 
1693  n = 0;
1694  for (i=0; i<=mask3; i++)
1695  if (l3->host_load[i] != NULL)
1696  n++;
1697  if (n != l3->refcount) {
1698  printf("YHL: %i in use, but refcount = %i!\n", n, l3->refcount);
1699  printf("Entry r = %i\n", r);
1700  printf("Valid = %i\n",
1701 cpu->cd.DYNTRANS_ARCH.vph_tlb_entry[r].valid);
1702  exit(1);
1703  }
1704 }
1705 #endif
1706 
1707 #endif /* !MODE32 */
1708  }
1709 }
1710 #endif /* DYNTRANS_UPDATE_TRANSLATION_TABLE */
1711 
1712 
1713 /*****************************************************************************/
1714 
1715 
1716 #ifdef DYNTRANS_TO_BE_TRANSLATED_HEAD
1717  /*
1718  * Check for breakpoints.
1719  */
1721  MODE_uint_t curpc = cpu->pc;
1722  int i;
1723  for (i=0; i<cpu->machine->breakpoints.n; i++)
1724  if (curpc == (MODE_uint_t)
1725  cpu->machine->breakpoints.addr[i]) {
1726  if (!cpu->machine->instruction_trace) {
1727  int tmp_old_quiet_mode = quiet_mode;
1728  quiet_mode = 0;
1729  DISASSEMBLE(cpu, ib, 1, 0);
1730  quiet_mode = tmp_old_quiet_mode;
1731  }
1732 #ifdef MODE32
1733  fatal("BREAKPOINT: pc = 0x%" PRIx32"\n(The "
1734  "instruction has not yet executed.)\n",
1735  (uint32_t)cpu->pc);
1736 #else
1737  fatal("BREAKPOINT: pc = 0x%" PRIx64"\n(The "
1738  "instruction has not yet executed.)\n",
1739  (uint64_t)cpu->pc);
1740 #endif
1741 #ifdef DYNTRANS_DELAYSLOT
1742  if (cpu->delay_slot != NOT_DELAYED)
1743  fatal("ERROR! Breakpoint in a delay"
1744  " slot! Not yet supported.\n");
1745 #endif
1748  goto stop_running_translated;
1749  }
1750  }
1751 #endif /* DYNTRANS_TO_BE_TRANSLATED_HEAD */
1752 
1753 
1754 /*****************************************************************************/
1755 
1756 
1757 #ifdef DYNTRANS_TO_BE_TRANSLATED_TAIL
1758  /*
1759  * If we end up here, then an instruction was translated. Let's mark
1760  * the page as containing a translation at this part of the page.
1761  */
1762 
1763  /* Make sure cur_physpage is in synch: */
1764  cpu->cd.DYNTRANS_ARCH.cur_physpage = (struct DYNTRANS_TC_PHYSPAGE *)
1765  cpu->cd.DYNTRANS_ARCH.cur_ic_page;
1766 
1767  {
1768  int x = addr & (DYNTRANS_PAGESIZE - 1);
1769  int addr_per_translation_range = DYNTRANS_PAGESIZE / (8 *
1770  sizeof(cpu->cd.DYNTRANS_ARCH.cur_physpage->
1771  translations_bitmap));
1772  x /= addr_per_translation_range;
1773 
1774  cpu->cd.DYNTRANS_ARCH.cur_physpage->
1775  translations_bitmap |= (1 << x);
1776  }
1777 
1778 
1779  /*
1780  * Now it is time to check for combinations of instructions that can
1781  * be converted into a single function call.
1782  *
1783  * Note: Single-stepping or instruction tracing doesn't work with
1784  * instruction combinations. For architectures with delay slots,
1785  * we also ignore combinations if the delay slot is across a page
1786  * boundary.
1787  */
1788  if (!single_step && !cpu->machine->instruction_trace
1789 #ifdef DYNTRANS_DELAYSLOT
1790  && !in_crosspage_delayslot
1791 #endif
1792  && cpu->cd.DYNTRANS_ARCH.combination_check != NULL
1794  cpu->cd.DYNTRANS_ARCH.combination_check(cpu, ic,
1795  addr & (DYNTRANS_PAGESIZE - 1));
1796  }
1797 
1798  cpu->cd.DYNTRANS_ARCH.combination_check = NULL;
1799 
1800  /* An additional check, to catch some bugs: */
1801  if (ic->f == TO_BE_TRANSLATED) {
1802  fatal("INTERNAL ERROR: ic->f not set!\n");
1803  goto bad;
1804  }
1805  if (ic->f == NULL) {
1806  fatal("INTERNAL ERROR: ic->f == NULL!\n");
1807  goto bad;
1808  }
1809 
1810 
1811  /*
1812  * ... and finally execute the translated instruction:
1813  */
1814 
1815  /* (Except when doing read-ahead!) */
1816  if (cpu->translation_readahead)
1817  return;
1818 
1819  /*
1820  * Special case when single-stepping: Execute the translated
1821  * instruction, but then replace it with a "to be translated"
1822  * directly afterwards.
1823  */
1825 #ifdef DYNTRANS_DELAYSLOT
1826  || in_crosspage_delayslot
1827 #endif
1828  ) {
1830  ic->f(cpu, ic);
1831  ic->f = TO_BE_TRANSLATED;
1832  return;
1833  }
1834 
1835 
1836  /* Translation read-ahead: */
1837  if (!single_step && !cpu->machine->instruction_trace &&
1838  cpu->machine->breakpoints.n == 0) {
1839  uint64_t baseaddr = cpu->pc;
1840  uint64_t pagenr = DYNTRANS_ADDR_TO_PAGENR(baseaddr);
1841  int i = 1;
1842 
1844 
1845  while (DYNTRANS_ADDR_TO_PAGENR(baseaddr +
1846  (i << DYNTRANS_INSTR_ALIGNMENT_SHIFT)) == pagenr &&
1847  cpu->translation_readahead > 0) {
1848  void (*old_f)(struct cpu *,
1849  struct DYNTRANS_IC *) = ic[i].f;
1850 
1851  /* Already translated? Then abort: */
1852  if (old_f != TO_BE_TRANSLATED)
1853  break;
1854 
1855  /* Translate the instruction: */
1856  ic[i].f(cpu, ic+i);
1857 
1858  /* Translation failed? Then abort. */
1859  if (ic[i].f == old_f)
1860  break;
1861 
1862  cpu->translation_readahead --;
1863  ++i;
1864  }
1865 
1866  cpu->translation_readahead = 0;
1867  }
1868 
1869 
1870  /*
1871  * Finally finally :-), execute the instruction.
1872  *
1873  * Note: The instruction might have changed during read-ahead, if
1874  * instruction combinations are used.
1875  */
1876 
1877  ic->f(cpu, ic);
1878 
1879  return;
1880 
1881 
1882 bad: /*
1883  * Nothing was translated. (Unimplemented or illegal instruction.)
1884  */
1885 
1886  /* Clear the translation, in case it was "half-way" done: */
1887  ic->f = TO_BE_TRANSLATED;
1888 
1889  if (cpu->translation_readahead)
1890  return;
1891 
1892  quiet_mode = 0;
1893  fatal("to_be_translated(): TODO: unimplemented instruction");
1894 
1895  if (cpu->machine->instruction_trace) {
1896  if (cpu->is_32bit)
1897  fatal(" at 0x%" PRIx32"\n", (uint32_t)cpu->pc);
1898  else
1899  fatal(" at 0x%" PRIx64"\n", (uint64_t)cpu->pc);
1900  } else {
1901  fatal(":\n");
1902  DISASSEMBLE(cpu, ib, 1, 0);
1903  }
1904 
1905  cpu->running = 0;
1906 
1907  /* Note: Single-stepping can jump here. */
1908 stop_running_translated:
1909 
1911 
1912  ic = cpu->cd.DYNTRANS_ARCH.next_ic = &nothing_call;
1913  cpu->cd.DYNTRANS_ARCH.next_ic ++;
1914 
1915 #ifdef DYNTRANS_DELAYSLOT
1916  /* Special hack: If the bad instruction was in a delay slot,
1917  make sure that execution does not continue anyway: */
1918  if (cpu->delay_slot)
1920 #endif
1921 
1922  /* Execute the "nothing" instruction: */
1923  ic->f(cpu, ic);
1924 
1925 #endif /* DYNTRANS_TO_BE_TRANSLATED_TAIL */
1926 
void * zeroed_alloc(size_t s)
Definition: memory.cc:118
void fatal(const char *fmt,...)
Definition: main.cc:152
int emulated_hz
Definition: machine.h:165
#define DYNTRANS_INIT_TABLES
int(* translate_v2p)(struct cpu *, uint64_t vaddr, uint64_t *return_paddr, int flags)
Definition: cpu.h:369
#define NOT_DELAYED
Definition: cpu.h:305
#define SPR_TBL
Definition: ppc_spr.h:73
#define INVALIDATE_VADDR
Definition: cpu.h:480
#define JUST_MARK_AS_NON_WRITABLE
Definition: cpu.h:477
uint64_t msr
Definition: cpu_ppc.h:130
#define MODE_uint_t
uint64_t spr[1024]
Definition: cpu_ppc.h:134
#define DYNTRANS_INVALIDATE_TC
uint32_t sr
Definition: cpu_sh.h:112
uint8_t delay_slot
Definition: cpu.h:356
uint8_t is_32bit
Definition: cpu.h:350
#define DYNTRANS_TC_ALLOCATE
#define DYNTRANS_PC_TO_POINTERS
#define INVALIDATE_ALL
Definition: cpu.h:478
#define DYNTRANS_PC_TO_POINTERS_GENERIC
#define STATUS_ERL
Definition: cop0.h:124
struct arm_instr_call * ic
#define M88K_PSR_MODE
Definition: m88k_psl.h:70
uint32_t n_entries_used
Definition: cpu.h:119
struct ppc_cpu ppc
Definition: cpu.h:444
#define MIPS_GPR_A0
union cpu::@1 cd
struct memory * mem
Definition: cpu.h:362
#define COP0_COUNT
Definition: cop0.h:92
struct breakpoints breakpoints
Definition: machine.h:159
#define COP0_STATUS
Definition: cop0.h:109
#define DYNTRANS_UPDATE_TRANSLATION_TABLE
struct machine * machine
Definition: cpu.h:328
int irq_asserted
Definition: cpu_ppc.h:118
#define MEM_READ
Definition: memory.h:116
void f(int s, int func, int only_name)
#define instr(n)
int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr, int min_string_length)
Definition: memory.cc:190
#define DYNTRANS_L2_64_TABLE
#define DYNTRANS_PAGESIZE
Definition: cpu_alpha.cc:50
int16_t int_to_assert
Definition: cpu_sh.h:157
#define ARM_FLAG_I
Definition: cpu_arm.h:92
#define DYNTRANS_PC_TO_POINTERS_FUNC
#define ALPHA_A0
Definition: cpu_alpha.h:93
#define DYNTRANS_MAX_VPH_TLB_ENTRIES
struct arm_cpu arm
Definition: cpu.h:441
void m88k_exception(struct cpu *cpu, int vector, int is_trap)
Definition: cpu_m88k.cc:648
#define EXCEPTION_INT
Definition: cop0.h:183
void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
Definition: cpu_sh.cc:632
#define DELAYED
Definition: cpu.h:306
#define DYNTRANS_ARCH
#define I
int enabled
Definition: machine.h:66
char * get_symbol_name(struct symbol_context *, uint64_t addr, uint64_t *offset)
Definition: symbol.cc:188
#define PPC_MSR_EE
Definition: cpu_ppc.h:159
#define DYNTRANS_DELAYSLOT
Definition: cpu_m88k.cc:58
#define M88K_EXCEPTION_INTERRUPT
uint32_t next_ofs
Definition: cpu.h:118
unsigned int int_level
Definition: cpu_sh.h:158
int debugger_n_steps_left_before_interaction
Definition: debugger.cc:73
int translation_readahead
Definition: cpu.h:424
int32_t count_register_read_count
Definition: cpu_mips.h:227
uint64_t pc
Definition: cpu.h:383
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
#define MIPS_SR_INT_IE
Definition: mips_cpuregs.h:154
#define DYNTRANS_TC_ALLOCATE_DEFAULT_PAGE_DEF
#define COP0_COMPARE
Definition: cop0.h:108
void arm_exception(struct cpu *cpu, int exception_nr)
Definition: cpu_arm.cc:589
#define M88K_CR_PSR
uint64_t reg[N_MIPS_COPROC_REGS]
Definition: cpu_mips.h:102
#define FLAG_INSTR
Definition: memory.h:138
#define ARM_EXCEPTION_IRQ
Definition: cpu_arm.h:121
#define R5900_STATUS_EIE
Definition: cop0.h:128
#define EXC3K
#define DISASSEMBLE
#define MIPS_R5900
Definition: mips_cpuregs.h:723
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:365
#define DYNTRANS_ALPHA
int instruction_trace
Definition: machine.h:162
#define DYNTRANS_L2N
struct interrupt irq_compare
Definition: cpu_mips.h:228
int64_t ninstrs
Definition: cpu.h:340
#define PPC_NO_DEC
Definition: cpu_ppc.h:66
size_t translation_cache_cur_ofs
Definition: cpu.h:429
int compare_interrupts_pending
Definition: cpu_mips.h:226
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
FILE * file
Definition: machine.h:65
uint8_t running
Definition: cpu.h:353
unsigned char * translation_cache
Definition: cpu.h:428
void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr, int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
Definition: cpu_mips.cc:1714
#define MEM_WRITE
Definition: memory.h:117
#define COP0_CAUSE
Definition: cop0.h:129
#define ENTER_SINGLE_STEPPING
Definition: debugger.h:48
int dec_intr_pending
Definition: cpu_ppc.h:119
#define SH_SR_IMASK_SHIFT
Definition: cpu_sh.h:188
volatile int single_step
Definition: debugger.cc:68
struct mips_coproc * coproc[N_MIPS_COPROCS]
Definition: cpu_mips.h:219
void cpu_register_dump(struct machine *m, struct cpu *cpu, int gprs, int coprocs)
Definition: cpu.cc:203
#define SH_SR_IMASK
Definition: cpu_sh.h:187
#define SPR_DEC
Definition: ppc_spr.h:54
int irq_asserted
Definition: cpu_arm.h:227
uint32_t addr
#define DYNTRANS_INVALIDATE_TLB_ENTRY
#define SH_SR_BL
Definition: cpu_sh.h:192
#define debug
Definition: dev_adb.cc:57
#define M88K_PSR_IND
Definition: m88k_psl.h:81
void ppc_exception(struct cpu *cpu, int exception_nr)
Definition: cpu_ppc.cc:352
int quiet_mode
Definition: emul.cc:68
uint32_t cr[N_M88K_CONTROL_REGS]
Definition: cpu_m88k.h:241
Definition: cpu.h:326
int(* instruction_has_delayslot)(struct cpu *cpu, unsigned char *ib)
Definition: cpu.h:379
#define DYNTRANS_L1N
Definition: cpu.h:222
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
#define INVALIDATE_PADDR
Definition: cpu.h:479
int register_dump
Definition: machine.h:150
int n_translated_instrs
Definition: cpu.h:427
#define CACHE_INSTRUCTION
Definition: memory.h:122
#define MEMORY_USER_ACCESS
Definition: memory.h:127
#define MAX_DYNTRANS_READAHEAD
Definition: cpu.h:313
#define STATUS_IM_MASK
Definition: cop0.h:117
struct symbol_context symbol_context
Definition: machine.h:144
#define STATUS_EXL
Definition: cop0.h:125
#define DYNTRANS_L3N
#define SPR_TBU
Definition: ppc_spr.h:74
#define DYNTRANS_IC_ENTRIES_PER_PAGE
#define DYNTRANS_PC_TO_IC_ENTRY
#define DYNTRANS_RUN_INSTR_DEF
int allow_instruction_combinations
Definition: machine.h:166
#define DYNTRANS_FUNCTION_TRACE_DEF
#define STATUS_IE
Definition: cop0.h:126
char * memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr, char *buf, int bufsize)
Definition: memory.cc:220
#define DYNTRANS_DUALMODE_32
Definition: cpu_mips.cc:73
#define ARM_FLAG_T
Definition: cpu_arm.h:94
#define EXCEPTION_IN_DELAY_SLOT
Definition: cpu.h:308
size_t dyntrans_cache_size
Definition: main.cc:65
void(* update_translation_table)(struct cpu *, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
Definition: cpu.h:371
#define DYNTRANS_INVALIDATE_TC_CODE
struct statistics statistics
Definition: machine.h:176
struct mips_cpu mips
Definition: cpu.h:443
int cpu_disassemble_instr(struct machine *m, struct cpu *cpu, unsigned char *instr, int running, uint64_t addr)
Definition: cpu.cc:183
addr & if(addr >=0x24 &&page !=NULL)
uint32_t cpsr
Definition: cpu_arm.h:167
char * fields
Definition: machine.h:67
#define PPC_EXCEPTION_DEC
Definition: cpu_ppc.h:193
Definition: symbol.h:37
#define N_SAFE_DYNTRANS_LIMIT
Definition: cpu.h:311
void cpu_create_or_reset_tc(struct cpu *cpu)
Definition: cpu.cc:289
#define MEM_DOWNGRADE
Definition: memory.h:118
#define DYNTRANS_TC_PHYSPAGE
struct m88k_cpu m88k
Definition: cpu.h:442
#define DYNTRANS_INSTR_ALIGNMENT_SHIFT
struct mips_cpu_type_def cpu_type
Definition: cpu_mips.h:206
#define DYNTRANS_IC
uint64_t * addr
Definition: machine.h:60
#define S
#define DYNTRANS_L3_64_TABLE
#define DYNTRANS_ADDR_TO_PAGENR
int irq_asserted
Definition: cpu_m88k.h:247
volatile int single_step_breakpoint
Definition: debugger.cc:72
#define PAGENR_TO_TABLE_INDEX(a)
Definition: cpu.h:319
struct sh_cpu sh
Definition: cpu.h:445
int compare_register_set
Definition: cpu_mips.h:225
struct ppc_cpu_type_def cpu_type
Definition: cpu_ppc.h:111
#define INVALIDATE_VADDR_UPPER4
Definition: cpu.h:481
void(* invalidate_translation_caches)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:374
#define PPC_EXCEPTION_EI
Definition: cpu_ppc.h:191
unsigned char * memory_paddr_to_hostaddr(struct memory *mem, uint64_t paddr, int writeflag)
Definition: memory.cc:495

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13