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