cpu_m88k_instr.cc Source File

Back to the index.

cpu_m88k_instr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-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  * M88K instructions.
29  *
30  * Individual functions should keep track of cpu->n_translated_instrs.
31  * (If no instruction was executed, then it should be decreased. If, say, 4
32  * instructions were combined into one function and executed, then it should
33  * be increased by 3.)
34  */
35 
36 
37 #define SYNCH_PC { \
38  int low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page) \
39  / sizeof(struct m88k_instr_call); \
40  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) \
41  << M88K_INSTR_ALIGNMENT_SHIFT); \
42  cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT); \
43  }
44 
45 #define ABORT_EXECUTION { SYNCH_PC; \
46  fatal("Execution aborted at: pc = 0x%08x\n", (int)cpu->pc); \
47  cpu->cd.m88k.next_ic = &nothing_call; \
48  cpu->running = 0; \
49  debugger_n_steps_left_before_interaction = 0; }
50 
51 
52 /*
53  * nop: Do nothing.
54  */
56 {
57 }
58 
59 
60 /*
61  * br_samepage: Branch (to within the same translated page)
62  * bsr_samepage: Branch to subroutine (to within the same translated page)
63  *
64  * arg[0] = pointer to new instr_call
65  * arg[2] = offset to return address, from start of page
66  */
67 X(br_samepage)
68 {
69  cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0];
70 }
71 X(bsr_samepage)
72 {
73  cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc &
75  + ic->arg[2];
76  cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[0];
77 }
78 
79 
80 /*
81  * br: Branch (to a different translated page)
82  * br.n: Branch (to a different translated page) with delay slot
83  * bsr: Branch to subroutine (to a different translated page)
84  * bsr.n: Branch to subroutine (to a different page) with delay slot
85  *
86  * arg[1] = relative offset from start of page
87  * arg[2] = offset to return address, from start of page
88  */
89 X(br)
90 {
91  cpu->pc = (uint32_t)((cpu->pc & 0xfffff000) + (int32_t)ic->arg[1]);
93 }
94 X(br_n)
95 {
97  M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[1];
99  ic[1].f(cpu, ic+1);
102  /* Note: Must be non-delayed when jumping to the new pc: */
106  } else
108 }
109 X(bsr)
110 {
111  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
113  cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2];
114  cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]);
116 }
117 X(bsr_n)
118 {
119  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
121  cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4;
122  cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1];
124  ic[1].f(cpu, ic+1);
127  /* Note: Must be non-delayed when jumping to the new pc: */
131  } else
133 }
134 X(bsr_trace)
135 {
136  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
138  cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2];
139  cpu->pc = (uint32_t) (cpu->pc + ic->arg[1]);
142 }
143 X(bsr_n_trace)
144 {
145  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
147  cpu->cd.m88k.r[M88K_RETURN_REG] = cpu->pc + ic->arg[2] + 4;
148  cpu->cd.m88k.delay_target = cpu->pc + ic->arg[1];
150  ic[1].f(cpu, ic+1);
153  /* Note: Must be non-delayed when jumping to the new pc: */
158  } else
160 }
161 
162 
163 /*
164  * bb? Branch if a bit in a register is 0 or 1.
165  * bb?_samepage: Branch within the same translated page.
166  * bb?_n_*: With delay slot.
167  *
168  * arg[0] = pointer to source register to test (s1).
169  * arg[1] = uint32_t mask to test (e.g. 0x00010000 to test bit 16)
170  * arg[2] = offset from start of current page _OR_ pointer to new instr_call
171  */
172 X(bb0)
173 {
174  if (!(reg(ic->arg[0]) & ic->arg[1])) {
175  cpu->pc = (cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
177  }
178 }
179 X(bb0_samepage)
180 {
181  if (!(reg(ic->arg[0]) & ic->arg[1]))
182  cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[2];
183 }
184 X(bb0_n)
185 {
186  int cond = !(reg(ic->arg[0]) & (uint32_t)ic->arg[1]);
187 
188  SYNCH_PC;
189 
190  if (cond)
192  (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
193  M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2];
194  else
195  cpu->cd.m88k.delay_target = cpu->pc + 8;
196 
198  ic[1].f(cpu, ic+1);
201  /* Note: Must be non-delayed when jumping to the new pc: */
203  if (cond) {
206  } else
207  cpu->cd.m88k.next_ic ++;
208  } else
210 }
211 X(bb1)
212 {
213  if (reg(ic->arg[0]) & ic->arg[1]) {
214  cpu->pc = (cpu->pc & 0xfffff000) + (int32_t)ic->arg[2];
216  }
217 }
218 X(bb1_samepage)
219 {
220  if (reg(ic->arg[0]) & ic->arg[1])
221  cpu->cd.m88k.next_ic = (struct m88k_instr_call *) ic->arg[2];
222 }
223 X(bb1_n)
224 {
225  int cond = reg(ic->arg[0]) & ic->arg[1];
226 
227  SYNCH_PC;
228 
229  if (cond)
231  (cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
232  M88K_INSTR_ALIGNMENT_SHIFT)) + (int32_t)ic->arg[2];
233  else
234  cpu->cd.m88k.delay_target = cpu->pc + 8;
235 
237  ic[1].f(cpu, ic+1);
240  /* Note: Must be non-delayed when jumping to the new pc: */
242  if (cond) {
245  } else
246  cpu->cd.m88k.next_ic ++;
247  } else
249 }
250 
251 
252 /*
253  * ff0, ff1: Find first cleared/set bit in a register
254  *
255  * arg[0] = pointer to register d
256  * arg[2] = pointer to register s2
257  */
258 X(ff0)
259 {
260  uint32_t mask = 0x80000000, s2 = reg(ic->arg[2]);
261  int n = 31;
262 
263  for (;;) {
264  if (!(s2 & mask)) {
265  reg(ic->arg[0]) = n;
266  return;
267  }
268  mask >>= 1; n--;
269  if (mask == 0) {
270  reg(ic->arg[0]) = 32;
271  return;
272  }
273  }
274 }
275 X(ff1)
276 {
277  uint32_t mask = 0x80000000, s2 = reg(ic->arg[2]);
278  int n = 31;
279 
280  for (;;) {
281  if (s2 & mask) {
282  reg(ic->arg[0]) = n;
283  return;
284  }
285  mask >>= 1; n--;
286  if (mask == 0) {
287  reg(ic->arg[0]) = 32;
288  return;
289  }
290  }
291 }
292 
293 
294 /* Include all automatically generated bcnd and bcnd.n instructions: */
295 #include "tmp_m88k_bcnd.cc"
296 
297 
298 /* Include all automatically generated load/store instructions: */
299 #include "tmp_m88k_loadstore.cc"
300 #define M88K_LOADSTORE_STORE 4
301 #define M88K_LOADSTORE_SIGNEDNESS 8
302 #define M88K_LOADSTORE_ENDIANNESS 16
303 #define M88K_LOADSTORE_SCALEDNESS 32
304 #define M88K_LOADSTORE_USR 64
305 #define M88K_LOADSTORE_REGISTEROFFSET 128
306 
307 
308 /*
309  * jmp: Jump to register
310  * jmp.n: Jump to register, with delay slot
311  * jsr: Jump to register, set r1 to return address
312  * jsr.n: Jump to register, set r1 to return address, with delay slot
313  *
314  * arg[1] = offset to return address, from start of current page
315  * arg[2] = pointer to register s2
316  */
317 X(jmp)
318 {
319  cpu->pc = reg(ic->arg[2]) & ~3;
321 }
322 X(jmp_n)
323 {
324  cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
326  ic[1].f(cpu, ic+1);
329  /* Note: Must be non-delayed when jumping to the new pc: */
333  } else
335 }
336 X(jmp_trace)
337 {
338  cpu->pc = reg(ic->arg[2]) & ~3;
341 }
342 X(jmp_n_trace)
343 {
344  cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
346  ic[1].f(cpu, ic+1);
349  /* Note: Must be non-delayed when jumping to the new pc: */
354  } else
356 }
357 X(jsr)
358 {
359  cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
360  cpu->pc = reg(ic->arg[2]) & ~3;
362 }
363 X(jsr_n)
364 {
365  cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
366  cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
368  ic[1].f(cpu, ic+1);
371  /* Note: Must be non-delayed when jumping to the new pc: */
375  } else
377 }
378 X(jsr_trace)
379 {
380  cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
381  cpu->pc = reg(ic->arg[2]) & ~3;
384 }
385 X(jsr_n_trace)
386 {
387  cpu->cd.m88k.delay_target = reg(ic->arg[2]) & ~3;
388  cpu->cd.m88k.r[M88K_RETURN_REG] = (cpu->pc & 0xfffff000) + ic->arg[1];
390  ic[1].f(cpu, ic+1);
393  /* Note: Must be non-delayed when jumping to the new pc: */
398  } else
400 }
401 
402 
403 /*
404  * cmp_imm: Compare S1 with immediate value.
405  * cmp: Compare S1 with S2.
406  *
407  * arg[0] = pointer to register d
408  * arg[1] = pointer to register s1
409  * arg[2] = pointer to register s2 or imm
410  */
411 static void m88k_cmp(struct cpu *cpu, struct m88k_instr_call *ic, uint32_t y)
412 {
413  uint32_t x = reg(ic->arg[1]);
414  uint32_t r;
415 
416  if (x == y) {
419  } else {
420  if (x > y)
422  else
424  if ((int32_t)x > (int32_t)y)
425  r |= M88K_CMP_GE | M88K_CMP_GT;
426  else
427  r |= M88K_CMP_LT | M88K_CMP_LE;
428  }
429 
430  reg(ic->arg[0]) = r;
431 }
432 X(cmp_imm) { m88k_cmp(cpu, ic, ic->arg[2]); }
433 X(cmp) { m88k_cmp(cpu, ic, reg(ic->arg[2])); }
434 
435 
436 /*
437  * extu_imm: Extract bits, unsigned, immediate W<O>.
438  * extu: Extract bits, unsigned, W<O> taken from register s2.
439  * ext_imm: Extract bits, signed, immediate W<O>.
440  * ext: Extract bits, signed, W<O> taken from register s2.
441  * mak_imm: Make bit field, immediate W<O>.
442  * mak: Make bit field, W<O> taken from register s2.
443  * rot: Rotate s1 right, nr of steps taken from s2.
444  * clr: Clear bits, W<O> taken from register s2.
445  * set: Set bits, W<O> taken from register s2.
446  *
447  * arg[0] = pointer to register d
448  * arg[1] = pointer to register s1
449  * arg[2] = pointer to register s2 or 10 bits wwwwwooooo
450  */
451 static void m88k_extu(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
452 {
453  uint32_t x = reg(ic->arg[1]) >> o;
454  if (w != 0) {
455  x <<= (32-w);
456  x >>= (32-w);
457  }
458  reg(ic->arg[0]) = x;
459 }
460 static void m88k_ext(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
461 {
462  int32_t x = reg(ic->arg[1]);
463  x >>= o; /* signed (arithmetic) shift */
464  if (w != 0) {
465  x <<= (32-w);
466  x >>= (32-w);
467  }
468  reg(ic->arg[0]) = x;
469 }
470 static void m88k_mak(struct cpu *cpu, struct m88k_instr_call *ic, int w, int o)
471 {
472  uint32_t x = reg(ic->arg[1]);
473  if (w != 0) {
474  x <<= (32-w);
475  x >>= (32-w);
476  }
477  reg(ic->arg[0]) = x << o;
478 }
479 X(extu_imm)
480 {
481  m88k_extu(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
482 }
483 X(extu)
484 {
485  m88k_extu(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
486  reg(ic->arg[2]) & 0x1f);
487 }
488 X(ext_imm)
489 {
490  m88k_ext(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
491 }
492 X(ext)
493 {
494  m88k_ext(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
495  reg(ic->arg[2]) & 0x1f);
496 }
497 X(mak_imm)
498 {
499  m88k_mak(cpu, ic, ic->arg[2] >> 5, ic->arg[2] & 0x1f);
500 }
501 X(mak)
502 {
503  m88k_mak(cpu, ic, (reg(ic->arg[2]) >> 5) & 0x1f,
504  reg(ic->arg[2]) & 0x1f);
505 }
506 static void m88k_rot(struct cpu *cpu, struct m88k_instr_call *ic, int n)
507 {
508  uint32_t x = reg(ic->arg[1]);
509 
510  if (n != 0) {
511  uint32_t mask = (1 << n) - 1;
512  uint32_t bits = x & mask;
513  x >>= n;
514  x |= (bits << (32-n));
515  }
516 
517  reg(ic->arg[0]) = x;
518 }
519 X(rot)
520 {
521  m88k_rot(cpu, ic, reg(ic->arg[2]) & 0x1f);
522 }
523 X(clr)
524 {
525  int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f;
526  uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1;
527  x <<= o;
528  reg(ic->arg[0]) = reg(ic->arg[1]) & ~x;
529 }
530 X(set)
531 {
532  int w = (reg(ic->arg[2]) >> 5) & 0x1f, o = reg(ic->arg[2]) & 0x1f;
533  uint32_t x = w == 0? 0xffffffff : ((uint32_t)1 << w) - 1;
534  x <<= o;
535  reg(ic->arg[0]) = reg(ic->arg[1]) | x;
536 }
537 
538 
539 /*
540  * or_r0_imm0: d = 0 (optimized case when s1 = r0, imm = 0)
541  * or_r0_imm: d = imm (optimized case when s1 = r0)
542  * or_imm: d = s1 | imm
543  * xor_imm: d = s1 ^ imm
544  * and_imm: d = (s1 & imm) | (s1 & 0xffff0000)
545  * and_u_imm: d = (s1 & imm) | (s1 & 0xffff)
546  * mask_imm: d = s1 & imm
547  * add_imm: d = s1 - imm (addition with overflow exception)
548  * addu_imm: d = s1 + imm
549  * subu_imm: d = s1 - imm
550  * inc_reg: d ++; (addu special case; d = d + 1)
551  * dec_reg: d --; (subu special case; d = d - 1)
552  * mulu_imm: d = s1 * imm
553  * divu_imm: d = s1 / imm (unsigned)
554  * div_imm: d = s1 / imm (signed)
555  * sub_imm: d = s1 - imm (subtraction with overflow exception)
556  *
557  * arg[0] = pointer to register d
558  * arg[1] = pointer to register s1
559  * arg[2] = imm
560  */
561 X(or_r0_imm0) { reg(ic->arg[0]) = 0; }
562 X(or_r0_imm) { reg(ic->arg[0]) = ic->arg[2]; }
563 X(or_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) | ic->arg[2]; }
564 X(xor_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) ^ ic->arg[2]; }
565 X(and_imm) { reg(ic->arg[0]) = (reg(ic->arg[1]) & ic->arg[2])
566  | (reg(ic->arg[1]) & 0xffff0000); }
567 X(and_u_imm) { reg(ic->arg[0]) = (reg(ic->arg[1]) & ic->arg[2])
568  | (reg(ic->arg[1]) & 0xffff); }
569 X(mask_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) & ic->arg[2]; }
570 X(add_imm)
571 {
572  uint64_t a = (int32_t) reg(ic->arg[1]);
573  uint64_t b = ic->arg[2];
574  uint64_t res = a + b;
575  uint64_t res2 = (int32_t) res;
576 
577  if (res != res2) {
578  SYNCH_PC;
580  return;
581  }
582 
583  reg(ic->arg[0]) = res;
584 }
585 X(addu_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) + ic->arg[2]; }
586 X(subu_imm) { reg(ic->arg[0]) = reg(ic->arg[1]) - ic->arg[2]; }
587 X(inc_reg) { reg(ic->arg[0]) ++; }
588 X(dec_reg) { reg(ic->arg[0]) --; }
589 X(mulu_imm)
590 {
592  SYNCH_PC;
595  } else
596  reg(ic->arg[0]) = reg(ic->arg[1]) * ic->arg[2];
597 }
598 X(divu_imm)
599 {
601  SYNCH_PC;
604  } else if (ic->arg[2] == 0) {
605  SYNCH_PC;
607  } else
608  reg(ic->arg[0]) = (uint32_t) reg(ic->arg[1]) / (uint32_t) ic->arg[2];
609 }
610 X(div_imm)
611 {
613  SYNCH_PC;
616  } else if (ic->arg[2] == 0) {
617  SYNCH_PC;
619  } else {
620  int32_t res = (int32_t) reg(ic->arg[1]) / (int32_t) ic->arg[2];
621  reg(ic->arg[0]) = res;
622  }
623 }
624 X(sub_imm)
625 {
626  uint64_t a = (int32_t) reg(ic->arg[1]);
627  uint64_t b = ic->arg[2];
628  uint64_t res = a - b;
629  uint64_t res2 = (int32_t) res;
630 
631  if (res != res2) {
632  SYNCH_PC;
634  return;
635  }
636 
637  reg(ic->arg[0]) = res;
638 }
639 
640 
641 /*
642  * or: d = s1 | s2
643  * or_c: d = s1 | ~s2
644  * or_r0: d = s2
645  * xor: d = s1 ^ s2
646  * xor_c: d = s1 ^ ~s2
647  * and: d = s1 & s2
648  * and_c: d = s1 & ~s2
649  * add: d = s1 + s2 with trap on overflow
650  * addu: d = s1 + s2
651  * addu_co: d = s1 + s2 carry out
652  * addu_ci: d = s1 + s2 + carry carry in
653  * lda_reg_X: same as addu, but s2 is scaled by 2, 4, or 8
654  * subu: d = s1 - s2
655  * subu_co: d = s1 - s2 carry/borrow out
656  * subu_ci: d = s1 - s2 - (carry? 0 : 1) carry in
657  * mul: d = s1 * s2
658  * divu: d = s1 / s2 (unsigned)
659  * div: d = s1 / s2 (signed)
660  *
661  * arg[0] = pointer to register d
662  * arg[1] = pointer to register s1
663  * arg[2] = pointer to register s2
664  */
665 X(or) { reg(ic->arg[0]) = reg(ic->arg[1]) | reg(ic->arg[2]); }
666 X(or_c) { reg(ic->arg[0]) = reg(ic->arg[1]) | ~(reg(ic->arg[2])); }
667 X(or_r0){ reg(ic->arg[0]) = reg(ic->arg[2]); }
668 X(xor) { reg(ic->arg[0]) = reg(ic->arg[1]) ^ reg(ic->arg[2]); }
669 X(xor_c){ reg(ic->arg[0]) = reg(ic->arg[1]) ^ ~(reg(ic->arg[2])); }
670 X(and) { reg(ic->arg[0]) = reg(ic->arg[1]) & reg(ic->arg[2]); }
671 X(and_c){ reg(ic->arg[0]) = reg(ic->arg[1]) & ~(reg(ic->arg[2])); }
672 X(addu) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]); }
673 X(addu_s2r0) { reg(ic->arg[0]) = reg(ic->arg[1]); }
674 X(lda_reg_2) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 2; }
675 X(lda_reg_4) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 4; }
676 X(lda_reg_8) { reg(ic->arg[0]) = reg(ic->arg[1]) + reg(ic->arg[2]) * 8; }
677 X(subu) { reg(ic->arg[0]) = reg(ic->arg[1]) - reg(ic->arg[2]); }
678 X(add)
679 {
680  uint64_t s1 = (int32_t) reg(ic->arg[1]);
681  uint64_t s2 = (int32_t) reg(ic->arg[2]);
682  uint64_t d = s1 + s2;
683  uint64_t dx = (int32_t) d;
684 
685  /* "If the result cannot be represented as a signed 32-bit integer"
686  then there should be an exception. */
687  if (d != dx) {
688  SYNCH_PC;
690  } else {
691  reg(ic->arg[0]) = d;
692  }
693 }
694 X(mul)
695 {
697  SYNCH_PC;
700  } else
701  reg(ic->arg[0]) = reg(ic->arg[1]) * reg(ic->arg[2]);
702 }
703 X(divu)
704 {
706  SYNCH_PC;
709  } else if (reg(ic->arg[2]) == 0) {
710  SYNCH_PC;
712  } else
713  reg(ic->arg[0]) = (uint32_t) reg(ic->arg[1]) / (uint32_t) reg(ic->arg[2]);
714 }
715 X(div)
716 {
718  SYNCH_PC;
721  } else if (reg(ic->arg[2]) == 0) {
722  SYNCH_PC;
724  } else {
725  int32_t res = (int32_t) reg(ic->arg[1]) / (int32_t) reg(ic->arg[2]);
726  reg(ic->arg[0]) = res;
727  }
728 }
729 X(addu_co)
730 {
731  uint64_t a = reg(ic->arg[1]), b = reg(ic->arg[2]);
732  a += b;
733  reg(ic->arg[0]) = a;
735  if ((a >> 32) & 1)
737 }
738 X(addu_ci)
739 {
740  uint32_t result = reg(ic->arg[1]) + reg(ic->arg[2]);
742  result ++;
743  reg(ic->arg[0]) = result;
744 }
745 X(subu_co)
746 {
747  uint64_t a = reg(ic->arg[1]), b = reg(ic->arg[2]);
748  a -= b;
749  reg(ic->arg[0]) = a;
751  if ((a >> 32) & 1)
753 }
754 X(subu_ci)
755 {
756  uint32_t result = reg(ic->arg[1]) - reg(ic->arg[2]);
758  result --;
759  reg(ic->arg[0]) = result;
760 }
761 
762 
763 /*
764  * ldcr: Load value from a control register, store in register d.
765  * fldcr: Load value from a floating point control register, store in reg d.
766  *
767  * arg[0] = pointer to register d
768  * arg[1] = 6-bit control register number
769  */
770 X(ldcr)
771 {
772  SYNCH_PC;
773 
775  m88k_ldcr(cpu, (uint32_t *) (void *) ic->arg[0], ic->arg[1]);
776  else
778 }
779 X(fldcr)
780 {
781  SYNCH_PC;
782 
783  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE || ic->arg[1] >= 62)
784  reg(ic->arg[0]) = cpu->cd.m88k.fcr[ic->arg[1]];
785  else {
786  /* TODO: The manual says "floating point privilege
787  violation", not just "privilege violation"! */
789  }
790 }
791 
792 
793 /*
794  * stcr: Store a value into a control register.
795  * fstcr: Store a value into a floating point control register.
796  *
797  * arg[0] = pointer to source register
798  * arg[1] = 6-bit control register number
799  */
800 X(stcr)
801 {
802  SYNCH_PC;
803 
805  m88k_stcr(cpu, reg(ic->arg[0]), ic->arg[1], 0);
806  else
808 }
809 X(fstcr)
810 {
811  SYNCH_PC;
812 
813  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE || ic->arg[1] >= 62)
814  m88k_fstcr(cpu, reg(ic->arg[0]), ic->arg[1]);
815  else {
816  /* TODO: The manual says "floating point privilege
817  violation", not just "privilege violation"! */
819  }
820 }
821 
822 
823 /*
824  * fadd.xxx: Floating point addition
825  * fsub.xxx: Floating point subtraction
826  * fmul.xxx: Floating point multiplication
827  * fdiv.xxx: Floating point multiplication
828  *
829  * arg[0] = pointer to destination register
830  * arg[1] = pointer to source register s1
831  * arg[2] = pointer to source register s2
832  *
833  * Note: For 'd' variants, arg[x] points to a _pair_ of registers!
834  */
835 X(fadd_sss)
836 {
837  struct ieee_float_value f1;
838  struct ieee_float_value f2;
839  uint32_t d;
840  uint32_t s2 = reg(ic->arg[2]);
841  uint32_t s1 = reg(ic->arg[1]);
842 
844  SYNCH_PC;
847  return;
848  }
849 
852 
853  d = ieee_store_float_value(f1.f + f2.f, IEEE_FMT_S);
854 
855  reg(ic->arg[0]) = d;
856 }
857 X(fadd_dsd)
858 {
859  struct ieee_float_value f1;
860  struct ieee_float_value f2;
861  uint64_t d;
862  uint64_t s2 = reg(ic->arg[2]);
863  uint32_t s1 = reg(ic->arg[1]);
864  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
865 
867  SYNCH_PC;
870  return;
871  }
872 
875 
876  d = ieee_store_float_value(f1.f + f2.f, IEEE_FMT_D);
877 
878  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
879  reg(ic->arg[0] + 4) = d; /* and low word. */
880 }
881 X(fadd_dds)
882 {
883  struct ieee_float_value f1;
884  struct ieee_float_value f2;
885  uint64_t d;
886  uint32_t s2 = reg(ic->arg[2]);
887  uint64_t s1 = reg(ic->arg[1]);
888  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
889 
891  SYNCH_PC;
894  return;
895  }
896 
899 
900  d = ieee_store_float_value(f1.f + f2.f, IEEE_FMT_D);
901 
902  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
903  reg(ic->arg[0] + 4) = d; /* and low word. */
904 }
905 X(fadd_ddd)
906 {
907  struct ieee_float_value f1;
908  struct ieee_float_value f2;
909  uint64_t d;
910  uint64_t s1 = reg(ic->arg[1]);
911  uint64_t s2 = reg(ic->arg[2]);
912  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
913  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
914 
916  SYNCH_PC;
919  return;
920  }
921 
924 
925  d = ieee_store_float_value(f1.f + f2.f, IEEE_FMT_D);
926 
927  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
928  reg(ic->arg[0] + 4) = d; /* and low word. */
929 }
930 X(fsub_sds)
931 {
932  struct ieee_float_value f1;
933  struct ieee_float_value f2;
934  uint32_t d;
935  uint32_t s2 = reg(ic->arg[2]);
936  uint64_t s1 = reg(ic->arg[1]);
937  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
938 
940  SYNCH_PC;
943  return;
944  }
945 
948 
949  d = ieee_store_float_value(f1.f - f2.f, IEEE_FMT_S);
950  reg(ic->arg[0]) = d;
951 }
952 X(fsub_dss)
953 {
954  struct ieee_float_value f1;
955  struct ieee_float_value f2;
956  uint64_t d;
957  uint32_t s2 = reg(ic->arg[2]);
958  uint32_t s1 = reg(ic->arg[1]);
959 
961  SYNCH_PC;
964  return;
965  }
966 
969 
970  d = ieee_store_float_value(f1.f - f2.f, IEEE_FMT_D);
971 
972  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
973  reg(ic->arg[0] + 4) = d; /* and low word. */
974 }
975 X(fsub_dsd)
976 {
977  struct ieee_float_value f1;
978  struct ieee_float_value f2;
979  uint64_t d;
980  uint64_t s2 = reg(ic->arg[2]);
981  uint32_t s1 = reg(ic->arg[1]);
982  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
983 
985  SYNCH_PC;
988  return;
989  }
990 
993 
994  d = ieee_store_float_value(f1.f - f2.f, IEEE_FMT_D);
995 
996  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
997  reg(ic->arg[0] + 4) = d; /* and low word. */
998 }
999 X(fsub_dds)
1000 {
1001  struct ieee_float_value f1;
1002  struct ieee_float_value f2;
1003  uint64_t d;
1004  uint32_t s2 = reg(ic->arg[2]);
1005  uint64_t s1 = reg(ic->arg[1]);
1006  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1007 
1008  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1009  SYNCH_PC;
1012  return;
1013  }
1014 
1017 
1018  d = ieee_store_float_value(f1.f - f2.f, IEEE_FMT_D);
1019 
1020  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1021  reg(ic->arg[0] + 4) = d; /* and low word. */
1022 }
1023 X(fsub_ddd)
1024 {
1025  struct ieee_float_value f1;
1026  struct ieee_float_value f2;
1027  uint64_t d;
1028  uint64_t s1 = reg(ic->arg[1]);
1029  uint64_t s2 = reg(ic->arg[2]);
1030  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1031  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1032 
1033  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1034  SYNCH_PC;
1037  return;
1038  }
1039 
1042 
1043  d = ieee_store_float_value(f1.f - f2.f, IEEE_FMT_D);
1044 
1045  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1046  reg(ic->arg[0] + 4) = d; /* and low word. */
1047 }
1048 X(fmul_sss)
1049 {
1050  struct ieee_float_value f1;
1051  struct ieee_float_value f2;
1052  uint32_t d;
1053  uint32_t s2 = reg(ic->arg[2]);
1054  uint32_t s1 = reg(ic->arg[1]);
1055 
1056  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1057  SYNCH_PC;
1060  return;
1061  }
1062 
1065 
1066  d = ieee_store_float_value(f1.f * f2.f, IEEE_FMT_S);
1067  reg(ic->arg[0]) = d;
1068 }
1069 X(fmul_dss)
1070 {
1071  struct ieee_float_value f1;
1072  struct ieee_float_value f2;
1073  uint64_t d;
1074  uint32_t s2 = reg(ic->arg[2]);
1075  uint32_t s1 = reg(ic->arg[1]);
1076 
1077  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1078  SYNCH_PC;
1081  return;
1082  }
1083 
1086 
1087  d = ieee_store_float_value(f1.f * f2.f, IEEE_FMT_D);
1088 
1089  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1090  reg(ic->arg[0] + 4) = d; /* and low word. */
1091 }
1092 X(fmul_dsd)
1093 {
1094  struct ieee_float_value f1;
1095  struct ieee_float_value f2;
1096  uint64_t d;
1097  uint64_t s2 = reg(ic->arg[2]);
1098  uint32_t s1 = reg(ic->arg[1]);
1099  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1100 
1101  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1102  SYNCH_PC;
1105  return;
1106  }
1107 
1110 
1111  d = ieee_store_float_value(f1.f * f2.f, IEEE_FMT_D);
1112 
1113  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1114  reg(ic->arg[0] + 4) = d; /* and low word. */
1115 }
1116 X(fmul_dds)
1117 {
1118  struct ieee_float_value f1;
1119  struct ieee_float_value f2;
1120  uint64_t d;
1121  uint32_t s2 = reg(ic->arg[2]);
1122  uint64_t s1 = reg(ic->arg[1]);
1123  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1124 
1125  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1126  SYNCH_PC;
1129  return;
1130  }
1131 
1134 
1135  d = ieee_store_float_value(f1.f * f2.f, IEEE_FMT_D);
1136 
1137  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1138  reg(ic->arg[0] + 4) = d; /* and low word. */
1139 }
1140 X(fmul_ddd)
1141 {
1142  struct ieee_float_value f1;
1143  struct ieee_float_value f2;
1144  uint64_t d;
1145  uint64_t s1 = reg(ic->arg[1]);
1146  uint64_t s2 = reg(ic->arg[2]);
1147  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1148  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1149 
1150  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1151  SYNCH_PC;
1154  return;
1155  }
1156 
1159 
1160  d = ieee_store_float_value(f1.f * f2.f, IEEE_FMT_D);
1161 
1162  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1163  reg(ic->arg[0] + 4) = d; /* and low word. */
1164 }
1165 X(fdiv_sss)
1166 {
1167  struct ieee_float_value f1;
1168  struct ieee_float_value f2;
1169  uint32_t d;
1170  uint32_t s1 = reg(ic->arg[1]);
1171  uint32_t s2 = reg(ic->arg[2]);
1172 
1173  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1174  SYNCH_PC;
1177  return;
1178  }
1179 
1182 
1183  if (f2.f == 0) {
1184  SYNCH_PC;
1187  return;
1188  }
1189 
1190  d = ieee_store_float_value(f1.f / f2.f, IEEE_FMT_D);
1191 
1192  reg(ic->arg[0]) = d;
1193 }
1194 X(fdiv_dsd)
1195 {
1196  struct ieee_float_value f1;
1197  struct ieee_float_value f2;
1198  uint64_t d;
1199  uint32_t s1 = reg(ic->arg[1]);
1200  uint64_t s2 = reg(ic->arg[2]);
1201  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1202 
1203  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1204  SYNCH_PC;
1207  return;
1208  }
1209 
1212 
1213  if (f2.f == 0) {
1214  SYNCH_PC;
1217  return;
1218  }
1219 
1220  d = ieee_store_float_value(f1.f / f2.f, IEEE_FMT_D);
1221 
1222  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1223  reg(ic->arg[0] + 4) = d; /* and low word. */
1224 }
1225 X(fdiv_ddd)
1226 {
1227  struct ieee_float_value f1;
1228  struct ieee_float_value f2;
1229  uint64_t d;
1230  uint64_t s1 = reg(ic->arg[1]);
1231  uint64_t s2 = reg(ic->arg[2]);
1232  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1233  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1234 
1235  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1236  SYNCH_PC;
1239  return;
1240  }
1241 
1244 
1245  if (f2.f == 0) {
1246  SYNCH_PC;
1249  return;
1250  }
1251 
1252  d = ieee_store_float_value(f1.f / f2.f, IEEE_FMT_D);
1253 
1254  reg(ic->arg[0]) = d >> 32; /* High 32-bit word, */
1255  reg(ic->arg[0] + 4) = d; /* and low word. */
1256 }
1257 
1258 
1259 /*
1260  * fcmp.sXX: Floating point comparison
1261  *
1262  * arg[0] = pointer to destination register
1263  * arg[1] = pointer to source register s1
1264  * arg[2] = pointer to source register s2
1265  *
1266  * Note: For 'd' variants, arg[x] points to a _pair_ of registers!
1267  */
1268 static uint32_t m88k_fcmp_common(struct ieee_float_value *f1,
1269  struct ieee_float_value *f2)
1270 {
1271  uint32_t d;
1272 
1273  /* TODO: Implement all bits correctly, e.g. "in range" bits. */
1274  d = 0;
1275  if (isnan(f1->f) || isnan(f2->f))
1276  d |= (1 << 0);
1277  else {
1278  d |= (1 << 1);
1279  if (f1->f == f2->f)
1280  d |= (1 << 2);
1281  else
1282  d |= (1 << 3);
1283  if (f1->f > f2->f)
1284  d |= (1 << 4);
1285  else
1286  d |= (1 << 5);
1287  if (f1->f < f2->f)
1288  d |= (1 << 6);
1289  else
1290  d |= (1 << 7);
1291  }
1292 
1293  return d;
1294 }
1295 X(fcmp_sds)
1296 {
1297  struct ieee_float_value f1;
1298  struct ieee_float_value f2;
1299  uint32_t s2 = reg(ic->arg[2]);
1300  uint64_t s1 = reg(ic->arg[1]);
1301  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1302 
1303  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1304  SYNCH_PC;
1307  return;
1308  }
1309 
1312  reg(ic->arg[0]) = m88k_fcmp_common(&f1, &f2);
1313 }
1314 X(fcmp_sdd)
1315 {
1316  struct ieee_float_value f1;
1317  struct ieee_float_value f2;
1318  uint64_t s1 = reg(ic->arg[1]);
1319  uint64_t s2 = reg(ic->arg[2]);
1320  s1 = (s1 << 32) + reg(ic->arg[1] + 4);
1321  s2 = (s2 << 32) + reg(ic->arg[2] + 4);
1322 
1323  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1324  SYNCH_PC;
1327  return;
1328  }
1329 
1332  reg(ic->arg[0]) = m88k_fcmp_common(&f1, &f2);
1333 }
1334 
1335 
1336 /*
1337  * flt.ss and flt.ds: Convert integer to floating point.
1338  *
1339  * arg[0] = pointer to destination register
1340  * arg[1] = pointer to source register s2
1341  *
1342  * Note: For flt.ds, arg[0] points to a _pair_ of registers!
1343  */
1344 X(flt_ss)
1345 {
1346  int32_t x = reg(ic->arg[1]);
1347 
1348  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1349  SYNCH_PC;
1352  return;
1353  }
1354 
1355  reg(ic->arg[0]) = ieee_store_float_value((double)x, IEEE_FMT_S);
1356 }
1357 X(flt_ds)
1358 {
1359  int32_t x = reg(ic->arg[1]);
1360  uint64_t result;
1361 
1362  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1363  SYNCH_PC;
1366  return;
1367  }
1368 
1369  result = ieee_store_float_value((double)x, IEEE_FMT_D);
1370 
1371  reg(ic->arg[0]) = result >> 32; /* High 32-bit word, */
1372  reg(ic->arg[0] + 4) = result; /* and low word. */
1373 }
1374 
1375 
1376 /*
1377  * trnc.ss and trnc.sd: Truncate floating point to interger.
1378  *
1379  * arg[0] = pointer to destination register
1380  * arg[1] = pointer to source register s2
1381  *
1382  * Note: For trnc.sd, arg[1] points to a _pair_ of registers!
1383  */
1384 X(trnc_ss)
1385 {
1386  struct ieee_float_value f1;
1387  ieee_interpret_float_value(reg(ic->arg[1]), &f1, IEEE_FMT_S);
1388 
1389  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1390  SYNCH_PC;
1393  return;
1394  }
1395 
1396  reg(ic->arg[0]) = (int32_t) f1.f;
1397 }
1398 X(trnc_sd)
1399 {
1400  struct ieee_float_value f1;
1401  uint64_t x = reg(ic->arg[1]);
1402  x = (x << 32) + reg(ic->arg[1] + 4);
1404 
1405  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFD1) {
1406  SYNCH_PC;
1409  return;
1410  }
1411 
1412  reg(ic->arg[0]) = (int32_t) f1.f;
1413 }
1414 
1415 
1416 /*
1417  * xcr: Exchange (load + store) control register.
1418  *
1419  * arg[0] = pointer to register d
1420  * arg[1] = pointer to register s1
1421  * arg[2] = 6-bit control register number
1422  */
1423 X(xcr)
1424 {
1425  uint32_t tmp, tmp2;
1426  SYNCH_PC;
1427 
1428  if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE) {
1429  tmp = reg(ic->arg[1]);
1430  m88k_ldcr(cpu, &tmp2, ic->arg[2]);
1431  m88k_stcr(cpu, tmp, ic->arg[2], 0);
1432  reg(ic->arg[0]) = tmp2;
1433  } else
1435 }
1436 
1437 
1438 /*
1439  * rte: Return from exception
1440  */
1441 X(rte)
1442 {
1443  /* If executed from user mode, then cause an exception: */
1444  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) {
1445  SYNCH_PC;
1447  return;
1448  }
1449 
1451 
1452  if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_E) {
1453  fatal("rte: NIP: TODO: single-step support\n");
1454  goto abort_dump;
1455  }
1456 
1457  if (cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_E) {
1458  fatal("rte: TODO: FIP single-step support\n");
1459  goto abort_dump;
1460  }
1461 
1462  /* First try the NIP, if it is Valid: */
1464 
1465  /* If the NIP is not valid, then try the FIP: */
1466  if (!(cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_V)) {
1467  /* Neither the NIP nor the FIP valid? */
1468  if (!(cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_V)) {
1470  != (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR) + 4) {
1471  fatal("[ TODO: Neither FIP nor NIP has the "
1472  "Valid bit set?! ]\n");
1473  goto abort_dump;
1474  }
1475 
1476  /* For now, continue anyway, using NIP. */
1477  } else {
1479  }
1480  } else if (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_V &&
1483  != (cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR) + 4) {
1484  /*
1485  * The NIP instruction should first be executed (this
1486  * is the one the exception handler choose to return to),
1487  * and then the FIP instruction should run (the target
1488  * of a delayed branch).
1489  */
1490 
1491  uint32_t nip = cpu->cd.m88k.cr[M88K_CR_SNIP] & M88K_NIP_ADDR;
1492  uint32_t fip = cpu->cd.m88k.cr[M88K_CR_SFIP] & M88K_FIP_ADDR;
1493 
1494  cpu->pc = nip;
1497 
1498  if (cpu->pc != nip) {
1499  fatal("NIP execution caused exception?! TODO\n");
1500  goto abort_dump;
1501  }
1502 
1503  instr(to_be_translated)(cpu, cpu->cd.m88k.next_ic);
1504 
1505  if ((cpu->pc & 0xfffff000) != (nip & 0xfffff000)) {
1506  fatal("instruction in delay slot when returning via"
1507  " rte caused an exception?! nip=0x%08x, but pc "
1508  "changed to 0x%08x! TODO\n", nip, (int)cpu->pc);
1509  goto abort_dump;
1510  }
1511 
1512  cpu->pc = fip;
1515  return;
1516  }
1517 
1518  /* fatal("RTE: NIP=0x%08" PRIx32", FIP=0x%08" PRIx32"\n",
1519  cpu->cd.m88k.cr[M88K_CR_SNIP], cpu->cd.m88k.cr[M88K_CR_SFIP]); */
1520 
1522  return;
1523 
1524 abort_dump:
1525  fatal("RTE failed. NIP=0x%08" PRIx32", FIP=0x%08" PRIx32"\n",
1527 
1529 }
1530 
1531 
1532 /*
1533  * xmem_slow: Unoptimized xmem (exchange register with memory)
1534  *
1535  * arg[0] = copy of the instruction word
1536  */
1537 X(xmem_slow)
1538 {
1539  uint32_t iword = ic->arg[0], addr;
1540  uint8_t tmp[4];
1541  uint8_t data[4];
1542  int d = (iword >> 21) & 0x1f;
1543  int s1 = (iword >> 16) & 0x1f;
1544  int s2 = iword & 0x1f;
1545  int imm16 = iword & 0xffff;
1546  int scaled = iword & 0x200;
1547  int size = iword & 0x400;
1548  int user = iword & 0x80;
1549 
1550  SYNCH_PC;
1551 
1552  if (user) {
1553  fatal("xmem_slow: user: not yet (TODO)\n");
1554  exit(1);
1555  }
1556 
1557  if ((iword & 0xf0000000) == 0) {
1558  /* immediate offset: */
1559  addr = imm16;
1560  scaled = 0;
1561  size = (iword >> 26) & 1;
1562  user = 0;
1563  } else {
1564  /* register offset: */
1565  addr = cpu->cd.m88k.r[s2];
1566  if (scaled && size)
1567  addr *= sizeof(uint32_t);
1568  }
1569 
1570  addr += cpu->cd.m88k.r[s1];
1571 
1572  if (size) {
1573  uint32_t x = cpu->cd.m88k.r[d];
1575  x = LE32_TO_HOST(x);
1576  else
1577  x = BE32_TO_HOST(x);
1578 
1579  {
1580  uint32_t *p = (uint32_t *) tmp;
1581  *p = x;
1582  }
1583 
1584  if (addr & 3) {
1587  return;
1588  }
1589  } else
1590  tmp[0] = cpu->cd.m88k.r[d];
1591 
1592  if (!cpu->memory_rw(cpu, cpu->mem, addr, (uint8_t *) &data,
1593  size? 4 : 1, MEM_READ, CACHE_DATA)) {
1594  /* Exception. */
1595 
1596  fatal("XMEM exception: TODO: update the transaction"
1597  " registers!\n");
1598  exit(1);
1599  /* return; */
1600  }
1601 
1602  if (!cpu->memory_rw(cpu, cpu->mem, addr, (uint8_t *) &tmp,
1603  size? 4 : 1, MEM_WRITE, CACHE_DATA)) {
1604  /* Exception. */
1605 
1606  fatal("XMEM exception: TODO: update the transaction"
1607  " registers!\n");
1608  exit(1);
1609  /* return; */
1610  }
1611 
1612  if (size) {
1613  uint32_t x;
1614  uint32_t *p = (uint32_t *) data;
1615  x = *p;
1616 
1618  x = LE32_TO_HOST(x);
1619  else
1620  x = BE32_TO_HOST(x);
1621  cpu->cd.m88k.r[d] = x;
1622  } else
1623  cpu->cd.m88k.r[d] = data[0];
1624 }
1625 
1626 
1627 /*
1628  * prom-call:
1629  */
1630 X(prom_call)
1631 {
1632  /* If executed from user mode, then cause an exception: */
1633  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)) {
1634  SYNCH_PC;
1636  return;
1637  }
1638 
1639  switch (cpu->machine->machine_type) {
1640 
1641  case MACHINE_LUNA88K:
1643  break;
1644 
1645  case MACHINE_MVME88K:
1646  mvmeprom_emul(cpu);
1647  break;
1648 
1649  default:fatal("m88k prom_call: unimplemented machine type\n");
1651  }
1652 
1653  if (!cpu->running) {
1655  cpu->cd.m88k.next_ic = &nothing_call;
1656  }
1657 }
1658 
1659 
1660 /*
1661  * tb0, tb1: Trap on bit Clear/Set
1662  *
1663  * arg[0] = bitmask to check (e.g. 0x00020000 for bit 17)
1664  * arg[1] = pointer to register s1
1665  * arg[2] = 9-bit vector number
1666  */
1667 X(tb0)
1668 {
1669  SYNCH_PC;
1670 
1671  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
1672  && ic->arg[2] < M88K_EXCEPTION_USER_TRAPS_START) {
1674  return;
1675  }
1676 
1677  if (!(reg(ic->arg[1]) & ic->arg[0]))
1678  m88k_exception(cpu, ic->arg[2], 1);
1679 }
1680 X(tb1)
1681 {
1682  SYNCH_PC;
1683 
1684  if (!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE)
1685  && ic->arg[2] < M88K_EXCEPTION_USER_TRAPS_START) {
1687  return;
1688  }
1689 
1690  if (reg(ic->arg[1]) & ic->arg[0])
1691  m88k_exception(cpu, ic->arg[2], 1);
1692 }
1693 
1694 
1695 /*
1696  * idle:
1697  *
1698  * s: ld rX,rY,ofs
1699  * bcnd eq0,rX,s
1700  */
1702 {
1703  uint32_t rY = reg(ic[0].arg[1]) + ic[0].arg[2];
1704  uint32_t index = rY >> 12;
1705  unsigned char *p = cpu->cd.m88k.host_load[index];
1706  uint32_t *p32 = (uint32_t *) p;
1707  uint32_t v;
1708 
1709  /* Fallback: */
1710  if (p == NULL || (rY & 3)) {
1711  instr(ld_u_4_be)(cpu, ic);
1712  return;
1713  }
1714 
1715  v = p32[(rY & 0xfff) >> 2];
1717  v = LE32_TO_HOST(v);
1718  else
1719  v = BE32_TO_HOST(v);
1720 
1721  reg(ic[0].arg[0]) = v;
1722 
1723  if (v == 0) {
1724  SYNCH_PC;
1725  usleep(50);
1726  cpu->has_been_idling = 1;
1728  cpu->cd.m88k.next_ic = &nothing_call;
1729  } else {
1731  cpu->cd.m88k.next_ic = &ic[2];
1732  }
1733 }
1734 
1735 
1736 /*
1737  * idle_with_tb1:
1738  *
1739  * s: tb1 bit,r0,vector
1740  * ld rX,rY,ofs
1741  * bcnd eq0,rX,s
1742  */
1743 X(idle_with_tb1)
1744 {
1745  uint32_t rY = reg(ic[1].arg[1]) + ic[1].arg[2];
1746  uint32_t index = rY >> 12;
1747  unsigned char *p = cpu->cd.m88k.host_load[index];
1748  uint32_t *p32 = (uint32_t *) p;
1749  uint32_t v;
1750 
1751  /* Fallback: */
1752  if (p == NULL || (rY & 3)) {
1753  instr(tb1)(cpu, ic);
1754  return;
1755  }
1756 
1757  v = p32[(rY & 0xfff) >> 2];
1759  v = LE32_TO_HOST(v);
1760  else
1761  v = BE32_TO_HOST(v);
1762 
1763  reg(ic[1].arg[0]) = v;
1764 
1765  if (v == 0) {
1766  SYNCH_PC;
1767  usleep(50);
1768  cpu->has_been_idling = 1;
1770  cpu->cd.m88k.next_ic = &nothing_call;
1771  } else {
1772  cpu->n_translated_instrs += 2;
1773  cpu->cd.m88k.next_ic = &ic[3];
1774  }
1775 }
1776 
1777 
1778 /*****************************************************************************/
1779 
1780 
1781 X(end_of_page)
1782 {
1783  /* Update the PC: (offset 0, but on the next page) */
1784  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1) <<
1787 
1788  /* end_of_page doesn't count as an executed instruction: */
1790 
1791  /*
1792  * Find the new physpage and update translation pointers.
1793  *
1794  * Note: This may cause an exception, if e.g. the new page is
1795  * not accessible.
1796  */
1798 
1799  /* Simple jump to the next page (if we are lucky): */
1800  if (cpu->delay_slot == NOT_DELAYED)
1801  return;
1802 
1803  /*
1804  * If we were in a delay slot, and we got an exception while doing
1805  * quick_pc_to_pointers, then return. The function which called
1806  * end_of_page should handle this case.
1807  */
1809  return;
1810 
1811  /*
1812  * Tricky situation; the delay slot is on the next virtual page.
1813  * Calling to_be_translated will translate one instruction manually,
1814  * execute it, and then discard it.
1815  */
1816  /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
1817 
1818  instr(to_be_translated)(cpu, cpu->cd.m88k.next_ic);
1819 
1820  /* The instruction in the delay slot has now executed. */
1821  /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
1822  cpu->delay_slot); */
1823 
1824  /* Find the physpage etc of the instruction in the delay slot
1825  (or, if there was an exception, the exception handler): */
1827 }
1828 
1829 
1830 X(end_of_page2)
1831 {
1832  /* Synchronize PC on the _second_ instruction on the next page: */
1833  int low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page)
1834  / sizeof(struct m88k_instr_call);
1835  cpu->pc &= ~((M88K_IC_ENTRIES_PER_PAGE-1)
1837  cpu->pc += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT);
1838 
1839  if (low_pc < 0 || low_pc > ((M88K_IC_ENTRIES_PER_PAGE+1)
1841  printf("[ end_of_page2: HUH? low_pc=%i, cpu->pc = %08"
1842  PRIx32" ]\n", low_pc, (uint32_t) cpu->pc);
1843  }
1844 
1845  /* This doesn't count as an executed instruction. */
1847 
1849 
1850  if (cpu->delay_slot == NOT_DELAYED)
1851  return;
1852 
1853  fatal("end_of_page2: fatal error, we're in a delay slot\n");
1854  exit(1);
1855 }
1856 
1857 
1858 /*****************************************************************************/
1859 
1860 
1861 /*
1862  * Idle loop detection, e.g.:
1863  *
1864  * s00028d44: 15b7d650 ld r13,r23,0xd650 ; [<_sched_whichqs>]
1865  * s00028d48: e84dffff bcnd eq0,r13,0x00028d44 ; <_sched_idle+0xc4>
1866  *
1867  * or
1868  *
1869  * s00079d78: f020d8ff tb1 1,r0,0xff
1870  * s00079d7c: 15ac7320 ld r13,r12,0x7320 ; [<_sched_whichqs>]
1871  * s00079d80: e84dfffe bcnd eq0,r13,0x00079d78 ; <_sched_idle+0x158>
1872  */
1873 void COMBINE(idle)(struct cpu *cpu, struct m88k_instr_call *ic, int low_addr)
1874 {
1875  int n_back = (low_addr >> M88K_INSTR_ALIGNMENT_SHIFT)
1877  if (n_back < 2)
1878  return;
1879 
1880  if (ic[0].f == instr(bcnd_samepage_eq0) &&
1881  ic[0].arg[2] == (size_t) &ic[-1] &&
1882  ic[-1].f == instr(ld_u_4_be) &&
1883  ic[0].arg[0] == ic[-1].arg[0] &&
1884  ic[0].arg[0] != (size_t) &cpu->cd.m88k.r[M88K_ZERO_REG]) {
1885  ic[-1].f = instr(idle);
1886  return;
1887  }
1888 
1889  if (ic[0].f == instr(bcnd_samepage_eq0) &&
1890  ic[0].arg[2] == (size_t) &ic[-2] &&
1891  ic[-2].f == instr(tb1) &&
1892  ic[-2].arg[1] == (size_t) &cpu->cd.m88k.r[M88K_ZERO_REG] &&
1893  ic[-1].f == instr(ld_u_4_be) &&
1894  ic[0].arg[0] == ic[-1].arg[0] &&
1895  ic[0].arg[0] != (size_t) &cpu->cd.m88k.r[M88K_ZERO_REG]) {
1896  ic[-2].f = instr(idle_with_tb1);
1897  return;
1898  }
1899 }
1900 
1901 
1902 /*****************************************************************************/
1903 
1904 
1905 /*
1906  * m88k_instr_to_be_translated():
1907  *
1908  * Translate an instruction word into a m88k_instr_call. ic is filled in with
1909  * valid data for the translated instruction, or a "nothing" instruction if
1910  * there was a translation failure. The newly translated instruction is then
1911  * executed.
1912  */
1913 X(to_be_translated)
1914 {
1915  uint32_t addr, low_pc, iword;
1916  unsigned char *page;
1917  unsigned char ib[4];
1918  uint32_t op26, op10, op11, d, s1, s2, cr6, imm16;
1919  int32_t d16, d26; //, simm16;
1920  int offset, shift;
1921  int in_crosspage_delayslot = 0;
1922  void (*samepage_function)(struct cpu *, struct m88k_instr_call *)=NULL;
1923 
1924  /* Figure out the (virtual) address of the instruction: */
1925  low_pc = ((size_t)ic - (size_t)cpu->cd.m88k.cur_ic_page)
1926  / sizeof(struct m88k_instr_call);
1927 
1928  /* Special case for branch with delayslot on the next page: */
1929  if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
1930  /* fatal("[ delay-slot translation across page "
1931  "boundary ]\n"); */
1932  in_crosspage_delayslot = 1;
1933  }
1934 
1935  addr = cpu->pc & ~((M88K_IC_ENTRIES_PER_PAGE-1)
1937  addr += (low_pc << M88K_INSTR_ALIGNMENT_SHIFT);
1938  cpu->pc = (MODE_int_t)addr;
1939  addr &= ~((1 << M88K_INSTR_ALIGNMENT_SHIFT) - 1);
1940 
1941  /* Read the instruction word from memory: */
1942  page = cpu->cd.m88k.host_load[(uint32_t)addr >> 12];
1943 
1944  if (page != NULL) {
1945  /* fatal("TRANSLATION HIT!\n"); */
1946  memcpy(ib, page + (addr & 0xffc), sizeof(ib));
1947  } else {
1948  /* fatal("TRANSLATION MISS!\n"); */
1949  if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
1950  sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1951  fatal("to_be_translated(): read failed: TODO\n");
1952  goto bad;
1953  }
1954  }
1955 
1956  {
1957  uint32_t *p = (uint32_t *) ib;
1958  iword = *p;
1959  }
1960 
1962  iword = LE32_TO_HOST(iword);
1963  else
1964  iword = BE32_TO_HOST(iword);
1965 
1966 
1967 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1968 #include "cpu_dyntrans.cc"
1969 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1970 
1971 
1972  /*
1973  * Translate the instruction:
1974  *
1975  * NOTE: _NEVER_ allow writes to the zero register; all instructions
1976  * that use the zero register as their destination should be treated
1977  * as NOPs, except those that access memory (they should use the
1978  * scratch register instead).
1979  */
1980  if (cpu->cd.m88k.r[M88K_ZERO_REG] != 0) {
1981  fatal("INTERNAL ERROR! M88K_ZERO_REG != 0?\n");
1982  exit(1);
1983  }
1984 
1985  op26 = (iword >> 26) & 0x3f;
1986  op11 = (iword >> 11) & 0x1f;
1987  op10 = (iword >> 10) & 0x3f;
1988  d = (iword >> 21) & 0x1f;
1989  s1 = (iword >> 16) & 0x1f;
1990  s2 = iword & 0x1f;
1991  imm16 = iword & 0xffff;
1992  // simm16 = (int16_t) (iword & 0xffff);
1993  cr6 = (iword >> 5) & 0x3f;
1994  d16 = ((int16_t) (iword & 0xffff)) * 4;
1995  d26 = ((int32_t)((iword & 0x03ffffff) << 6)) >> 4;
1996 
1997  switch (op26) {
1998 
1999  case 0x00:
2000  case 0x01:
2001  ic->f = instr(xmem_slow);
2002  ic->arg[0] = iword;
2003  if (d == M88K_ZERO_REG)
2004  ic->f = instr(nop);
2005  if (iword == 0)
2006  goto bad;
2007  break;
2008 
2009  case 0x02: /* ld.hu */
2010  case 0x03: /* ld.bu */
2011  case 0x04: /* ld.d */
2012  case 0x05: /* ld */
2013  case 0x06: /* ld.h */
2014  case 0x07: /* ld.b */
2015  case 0x08: /* st.d */
2016  case 0x09: /* st */
2017  case 0x0a: /* st.h */
2018  case 0x0b: /* st.b */
2019  {
2020  int store = 0, signedness = 0, opsize = 0;
2021 
2022  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2023  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2024  ic->arg[2] = imm16;
2025 
2026  switch (op26) {
2027  case 0x02: opsize = 1; break;
2028  case 0x03: opsize = 0; break;
2029  case 0x04: opsize = 3; break;
2030  case 0x05: opsize = 2; break;
2031  case 0x06: opsize = 1; signedness = 1; break;
2032  case 0x07: opsize = 0; signedness = 1; break;
2033  case 0x08: store = 1; opsize = 3; break;
2034  case 0x09: store = 1; opsize = 2; break;
2035  case 0x0a: store = 1; opsize = 1; break;
2036  case 0x0b: store = 1; opsize = 0; break;
2037  }
2038 
2039  if (opsize == 3 && d == 31) {
2040  fatal("m88k load/store of register pair r31/r0"
2041  " is not yet implemented\n");
2042  goto bad;
2043  }
2044 
2045  ic->f = m88k_loadstore[ opsize
2046  + (store? M88K_LOADSTORE_STORE : 0)
2047  + (signedness? M88K_LOADSTORE_SIGNEDNESS:0)
2050 
2051  if (!store && d == 0)
2052  ic->arg[0] = (size_t) &cpu->cd.m88k.zero_scratch;
2053  }
2054  break;
2055 
2056  case 0x10: /* and imm */
2057  case 0x11: /* and.u imm */
2058  case 0x12: /* mask imm */
2059  case 0x13: /* mask.u imm */
2060  case 0x14: /* xor imm */
2061  case 0x15: /* xor.u imm */
2062  case 0x16: /* or imm */
2063  case 0x17: /* or.u imm */
2064  case 0x18: /* addu imm */
2065  case 0x19: /* subu imm */
2066  case 0x1a: /* divu imm */
2067  case 0x1b: /* mulu imm */
2068  case 0x1c: /* add imm */
2069  case 0x1d: /* sub imm */
2070  case 0x1e: /* div imm */
2071  case 0x1f: /* cmp imm */
2072  shift = 0;
2073  switch (op26) {
2074  case 0x10: ic->f = instr(and_imm); break;
2075  case 0x11: ic->f = instr(and_u_imm); shift = 16; break;
2076  case 0x12: ic->f = instr(mask_imm); break;
2077  case 0x13: ic->f = instr(mask_imm); shift = 16; break;
2078  case 0x14: ic->f = instr(xor_imm); break;
2079  case 0x15: ic->f = instr(xor_imm); shift = 16; break;
2080  case 0x16: ic->f = instr(or_imm); break;
2081  case 0x17: ic->f = instr(or_imm); shift = 16; break;
2082  case 0x18: ic->f = instr(addu_imm); break;
2083  case 0x19: ic->f = instr(subu_imm); break;
2084  case 0x1a: ic->f = instr(divu_imm); break;
2085  case 0x1b: ic->f = instr(mulu_imm); break;
2086  case 0x1c: ic->f = instr(add_imm); break;
2087  case 0x1d: ic->f = instr(sub_imm); break;
2088  case 0x1e: ic->f = instr(div_imm); break;
2089  case 0x1f: ic->f = instr(cmp_imm); break;
2090  }
2091 
2092  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2093  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2094  ic->arg[2] = imm16 << shift;
2095 
2096  /* Optimization for or d,r0,imm and similar */
2097  if (s1 == M88K_ZERO_REG && ic->f == instr(or_imm)) {
2098  if (ic->arg[2] == 0)
2099  ic->f = instr(or_r0_imm0);
2100  else
2101  ic->f = instr(or_r0_imm);
2102  }
2103  if (ic->arg[2] == 0 && ic->f == instr(addu_imm))
2104  ic->f = instr(addu_s2r0);
2105 
2106  if (d == s1 && ic->arg[2] == 1) {
2107  if (ic->f == instr(addu_imm))
2108  ic->f = instr(inc_reg);
2109  if (ic->f == instr(subu_imm))
2110  ic->f = instr(dec_reg);
2111  }
2112 
2113  if (d == M88K_ZERO_REG)
2114  ic->f = instr(nop);
2115  break;
2116 
2117  case 0x20:
2118  if ((iword & 0x001ff81f) == 0x00004000) {
2119  ic->f = instr(ldcr);
2120  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2121  ic->arg[1] = cr6;
2122  if (d == M88K_ZERO_REG)
2123  ic->arg[0] = (size_t)
2124  &cpu->cd.m88k.zero_scratch;
2125  } else if ((iword & 0x001ff81f) == 0x00004800) {
2126  ic->f = instr(fldcr);
2127  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2128  ic->arg[1] = cr6;
2129  if (d == M88K_ZERO_REG)
2130  ic->arg[0] = (size_t)
2131  &cpu->cd.m88k.zero_scratch;
2132  } else if ((iword & 0x03e0f800) == 0x00008000) {
2133  ic->f = instr(stcr);
2134  ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
2135  ic->arg[1] = cr6;
2136  if (s1 != s2)
2137  goto bad;
2138  } else if ((iword & 0x03e0f800) == 0x00008800) {
2139  ic->f = instr(fstcr);
2140  ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
2141  ic->arg[1] = cr6;
2142  if (s1 != s2)
2143  goto bad;
2144  } else if ((iword & 0x0000f800) == 0x0000c000) {
2145  ic->f = instr(xcr);
2146  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2147  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2148  ic->arg[2] = cr6;
2149  if (s1 != s2)
2150  goto bad;
2151  } else
2152  goto bad;
2153  break;
2154 
2155  case 0x21:
2156  switch (op11) {
2157 
2158  case 0x00: /* fmul */
2159  if (d == 0) {
2160  /* d = 0 isn't allowed. for now, let's abort execution. */
2161  fatal("TODO: exception for d = 0 in fmul.xxx instruction\n");
2162  goto bad;
2163  }
2164  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2165  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2166  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2167  switch ((iword >> 5) & 0x3f) {
2168  case 0x00: ic->f = instr(fmul_sss); break;
2169  case 0x01: ic->f = instr(fmul_dss); break;
2170  case 0x05: ic->f = instr(fmul_dsd); break;
2171  case 0x11: ic->f = instr(fmul_dds); break;
2172  case 0x15: ic->f = instr(fmul_ddd); break;
2173  default:if (!cpu->translation_readahead)
2174  fatal("Unimplemented fmul combination 0x%x.\n",
2175  (iword >> 5) & 0x3f);
2176  goto bad;
2177  }
2178  break;
2179 
2180  case 0x04: /* flt */
2181  if (d == 0) {
2182  /* d = 0 isn't allowed. for now, let's abort execution. */
2183  fatal("TODO: exception for d = 0 in flt.xx instruction\n");
2184  goto bad;
2185  }
2186  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2187  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s2];
2188  if ((iword >> 5) & 1) {
2189  ic->f = instr(flt_ds);
2190  if (d & 1) {
2191  fatal("TODO: double precision load into uneven register r%i?\n", d);
2192  goto bad;
2193  }
2194  } else {
2195  ic->f = instr(flt_ss);
2196  }
2197  break;
2198 
2199  case 0x05: /* fadd */
2200  if (d == 0) {
2201  /* d = 0 isn't allowed. for now, let's abort execution. */
2202  fatal("TODO: exception for d = 0 in fadd.xxx instruction\n");
2203  goto bad;
2204  }
2205  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2206  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2207  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2208  switch ((iword >> 5) & 0x3f) {
2209  case 0x00: ic->f = instr(fadd_sss); break;
2210  case 0x05: ic->f = instr(fadd_dsd); break;
2211  case 0x11: ic->f = instr(fadd_dds); break;
2212  case 0x15: ic->f = instr(fadd_ddd); break;
2213  default:if (!cpu->translation_readahead)
2214  fatal("Unimplemented fadd combination 0x%x.\n",
2215  (iword >> 5) & 0x3f);
2216  goto bad;
2217  }
2218  break;
2219 
2220  case 0x06: /* fsub */
2221  if (d == 0) {
2222  /* d = 0 isn't allowed. for now, let's abort execution. */
2223  fatal("TODO: exception for d = 0 in fsub.xxx instruction\n");
2224  goto bad;
2225  }
2226  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2227  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2228  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2229  switch ((iword >> 5) & 0x3f) {
2230  case 0x01: ic->f = instr(fsub_dss); break;
2231  case 0x05: ic->f = instr(fsub_dsd); break;
2232  case 0x10: ic->f = instr(fsub_sds); break;
2233  case 0x11: ic->f = instr(fsub_dds); break;
2234  case 0x15: ic->f = instr(fsub_ddd); break;
2235  default:if (!cpu->translation_readahead)
2236  fatal("Unimplemented fsub combination 0x%x.\n",
2237  (iword >> 5) & 0x3f);
2238  goto bad;
2239  }
2240  break;
2241 
2242  case 0x07: /* fcmp */
2243  if (d == 0) {
2244  /* d = 0 isn't allowed. for now, let's abort execution. */
2245  fatal("TODO: exception for d = 0 in fcmp.xxx instruction\n");
2246  goto bad;
2247  }
2248  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2249  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2250  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2251  switch ((iword >> 5) & 0x3f) {
2252  case 0x10: ic->f = instr(fcmp_sds); break;
2253  case 0x14: ic->f = instr(fcmp_sdd); break;
2254  default:if (!cpu->translation_readahead)
2255  fatal("Unimplemented fcmp combination 0x%x.\n",
2256  (iword >> 5) & 0x3f);
2257  goto bad;
2258  }
2259  break;
2260 
2261  case 0x0b: /* trnc */
2262  if (d == 0) {
2263  /* d = 0 isn't allowed. for now, let's abort execution. */
2264  fatal("TODO: exception for d = 0 in trnc.xx instruction\n");
2265  goto bad;
2266  }
2267  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2268  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s2];
2269  if ((iword >> 7) & 1) {
2270  ic->f = instr(trnc_sd);
2271  if (s2 & 1) {
2272  fatal("TODO: double precision truncation into uneven register r%i?\n", d);
2273  goto bad;
2274  }
2275  } else {
2276  ic->f = instr(trnc_ss);
2277  }
2278  break;
2279 
2280  case 0x0e: /* fdiv */
2281  if (d == 0) {
2282  /* d = 0 isn't allowed. for now, let's abort execution. */
2283  fatal("TODO: exception for d = 0 in fdiv.xxx instruction\n");
2284  goto bad;
2285  }
2286  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2287  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2288  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2289  switch ((iword >> 5) & 0x3f) {
2290  case 0x00: ic->f = instr(fdiv_sss); break;
2291  case 0x05: ic->f = instr(fdiv_dsd); break;
2292  case 0x15: ic->f = instr(fdiv_ddd); break;
2293  default:if (!cpu->translation_readahead)
2294  fatal("Unimplemented fdiv combination 0x%x.\n",
2295  (iword >> 5) & 0x3f);
2296  goto bad;
2297  }
2298  break;
2299 
2300  default:goto bad;
2301  }
2302  break;
2303 
2304  case 0x30: /* br */
2305  case 0x31: /* br.n */
2306  case 0x32: /* bsr */
2307  case 0x33: /* bsr.n */
2308  switch (op26) {
2309  case 0x30:
2310  ic->f = instr(br);
2311  samepage_function = instr(br_samepage);
2312  if (cpu->translation_readahead > 1)
2314  break;
2315  case 0x31:
2316  ic->f = instr(br_n);
2317  if (cpu->translation_readahead > 2)
2319  break;
2320  case 0x32:
2321  ic->f = instr(bsr);
2322  samepage_function = instr(bsr_samepage);
2323  break;
2324  case 0x33:
2325  ic->f = instr(bsr_n);
2326  break;
2327  }
2328 
2329  offset = (addr & 0xffc) + d26;
2330 
2331  /* Prepare both samepage and offset style args.
2332  (Only one will be used in the actual instruction.) */
2333  ic->arg[0] = (size_t) ( cpu->cd.m88k.cur_ic_page +
2334  (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
2335  ic->arg[1] = offset;
2336  ic->arg[2] = (addr & 0xffc) + 4; /* Return offset
2337  for bsr_samepage */
2338 
2339  if (offset >= 0 && offset <= 0xffc &&
2340  samepage_function != NULL)
2341  ic->f = samepage_function;
2342 
2343  if (cpu->machine->show_trace_tree) {
2344  if (op26 == 0x32)
2345  ic->f = instr(bsr_trace);
2346  if (op26 == 0x33)
2347  ic->f = instr(bsr_n_trace);
2348  }
2349 
2350  break;
2351 
2352  case 0x34: /* bb0 */
2353  case 0x35: /* bb0.n */
2354  case 0x36: /* bb1 */
2355  case 0x37: /* bb1.n */
2356  switch (op26) {
2357  case 0x34:
2358  ic->f = instr(bb0);
2359  samepage_function = instr(bb0_samepage);
2360  break;
2361  case 0x35:
2362  ic->f = instr(bb0_n);
2363  break;
2364  case 0x36:
2365  ic->f = instr(bb1);
2366  samepage_function = instr(bb1_samepage);
2367  break;
2368  case 0x37:
2369  ic->f = instr(bb1_n);
2370  break;
2371  }
2372 
2373  ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
2374  ic->arg[1] = (uint32_t) (1 << d);
2375 
2376  offset = (addr & 0xffc) + d16;
2377  ic->arg[2] = offset;
2378 
2379  if (offset >= 0 && offset <= 0xffc &&
2380  samepage_function != NULL) {
2381  ic->f = samepage_function;
2382  ic->arg[2] = (size_t) ( cpu->cd.m88k.cur_ic_page +
2383  (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
2384  }
2385  break;
2386 
2387  case 0x3a: /* bcnd */
2388  case 0x3b: /* bcnd.n */
2389  ic->f = m88k_bcnd[d + 32 * (op26 & 1)];
2390  samepage_function = m88k_bcnd[64 + d + 32 * (op26 & 1)];
2391 
2392  if (ic->f == NULL)
2393  goto bad;
2394 
2395  ic->arg[0] = (size_t) &cpu->cd.m88k.r[s1];
2396 
2397  offset = (addr & 0xffc) + d16;
2398  ic->arg[2] = offset;
2399 
2400  if (offset >= 0 && offset <= 0xffc &&
2401  samepage_function != NULL) {
2402  ic->f = samepage_function;
2403  ic->arg[2] = (size_t) ( cpu->cd.m88k.cur_ic_page +
2404  (offset >> M88K_INSTR_ALIGNMENT_SHIFT) );
2405  }
2406 
2407  if ((iword & 0xffe0ffff) == 0xe840ffff ||
2408  (iword & 0xffe0ffff) == 0xe840fffe)
2409  cpu->cd.m88k.combination_check = COMBINE(idle);
2410 
2411  break;
2412 
2413  case 0x3c:
2414  switch (op10) {
2415 
2416  case 0x20: /* clr */
2417  case 0x22: /* set */
2418  case 0x24: /* ext */
2419  case 0x26: /* extu */
2420  case 0x28: /* mak */
2421  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2422  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2423  ic->arg[2] = iword & 0x3ff;
2424 
2425  switch (op10) {
2426  case 0x20: ic->f = instr(mask_imm);
2427  {
2428  int w = ic->arg[2] >> 5;
2429  int o = ic->arg[2] & 0x1f;
2430  uint32_t x = w == 0? 0xffffffff
2431  : ((uint32_t)1 << w) - 1;
2432  x <<= o;
2433  ic->arg[2] = ~x;
2434  }
2435  break;
2436  case 0x22: ic->f = instr(or_imm);
2437  {
2438  int w = ic->arg[2] >> 5;
2439  int o = ic->arg[2] & 0x1f;
2440  uint32_t x = w == 0? 0xffffffff
2441  : ((uint32_t)1 << w) - 1;
2442  x <<= o;
2443  ic->arg[2] = x;
2444  }
2445  break;
2446  case 0x24: ic->f = instr(ext_imm); break;
2447  case 0x26: ic->f = instr(extu_imm); break;
2448  case 0x28: ic->f = instr(mak_imm); break;
2449  }
2450 
2451  if (d == M88K_ZERO_REG)
2452  ic->f = instr(nop);
2453  break;
2454 
2455  case 0x34: /* tb0 */
2456  case 0x36: /* tb1 */
2457  ic->arg[0] = 1 << d;
2458  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2459  ic->arg[2] = iword & 0x1ff;
2460  switch (op10) {
2461  case 0x34: ic->f = instr(tb0); break;
2462  case 0x36: ic->f = instr(tb1); break;
2463  }
2464  break;
2465 
2466  default:goto bad;
2467  }
2468  break;
2469 
2470  case 0x3d:
2471  if ((iword & 0xf000) <= 0x3fff ) {
2472  /* Load, Store, xmem, and lda: */
2473  int op = 0, opsize, user = 0, wt = 0;
2474  int signedness = 1, scaled = 0;
2475 
2476  switch (iword & 0xf000) {
2477  case 0x2000: op = 1; /* st */ break;
2478  case 0x3000: op = 2; /* lda */ break;
2479  default: if ((iword & 0xf800) >= 0x0800)
2480  op = 0; /* ld */
2481  else
2482  op = 3; /* xmem */
2483  }
2484 
2485  /* for (most) ld, st, lda: */
2486  opsize = (iword >> 10) & 3;
2487 
2488  /* Turn opsize into x, where size = 1 << x: */
2489  opsize = 3 - opsize;
2490 
2491  if (op == 3) {
2492  /* xmem: */
2493  switch ((iword >> 10) & 3) {
2494  case 0: opsize = 0; break;
2495  case 1: opsize = 2; break;
2496  default:fatal("Weird xmem opsize/type?\n");
2497  goto bad;
2498  }
2499  } else {
2500  if ((iword & 0xf800) == 0x800) {
2501  signedness = 0;
2502  if ((iword & 0xf00) < 0xc00)
2503  opsize = 1;
2504  else
2505  opsize = 0;
2506  } else {
2507  if (opsize >= 2 || op == 1)
2508  signedness = 0;
2509  }
2510  }
2511 
2512  if (iword & 0x100)
2513  user = 1;
2514  if (iword & 0x80)
2515  wt = 1;
2516  if (iword & 0x200)
2517  scaled = 1;
2518 
2519  if (wt) {
2520  fatal("wt bit not yet implemented! TODO\n");
2521  goto bad;
2522  }
2523 
2524  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2525  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2526  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2527 
2528  if (op == 0 || op == 1) {
2529  /* ld or st: */
2530  ic->f = m88k_loadstore[ opsize
2531  + (op==1? M88K_LOADSTORE_STORE : 0)
2532  + (signedness? M88K_LOADSTORE_SIGNEDNESS:0)
2535  + (scaled? M88K_LOADSTORE_SCALEDNESS : 0)
2536  + (user? M88K_LOADSTORE_USR : 0)
2538 
2539  if (d == M88K_ZERO_REG && op == 0)
2540  ic->arg[0] = (size_t)&cpu->cd.m88k.zero_scratch;
2541 
2542  if (opsize == 3 && d == 31) {
2543  fatal("m88k load/store of register "
2544  "pair r31/r0: TODO\n");
2545  goto bad;
2546  }
2547  } else if (op == 2) {
2548  /* lda: */
2549  if (scaled) {
2550  switch (opsize) {
2551  case 0: ic->f = instr(addu); break;
2552  case 1: ic->f = instr(lda_reg_2); break;
2553  case 2: ic->f = instr(lda_reg_4); break;
2554  case 3: ic->f = instr(lda_reg_8); break;
2555  }
2556  } else {
2557  ic->f = instr(addu);
2558  }
2559  if (d == M88K_ZERO_REG)
2560  ic->f = instr(nop);
2561  } else {
2562  /* xmem: */
2563  ic->f = instr(xmem_slow);
2564  ic->arg[0] = iword;
2565  if (d == M88K_ZERO_REG)
2566  ic->f = instr(nop);
2567  }
2568  } else switch ((iword >> 8) & 0xff) {
2569  case 0x40: /* and */
2570  case 0x44: /* and.c */
2571  case 0x50: /* xor */
2572  case 0x54: /* xor.c */
2573  case 0x58: /* or */
2574  case 0x5c: /* or.c */
2575  case 0x60: /* addu */
2576  case 0x61: /* addu.co */
2577  case 0x62: /* addu.ci */
2578  case 0x64: /* subu */
2579  case 0x65: /* subu.co */
2580  case 0x66: /* subu.ci */
2581  case 0x68: /* divu */
2582  case 0x6c: /* mul */
2583  case 0x70: /* add */
2584  case 0x78: /* div */
2585  case 0x7c: /* cmp */
2586  case 0x80: /* clr */
2587  case 0x88: /* set */
2588  case 0x90: /* ext */
2589  case 0x98: /* extu */
2590  case 0xa0: /* mak */
2591  case 0xa8: /* rot */
2592  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2593  ic->arg[1] = (size_t) &cpu->cd.m88k.r[s1];
2594  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2595 
2596  switch ((iword >> 8) & 0xff) {
2597  case 0x40: ic->f = instr(and); break;
2598  case 0x44: ic->f = instr(and_c); break;
2599  case 0x50: ic->f = instr(xor); break;
2600  case 0x54: ic->f = instr(xor_c); break;
2601  case 0x58: ic->f = instr(or); break;
2602  case 0x5c: ic->f = instr(or_c); break;
2603  case 0x60: ic->f = instr(addu); break;
2604  case 0x61: ic->f = instr(addu_co); break;
2605  case 0x62: ic->f = instr(addu_ci); break;
2606  case 0x64: ic->f = instr(subu); break;
2607  case 0x65: ic->f = instr(subu_co); break;
2608  case 0x66: ic->f = instr(subu_ci); break;
2609  case 0x68: ic->f = instr(divu); break;
2610  case 0x6c: ic->f = instr(mul); break;
2611  case 0x70: ic->f = instr(add); break;
2612  case 0x78: ic->f = instr(div); break;
2613  case 0x7c: ic->f = instr(cmp); break;
2614  case 0x80: ic->f = instr(clr); break;
2615  case 0x88: ic->f = instr(set); break;
2616  case 0x90: ic->f = instr(ext); break;
2617  case 0x98: ic->f = instr(extu); break;
2618  case 0xa0: ic->f = instr(mak); break;
2619  case 0xa8: ic->f = instr(rot); break;
2620  }
2621 
2622  /* Optimization for or rX,r0,rY etc: */
2623  if (s1 == M88K_ZERO_REG && ic->f == instr(or))
2624  ic->f = instr(or_r0);
2625  if (s2 == M88K_ZERO_REG && ic->f == instr(addu))
2626  ic->f = instr(addu_s2r0);
2627 
2628  /*
2629  * Handle the case when the destination register is r0:
2630  *
2631  * If there is NO SIDE-EFFECT! (i.e. no carry out),
2632  * then replace the instruction with a nop. If there is
2633  * a side-effect, we still have to run the instruction,
2634  * so replace the destination register with a scratch
2635  * register.
2636  */
2637  if (d == M88K_ZERO_REG) {
2638  int opc = (iword >> 8) & 0xff;
2639  if (opc != 0x61 /* addu.co */ && opc != 0x63 /* addu.cio */ &&
2640  opc != 0x65 /* subu.co */ && opc != 0x67 /* subu.cio */ &&
2641  opc != 0x71 /* add.co */ && opc != 0x73 /* add.cio */ &&
2642  opc != 0x75 /* sub.co */ && opc != 0x77 /* sub.cio */ &&
2643  opc != 0x68 /* divu */ && opc != 0x69 /* divu.d */ &&
2644  opc != 0x6c /* mul */ && opc != 0x6d /* mulu.d */ &&
2645  opc != 0x6e /* muls */ && opc != 0x78 /* div */)
2646  ic->f = instr(nop);
2647  else
2648  ic->arg[0] = (size_t)
2649  &cpu->cd.m88k.zero_scratch;
2650  }
2651  break;
2652  case 0xc0: /* jmp */
2653  case 0xc4: /* jmp.n */
2654  case 0xc8: /* jsr */
2655  case 0xcc: /* jsr.n */
2656  switch ((iword >> 8) & 0xff) {
2657  case 0xc0: ic->f = instr(jmp);
2658  if (cpu->translation_readahead > 1)
2660  break;
2661  case 0xc4: ic->f = instr(jmp_n);
2662  if (cpu->translation_readahead > 2)
2664  break;
2665  case 0xc8: ic->f = instr(jsr); break;
2666  case 0xcc: ic->f = instr(jsr_n); break;
2667  }
2668 
2669  ic->arg[1] = (addr & 0xffc) + 4;
2670  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2671 
2672  if (((iword >> 8) & 0x04) == 0x04)
2673  ic->arg[1] = (addr & 0xffc) + 8;
2674 
2675  if (cpu->machine->show_trace_tree &&
2676  s2 == M88K_RETURN_REG) {
2677  if (ic->f == instr(jmp))
2678  ic->f = instr(jmp_trace);
2679  if (ic->f == instr(jmp_n))
2680  ic->f = instr(jmp_n_trace);
2681  }
2682  if (cpu->machine->show_trace_tree) {
2683  if (ic->f == instr(jsr))
2684  ic->f = instr(jsr_trace);
2685  if (ic->f == instr(jsr_n))
2686  ic->f = instr(jsr_n_trace);
2687  }
2688  break;
2689  case 0xe8: /* ff1 */
2690  case 0xec: /* ff0 */
2691  switch ((iword >> 8) & 0xff) {
2692  case 0xe8: ic->f = instr(ff1); break;
2693  case 0xec: ic->f = instr(ff0); break;
2694  }
2695 
2696  ic->arg[0] = (size_t) &cpu->cd.m88k.r[d];
2697  ic->arg[2] = (size_t) &cpu->cd.m88k.r[s2];
2698 
2699  if (d == M88K_ZERO_REG)
2700  ic->f = instr(nop);
2701  break;
2702  case 0xfc:
2703  switch (iword & 0xff) {
2704  case 0x00:
2705  if (iword == 0xf400fc00)
2706  ic->f = instr(rte);
2707  else {
2708  fatal("unimplemented rte variant: 0x%08" PRIx32"\n", iword);
2709  goto bad;
2710  }
2711  break;
2712  case (M88K_PROM_INSTR & 0xff):
2713  ic->f = instr(prom_call);
2714  break;
2715  default:fatal("Unimplemented 3d/fc instruction\n");
2716  goto bad;
2717  }
2718  break;
2719  default:goto bad;
2720  }
2721  break;
2722 
2723  default:goto bad;
2724  }
2725 
2726 
2727 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
2728 #include "cpu_dyntrans.cc"
2729 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
2730 }
2731 
MACHINE_MVME88K
#define MACHINE_MVME88K
Definition: machine.h:257
data
u_short data
Definition: siireg.h:79
instr
#define instr(n)
Definition: tmp_alpha_head.cc:43
ABORT_EXECUTION
#define ABORT_EXECUTION
Definition: cpu_m88k_instr.cc:45
cpu::has_been_idling
char has_been_idling
Definition: cpu.h:401
M88K_PSR_SFD1
#define M88K_PSR_SFD1
Definition: m88k_psl.h:79
M88K_EXCEPTION_INTEGER_OVERFLOW
#define M88K_EXCEPTION_INTEGER_OVERFLOW
Definition: M88K_CPUComponent.h:292
f
void f(int s, int func, int only_name)
Definition: generate_arm_r.c:45
M88K_EXCEPTION_PRIVILEGE_VIOLATION
#define M88K_EXCEPTION_PRIVILEGE_VIOLATION
Definition: M88K_CPUComponent.h:289
cpu_dyntrans.cc
M88K_CMP_NE
#define M88K_CMP_NE
Definition: M88K_CPUComponent.h:279
tmp_m88k_bcnd.cc
M88K_FPECR_FDVZ
#define M88K_FPECR_FDVZ
Definition: M88K_CPUComponent.h:255
X
X(nop)
Definition: cpu_m88k_instr.cc:55
cpu::running
uint8_t running
Definition: cpu.h:353
luna88kprom_emul
int luna88kprom_emul(struct cpu *cpu)
Definition: luna88kprom.cc:90
M88K_LOADSTORE_SIGNEDNESS
#define M88K_LOADSTORE_SIGNEDNESS
Definition: cpu_m88k_instr.cc:301
addu
void COMBINE() addu(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
Definition: cpu_mips_instr.cc:3480
M88K_LOADSTORE_STORE
#define M88K_LOADSTORE_STORE
Definition: cpu_m88k_instr.cc:300
NOT_DELAYED
#define NOT_DELAYED
Definition: cpu.h:305
cpu_functioncall_trace_return
void cpu_functioncall_trace_return(struct cpu *cpu)
Definition: cpu.cc:284
cpu::n_translated_instrs
int n_translated_instrs
Definition: cpu.h:430
machine::show_trace_tree
int show_trace_tree
Definition: machine.h:164
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
ieee_interpret_float_value
void ieee_interpret_float_value(uint64_t x, struct ieee_float_value *fvp, int fmt)
Definition: float_emul.cc:49
M88K_CR_SFIP
#define M88K_CR_SFIP
Definition: M88K_CPUComponent.h:188
N_SAFE_DYNTRANS_LIMIT
#define N_SAFE_DYNTRANS_LIMIT
Definition: cpu.h:311
m88k_bcnd
void(* m88k_bcnd[32 *2 *2])(struct cpu *, struct m88k_instr_call *)
Definition: tmp_m88k_bcnd.cc:342
MEM_READ
#define MEM_READ
Definition: memory.h:116
M88K_FIP_V
#define M88K_FIP_V
Definition: m88k_psl.h:84
cpu::byte_order
uint8_t byte_order
Definition: cpu.h:347
EMUL_BIG_ENDIAN
#define EMUL_BIG_ENDIAN
Definition: misc.h:165
cpu_functioncall_trace
void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
Definition: cpu.cc:228
LE32_TO_HOST
#define LE32_TO_HOST(x)
Definition: misc.h:180
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
IEEE_FMT_D
#define IEEE_FMT_D
Definition: float_emul.h:44
M88K_FIP_E
#define M88K_FIP_E
Definition: m88k_psl.h:85
BE32_TO_HOST
#define BE32_TO_HOST(x)
Definition: misc.h:181
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
cpu::m88k
struct m88k_cpu m88k
Definition: cpu.h:445
M88K_RETURN_REG
#define M88K_RETURN_REG
Definition: M88K_CPUComponent.h:266
M88K_ZERO_REG
#define M88K_ZERO_REG
Definition: M88K_CPUComponent.h:265
ieee_store_float_value
uint64_t ieee_store_float_value(double nf, int fmt)
Definition: float_emul.cc:238
op
char * op[16]
Definition: generate_arm_dpi.c:34
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
M88K_CMP_EQ
#define M88K_CMP_EQ
Definition: M88K_CPUComponent.h:280
cpu::cd
union cpu::@1 cd
page
page
Definition: tmp_arm_multi.cc:54
M88K_NIP_V
#define M88K_NIP_V
Definition: m88k_psl.h:87
ic
struct arm_instr_call * ic
Definition: tmp_arm_multi.cc:50
CACHE_INSTRUCTION
#define CACHE_INSTRUCTION
Definition: memory.h:122
m88k_stcr
void m88k_stcr(struct cpu *cpu, uint32_t value, int cr, int rte)
Definition: cpu_m88k.cc:503
M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE
#define M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE
Definition: M88K_CPUComponent.h:291
M88K_CMP_HS
#define M88K_CMP_HS
Definition: M88K_CPUComponent.h:271
M88K_EXCEPTION_USER_TRAPS_START
#define M88K_EXCEPTION_USER_TRAPS_START
Definition: M88K_CPUComponent.h:296
M88K_FPCR_FPECR
#define M88K_FPCR_FPECR
Definition: M88K_CPUComponent.h:254
M88K_IC_ENTRIES_PER_PAGE
#define M88K_IC_ENTRIES_PER_PAGE
Definition: M88K_CPUComponent.h:261
ieee_float_value
Definition: float_emul.h:38
tmp_m88k_loadstore.cc
M88K_FIP_ADDR
#define M88K_FIP_ADDR
Definition: m88k_psl.h:86
M88K_LOADSTORE_ENDIANNESS
#define M88K_LOADSTORE_ENDIANNESS
Definition: cpu_m88k_instr.cc:302
CACHE_DATA
#define CACHE_DATA
Definition: memory.h:121
m88k_exception
void m88k_exception(struct cpu *cpu, int vector, int is_trap)
Definition: cpu_m88k.cc:648
SYNCH_PC
#define SYNCH_PC
Definition: cpu_m88k_instr.cc:37
M88K_CMP_LS
#define M88K_CMP_LS
Definition: M88K_CPUComponent.h:273
M88K_PSR_MODE
#define M88K_PSR_MODE
Definition: m88k_psl.h:70
idle
void COMBINE() idle(struct cpu *cpu, struct m88k_instr_call *ic, int low_addr)
Definition: cpu_m88k_instr.cc:1873
M88K_NIP_ADDR
#define M88K_NIP_ADDR
Definition: m88k_psl.h:89
M88K_INSTR_ALIGNMENT_SHIFT
#define M88K_INSTR_ALIGNMENT_SHIFT
Definition: M88K_CPUComponent.h:260
M88K_NIP_E
#define M88K_NIP_E
Definition: m88k_psl.h:88
m88k_cpu::cr
uint32_t cr[N_M88K_CONTROL_REGS]
Definition: cpu_m88k.h:241
TO_BE_DELAYED
#define TO_BE_DELAYED
Definition: cpu.h:307
M88K_CR_SNIP
#define M88K_CR_SNIP
Definition: M88K_CPUComponent.h:187
M88K_LOADSTORE_SCALEDNESS
#define M88K_LOADSTORE_SCALEDNESS
Definition: cpu_m88k_instr.cc:303
cond
char * cond[16]
Definition: generate_arm_dpi.c:30
cpu::mem
struct memory * mem
Definition: cpu.h:362
MODE_int_t
#define MODE_int_t
Definition: tmp_alpha_tail.cc:55
EMUL_LITTLE_ENDIAN
#define EMUL_LITTLE_ENDIAN
Definition: misc.h:164
ieee_float_value::f
double f
Definition: float_emul.h:39
cpu::machine
struct machine * machine
Definition: cpu.h:328
M88K_LOADSTORE_USR
#define M88K_LOADSTORE_USR
Definition: cpu_m88k_instr.cc:304
cpu::delay_slot
uint8_t delay_slot
Definition: cpu.h:356
IEEE_FMT_S
#define IEEE_FMT_S
Definition: float_emul.h:43
reg
#define reg(x)
Definition: tmp_alpha_tail.cc:53
M88K_FPECR_FUNIMP
#define M88K_FPECR_FUNIMP
Definition: M88K_CPUComponent.h:256
m88k_loadstore
void(* m88k_loadstore[256])(struct cpu *, struct m88k_instr_call *)
Definition: tmp_m88k_loadstore.cc:1773
m88k_ldcr
void m88k_ldcr(struct cpu *cpu, uint32_t *r32ptr, int cr)
Definition: cpu_m88k.cc:425
M88K_PSR_C
#define M88K_PSR_C
Definition: m88k_psl.h:73
nop
void COMBINE() nop(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
Definition: cpu_mips_instr.cc:3365
M88K_CMP_GE
#define M88K_CMP_GE
Definition: M88K_CPUComponent.h:275
m88k_cpu::delay_target
uint32_t delay_target
Definition: cpu_m88k.h:258
MACHINE_LUNA88K
#define MACHINE_LUNA88K
Definition: machine.h:258
M88K_EXCEPTION_SFU1_PRECISE
#define M88K_EXCEPTION_SFU1_PRECISE
Definition: M88K_CPUComponent.h:294
M88K_CMP_HI
#define M88K_CMP_HI
Definition: M88K_CPUComponent.h:274
machine::machine_type
int machine_type
Definition: machine.h:111
M88K_CMP_LT
#define M88K_CMP_LT
Definition: M88K_CPUComponent.h:276
M88K_CR_PSR
#define M88K_CR_PSR
Definition: M88K_CPUComponent.h:183
m88k_cpu::r
uint32_t r[N_M88K_REGS+1]
Definition: cpu_m88k.h:235
quick_pc_to_pointers
#define quick_pc_to_pointers(cpu)
Definition: quick_pc_to_pointers.h:29
M88K_EXCEPTION_UNIMPLEMENTED_OPCODE
#define M88K_EXCEPTION_UNIMPLEMENTED_OPCODE
Definition: M88K_CPUComponent.h:288
M88K_EXCEPTION_MISALIGNED_ACCESS
#define M88K_EXCEPTION_MISALIGNED_ACCESS
Definition: M88K_CPUComponent.h:287
cpu::translation_readahead
int translation_readahead
Definition: cpu.h:427
M88K_CMP_LO
#define M88K_CMP_LO
Definition: M88K_CPUComponent.h:272
m88k_cpu::fcr
uint32_t fcr[N_M88K_FPU_CONTROL_REGS]
Definition: cpu_m88k.h:244
cpu
Definition: cpu.h:326
M88K_CMP_GT
#define M88K_CMP_GT
Definition: M88K_CPUComponent.h:278
EXCEPTION_IN_DELAY_SLOT
#define EXCEPTION_IN_DELAY_SLOT
Definition: cpu.h:308
COMBINE
#define COMBINE(n)
Definition: tmp_alpha_tail.cc:61
cpu::memory_rw
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:368
m88k_cpu::zero_scratch
uint32_t zero_scratch
Definition: cpu_m88k.h:238
cpu::pc
uint64_t pc
Definition: cpu.h:386
M88K_CMP_LE
#define M88K_CMP_LE
Definition: M88K_CPUComponent.h:277
M88K_PROM_INSTR
#define M88K_PROM_INSTR
Definition: M88K_CPUComponent.h:304
M88K_LOADSTORE_REGISTEROFFSET
#define M88K_LOADSTORE_REGISTEROFFSET
Definition: cpu_m88k_instr.cc:305
m88k_fstcr
void m88k_fstcr(struct cpu *cpu, uint32_t value, int fcr)
Definition: cpu_m88k.cc:587
M88K_CR_EPSR
#define M88K_CR_EPSR
Definition: M88K_CPUComponent.h:184
mvmeprom_emul
int mvmeprom_emul(struct cpu *cpu)
Definition: mvmeprom.cc:99

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18