1 /*
2  *  Copyright (C) 2005-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  *  Motorola M881x0 CPU emulation.
29  *
30  *  M88100: Disassembly of (almost?) everything, and execution of most
31  *          instructions. Exception handling and virtual memory has also
32  *          been implemented. Exceptions while in delay slots may not work
33  *          fully yet, though.
34  *
35  *  M88110: Not yet.
36  */
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <unistd.h>
43 
44 #include "cpu.h"
45 #include "float_emul.h"
46 #include "interrupt.h"
47 #include "machine.h"
48 #include "memory.h"
49 #include "misc.h"
50 #include "settings.h"
51 #include "symbol.h"
52 
53 #include "thirdparty/m8820x_pte.h"
54 #include "thirdparty/m88k_dmt.h"
55 #include "thirdparty/mvmeprom.h"
56 
57 #define DYNTRANS_32
58 #define DYNTRANS_DELAYSLOT
59 #include "tmp_m88k_head.cc"
60 
61 
62 void m88k_pc_to_pointers(struct cpu *);
63 void m88k_cpu_functioncall_trace(struct cpu *cpu, int n_args);
64 
65 static const char *memop[4] = { ".d", "", ".h", ".b" };
66 
67 void m88k_irq_interrupt_assert(struct interrupt *interrupt);
68 void m88k_irq_interrupt_deassert(struct interrupt *interrupt);
69 
70 
71 static const char *m88k_cr_names[] = M88K_CR_NAMES;
72 static const char *m88k_cr_197_names[] = M88K_CR_NAMES_197;
73 
m88k_cr_name(struct cpu * cpu,int i)74 static const char *m88k_cr_name(struct cpu *cpu, int i)
75 {
76 	const char **cr_names = m88k_cr_names;
77 
78 	/*  Hm. Is this really MVME197 specific? TODO  */
79 	if (cpu->machine->machine_subtype == MACHINE_MVME88K_197)
80 		cr_names = m88k_cr_197_names;
81 
82 	return cr_names[i];
83 }
84 
m88k_fcr_name(struct cpu * cpu,int fi)85 static char *m88k_fcr_name(struct cpu *cpu, int fi)
86 {
87 	/*  TODO  */
88 	static char fcr_name[10];
89 	snprintf(fcr_name, sizeof(fcr_name), "FCR%i", fi);
90 	return fcr_name;
91 }
92 
93 
94 
95 /*
96  *  m88k_cpu_new():
97  *
98  *  Create a new M88K cpu object by filling the CPU struct.
99  *  Return 1 on success, 0 if cpu_type_name isn't a valid M88K processor.
100  */
m88k_cpu_new(struct cpu * cpu,struct memory * mem,struct machine * machine,int cpu_id,char * cpu_type_name)101 int m88k_cpu_new(struct cpu *cpu, struct memory *mem,
102 	struct machine *machine, int cpu_id, char *cpu_type_name)
103 {
104 	int i, found;
105 	struct m88k_cpu_type_def cpu_type_defs[] = M88K_CPU_TYPE_DEFS;
106 
107 	/*  Scan the list for this cpu type:  */
108 	i = 0; found = -1;
109 	while (i >= 0 && cpu_type_defs[i].name != NULL) {
110 		if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
111 			found = i;
112 			break;
113 		}
114 		i++;
115 	}
116 	if (found == -1)
117 		return 0;
118 
119 	cpu->run_instr = m88k_run_instr;
120 	cpu->memory_rw = m88k_memory_rw;
121 	cpu->update_translation_table = m88k_update_translation_table;
122 	cpu->invalidate_translation_caches =
123 	    m88k_invalidate_translation_caches;
124 	cpu->invalidate_code_translation = m88k_invalidate_code_translation;
125 	cpu->translate_v2p = m88k_translate_v2p;
126 
127 	cpu->cd.m88k.cpu_type = cpu_type_defs[found];
128 	cpu->name            = strdup(cpu->cd.m88k.cpu_type.name);
129 	cpu->is_32bit        = 1;
130 	cpu->byte_order      = EMUL_BIG_ENDIAN;
131 
132 	cpu->instruction_has_delayslot = m88k_cpu_instruction_has_delayslot;
133 
134 	/*  Only show name and caches etc for CPU nr 0:  */
135 	if (cpu_id == 0) {
136 		debug("%s", cpu->name);
137 	}
138 
139 
140 	/*
141 	 *  Add register names as settings:
142 	 */
143 
144 	CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
145 
146 	for (i=0; i<N_M88K_REGS; i++) {
147 		char name[10];
148 		snprintf(name, sizeof(name), "r%i", i);
149 		CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.r[i]);
150 	}
151 
152 	for (i=0; i<N_M88K_CONTROL_REGS; i++) {
153 		char name[10];
154 		snprintf(name, sizeof(name), "%s", m88k_cr_name(cpu, i));
155 		CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.cr[i]);
156 	}
157 
158 	for (i=0; i<N_M88K_FPU_CONTROL_REGS; i++) {
159 		char name[10];
160 		snprintf(name, sizeof(name), "%s", m88k_fcr_name(cpu, i));
161 		CPU_SETTINGS_ADD_REGISTER32(name, cpu->cd.m88k.fcr[i]);
162 	}
163 
164 
165 	/*  Register the CPU interrupt pin:  */
166 	{
167 		struct interrupt templ;
168 		char name[50];
169 		snprintf(name, sizeof(name), "%s", cpu->path);
170 
171 		memset(&templ, 0, sizeof(templ));
172 		templ.line = 0;
173 		templ.name = name;
174 		templ.extra = cpu;
175 		templ.interrupt_assert = m88k_irq_interrupt_assert;
176 		templ.interrupt_deassert = m88k_irq_interrupt_deassert;
177 		interrupt_handler_register(&templ);
178 	}
179 
180 	/*  Set the Processor ID:  */
181 	cpu->cd.m88k.cr[M88K_CR_PID] = cpu->cd.m88k.cpu_type.pid | M88K_PID_MC;
182 
183 	/*  Start in supervisor mode, with interrupts disabled.  */
184 	cpu->cd.m88k.cr[M88K_CR_PSR] = M88K_PSR_MODE | M88K_PSR_IND;
185 	if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
186 		cpu->cd.m88k.cr[M88K_CR_PSR] |= M88K_PSR_BO;
187 
188 	/*  Initial stack pointer:  */
189 	cpu->cd.m88k.r[31] = 1048576 * cpu->machine->physical_ram_in_mb - 1024;
190 
191 	return 1;
192 }
193 
194 
195 /*
196  *  m88k_cpu_dumpinfo():
197  */
m88k_cpu_dumpinfo(struct cpu * cpu)198 void m88k_cpu_dumpinfo(struct cpu *cpu)
199 {
200 	/*  struct m88k_cpu_type_def *ct = &cpu->cd.m88k.cpu_type;  */
201 
202 	debug(", %s-endian",
203 	    cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
204 
205 	debug("\n");
206 }
207 
208 
209 /*
210  *  m88k_cpu_list_available_types():
211  *
212  *  Print a list of available M88K CPU types.
213  */
m88k_cpu_list_available_types(void)214 void m88k_cpu_list_available_types(void)
215 {
216 	int i, j;
217 	struct m88k_cpu_type_def tdefs[] = M88K_CPU_TYPE_DEFS;
218 
219 	i = 0;
220 	while (tdefs[i].name != NULL) {
221 		debug("%s", tdefs[i].name);
222 		for (j=13 - strlen(tdefs[i].name); j>0; j--)
223 			debug(" ");
224 		i++;
225 		if ((i % 5) == 0 || tdefs[i].name == NULL)
226 			debug("\n");
227 	}
228 }
229 
230 
231 /*
232  *  m88k_cpu_instruction_has_delayslot():
233  *
234  *  Returns 1 if an opcode has a delay slot after it, 0 otherwise.
235  */
m88k_cpu_instruction_has_delayslot(struct cpu * cpu,unsigned char * ib)236 int m88k_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
237 {
238 	uint32_t iword = *((uint32_t *)&ib[0]);
239 
240 	if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
241 		iword = LE32_TO_HOST(iword);
242 	else
243 		iword = BE32_TO_HOST(iword);
244 
245 	switch (iword >> 26) {
246 	case 0x31:	/*  br.n  */
247 	case 0x33:	/*  bsr.n  */
248 	case 0x35:	/*  bb0.n  */
249 	case 0x37:	/*  bb1.n  */
250 	case 0x3b:	/*  bcnd.n  */
251 		return 1;
252 	case 0x3d:
253 		switch ((iword >> 8) & 0xff) {
254 		case 0xc4:	/*  jmp.n  */
255 		case 0xcc:	/*  jsr.n  */
256 			return 1;
257 		}
258 	}
259 
260 	return 0;
261 }
262 
263 
264 /*
265  *  m88k_cpu_register_dump():
266  *
267  *  Dump cpu registers in a relatively readable format.
268  *
269  *  gprs: set to non-zero to dump GPRs and some special-purpose registers.
270  *  coprocs: set bit 0..3 to dump registers in coproc 0..3.
271  */
m88k_cpu_register_dump(struct cpu * cpu,int gprs,int coprocs)272 void m88k_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
273 {
274 	char *symbol;
275 	uint64_t offset;
276 	int i, x = cpu->cpu_id;
277 
278 	if (gprs) {
279 		symbol = get_symbol_name(&cpu->machine->symbol_context,
280 		    cpu->pc, &offset);
281 		debug("cpu%i:  pc  = 0x%08" PRIx32, x, (uint32_t)cpu->pc);
282 		debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
283 
284 		for (i=0; i<N_M88K_REGS; i++) {
285 			if ((i % 4) == 0)
286 				debug("cpu%i:", x);
287 			if (i == 0)
288 				debug("                  ");
289 			else
290 				debug("  r%-2i = 0x%08" PRIx32,
291 				    i, cpu->cd.m88k.r[i]);
292 			if ((i % 4) == 3)
293 				debug("\n");
294 		}
295 	}
296 
297 	if (coprocs & 1) {
298 		int n_control_regs = 32;
299 
300 		/*  Hm. Is this really MVME197 specific? TODO  */
301 		if (cpu->machine->machine_subtype == MACHINE_MVME88K_197)
302 			n_control_regs = 64;
303 
304 		for (i=0; i<n_control_regs; i++) {
305 			if ((i % 4) == 0)
306 				debug("cpu%i:", x);
307 			debug("  %4s=0x%08" PRIx32,
308 			    m88k_cr_name(cpu, i), cpu->cd.m88k.cr[i]);
309 			if ((i % 4) == 3)
310 				debug("\n");
311 		}
312 	}
313 
314 	if (coprocs & 2) {
315 		int n_fpu_control_regs = 64;
316 
317 		for (i=0; i<n_fpu_control_regs; i++) {
318 			if ((i % 4) == 0)
319 				debug("cpu%i:", x);
320 			debug("  %5s=0x%08" PRIx32,
321 			    m88k_fcr_name(cpu, i), cpu->cd.m88k.fcr[i]);
322 			if ((i % 4) == 3)
323 				debug("\n");
324 		}
325 	}
326 }
327 
328 
329 /*
330  *  m88k_cpu_tlbdump():
331  *
332  *  Called from the debugger to dump the TLB in a readable format.
333  *  x is the cpu number to dump, or -1 to dump all CPUs.
334  *
335  *  If rawflag is nonzero, then the TLB contents isn't formated nicely,
336  *  just dumped.
337  */
m88k_cpu_tlbdump(struct machine * m,int x,int rawflag)338 void m88k_cpu_tlbdump(struct machine *m, int x, int rawflag)
339 {
340 	int cpu_nr, cmmu_nr, i;
341 
342 	for (cpu_nr = 0; cpu_nr < m->ncpus; cpu_nr++) {
343 		struct cpu *cpu = m->cpus[cpu_nr];
344 
345 		if (x != -1 && cpu_nr != x)
346 			continue;
347 
348 		for (cmmu_nr = 0; cmmu_nr < MAX_M8820X_CMMUS; cmmu_nr++) {
349 			struct m8820x_cmmu *cmmu = cpu->cd.m88k.cmmu[cmmu_nr];
350 			if (cmmu == NULL)
351 				continue;
352 
353 			printf("cpu%i: CMMU %i (%s)\n", cpu_nr, cmmu_nr,
354 			    cmmu_nr & 1? "data" : "instruction");
355 
356 			/*  BATC:  */
357 			for (i = 0; i < N_M88200_BATC_REGS; i++) {
358 				uint32_t b = cmmu->batc[i];
359 				printf("cpu%i: BATC[%2i]: ", cpu_nr, i);
360 				printf("v=0x%08" PRIx32, b & 0xfff80000);
361 				printf(", p=0x%08" PRIx32,
362 				    (b << 13) & 0xfff80000);
363 				printf(", %s %s %s %s %s %s\n",
364 				    b & BATC_SO? "SP " : "!sp",
365 				    b & BATC_WT? "WT " : "!wt",
366 				    b & BATC_GLOBAL? "G  " : "!g ",
367 				    b & BATC_INH? "CI " : "!ci",
368 				    b & BATC_PROT? "WP " : "!wp",
369 				    b & BATC_SO? "V " : "!v");
370 			}
371 
372 			/*  PATC:  */
373 			for (i = 0; i < N_M88200_PATC_ENTRIES; i++) {
374 				uint32_t v = cmmu->patc_v_and_control[i];
375 				uint32_t p = cmmu->patc_p_and_supervisorbit[i];
376 
377 				printf("cpu%i: patc[%2i]: ", cpu_nr, i);
378 				if (p & M8820X_PATC_SUPERVISOR_BIT)
379 					printf("superv");
380 				else
381 					printf("user  ");
382 				printf(" v=0x%08" PRIx32, v & 0xfffff000);
383 				printf(", p=0x%08" PRIx32, p & 0xfffff000);
384 
385 				printf("  %s %s %s %s %s %s %s",
386 				    v & PG_U1?   "U1 " : "!u1",
387 				    v & PG_U0?   "U0 " : "!u0",
388 				    v & PG_SO?   "SP " : "!sp",
389 				    v & PG_M?    "M "  : "!m",
390 				    v & PG_U?    "U "  : "!u",
391 				    v & PG_PROT? "WP " : "!wp",
392 				    v & PG_V?    "V "  : "!v");
393 
394 				if (i == cmmu->patc_update_index)
395 					printf(" <--");
396 				printf("\n");
397 			}
398 		}
399 	}
400 }
401 
402 
403 /*
404  *  m88k_irq_interrupt_assert():
405  *  m88k_irq_interrupt_deassert():
406  */
m88k_irq_interrupt_assert(struct interrupt * interrupt)407 void m88k_irq_interrupt_assert(struct interrupt *interrupt)
408 {
409 	struct cpu *cpu = (struct cpu *) interrupt->extra;
410 	cpu->cd.m88k.irq_asserted = 1;
411 }
m88k_irq_interrupt_deassert(struct interrupt * interrupt)412 void m88k_irq_interrupt_deassert(struct interrupt *interrupt)
413 {
414 	struct cpu *cpu = (struct cpu *) interrupt->extra;
415 	cpu->cd.m88k.irq_asserted = 0;
416 }
417 
418 
419 /*
420  *  m88k_ldcr():
421  *
422  *  Read from a control register. Store the resulting value in a register
423  *  (pointed to by r32ptr).
424  */
m88k_ldcr(struct cpu * cpu,uint32_t * r32ptr,int cr)425 void m88k_ldcr(struct cpu *cpu, uint32_t *r32ptr, int cr)
426 {
427 	uint32_t retval = cpu->cd.m88k.cr[cr];
428 
429 	switch (cr) {
430 
431 	case M88K_CR_PID:
432 	case M88K_CR_PSR:
433 	case M88K_CR_EPSR:
434 	case M88K_CR_SSBR:
435 	case M88K_CR_SXIP:
436 	case M88K_CR_SNIP:
437 	case M88K_CR_SFIP:
438 	case M88K_CR_VBR:
439 	case M88K_CR_DMD0:
440 	case M88K_CR_DMD1:
441 	case M88K_CR_DMD2:
442 	case M88K_CR_SR0:
443 	case M88K_CR_SR1:
444 	case M88K_CR_SR2:
445 	case M88K_CR_SR3:
446 		break;
447 
448 	case M88K_CR_DMT0:
449 	case M88K_CR_DMT1:
450 	case M88K_CR_DMT2:
451 		/*
452 		 *  Catch some possible internal errors in the emulator:
453 		 *
454 		 *  For valid memory Load transactions, the Destination Register
455 		 *  should not be zero.
456 		 *
457 		 *  The Byte Order bit should be the same as the CPU's.
458 		 */
459 		if (retval & DMT_VALID && !(retval & DMT_WRITE)) {
460 			if (DMT_DREGBITS(retval) == M88K_ZERO_REG) {
461 				fatal("DMT DREG = zero? Internal error.\n");
462 				exit(1);
463 			}
464 		}
465 		if (!!(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_BO)
466 		    != !!(retval & DMT_BO) && retval & DMT_VALID) {
467 			fatal("DMT byte order not same as CPUs?\n");
468 			exit(1);
469 		}
470 
471 		break;
472 
473 	case M88K_CR_DMA0:
474 	case M88K_CR_DMA1:
475 	case M88K_CR_DMA2:
476 		/*
477 		 *  Catch some possible internal errors in the emulator:
478 		 *  The lowest 2 bits of the transaction address registers
479 		 *  should always be zero.
480 		 */
481 		if (retval & 3) {
482 			fatal("DMAx not word-aligned? Internal error.\n");
483 			exit(1);
484 		}
485 
486 		break;
487 
488 	default:fatal("m88k_ldcr: UNIMPLEMENTED cr = 0x%02x (%s)\n",
489 		    cr, m88k_cr_name(cpu, cr));
490 		exit(1);
491 	}
492 
493 	*r32ptr = retval;
494 }
495 
496 
497 /*
498  *  m88k_stcr():
499  *
500  *  Write to a control register.
501  *  (Used by both the stcr and rte instructions.)
502  */
m88k_stcr(struct cpu * cpu,uint32_t value,int cr,int rte)503 void m88k_stcr(struct cpu *cpu, uint32_t value, int cr, int rte)
504 {
505 	uint32_t old = cpu->cd.m88k.cr[cr];
506 
507 	switch (cr) {
508 
509 	case M88K_CR_PSR:	/*  Processor Status Register  */
510 		if ((cpu->byte_order == EMUL_LITTLE_ENDIAN
511 		    && !(value & M88K_PSR_BO)) ||
512 		    (cpu->byte_order == EMUL_BIG_ENDIAN
513 		    && (value & M88K_PSR_BO))) {
514 			fatal("TODO: attempt to change endianness by flipping"
515 			    " the endianness bit in the PSR. How should this"
516 			    " be handled? Aborting.\n");
517 			exit(1);
518 		}
519 
520 		if (!rte && old & M88K_PSR_MODE && !(value & M88K_PSR_MODE))
521 			fatal("[ m88k_stcr: WARNING! the PSR_MODE bit is being"
522 			    " cleared; this should be done using the RTE "
523 			    "instruction only, according to the M88100 "
524 			    "manual! Continuing anyway. ]\n");
525 
526 		if (value & M88K_PSR_MXM) {
527 			fatal("m88k_stcr: TODO: MXM support\n");
528 			exit(1);
529 		}
530 
531 		if ((old & M88K_PSR_MODE) != (value & M88K_PSR_MODE))
532 			cpu->invalidate_translation_caches(
533 			    cpu, 0, INVALIDATE_ALL);
534 
535 		cpu->cd.m88k.cr[cr] = value;
536 		break;
537 
538 	case M88K_CR_EPSR:
539 		cpu->cd.m88k.cr[cr] = value;
540 		break;
541 
542 	case M88K_CR_SXIP:
543 	case M88K_CR_SNIP:
544 	case M88K_CR_SFIP:
545 		cpu->cd.m88k.cr[cr] = value;
546 		break;
547 
548 	case M88K_CR_SSBR:	/*  Shadow ScoreBoard Register  */
549 		if (value & 1)
550 			fatal("[ m88k_stcr: WARNING! bit 0 non-zero when"
551 			    " writing to SSBR (?) ]\n");
552 		cpu->cd.m88k.cr[cr] = value;
553 		break;
554 
555 	case M88K_CR_VBR:
556 		if (value & 0x00000fff)
557 			fatal("[ m88k_stcr: WARNING! bits 0..11 non-zero when"
558 			    " writing to VBR (?) ]\n");
559 		cpu->cd.m88k.cr[cr] = value;
560 		break;
561 
562 	case M88K_CR_DMT0:
563 	case M88K_CR_DMT1:
564 	case M88K_CR_DMT2:
565 		cpu->cd.m88k.cr[cr] = value;
566 		break;
567 
568 	case M88K_CR_SR0:	/*  Supervisor Storage Registers 0..3  */
569 	case M88K_CR_SR1:
570 	case M88K_CR_SR2:
571 	case M88K_CR_SR3:
572 		cpu->cd.m88k.cr[cr] = value;
573 		break;
574 
575 	default:fatal("m88k_stcr: UNIMPLEMENTED cr = 0x%02x (%s)\n",
576 		    cr, m88k_cr_name(cpu, cr));
577 		exit(1);
578 	}
579 }
580 
581 
582 /*
583  *  m88k_fstcr():
584  *
585  *  Write to a floating-point control register.
586  */
m88k_fstcr(struct cpu * cpu,uint32_t value,int fcr)587 void m88k_fstcr(struct cpu *cpu, uint32_t value, int fcr)
588 {
589 #if 0
590 	/*  TODO (?)  */
591 	uint32_t old = cpu->cd.m88k.cr[fcr];
592 
593 	switch (fcr) {
594 	default:fatal("m88k_fstcr: UNIMPLEMENTED fcr = 0x%02x (%s)\n",
595 		    fcr, m88k_fcr_name(cpu, fcr));
596 		exit(1);
597 	}
598 #else
599 	cpu->cd.m88k.cr[fcr] = value;
600 #endif
601 }
602 
603 
604 /*
605  *  m88k_memory_transaction_debug_dump():
606  *
607  *  Debug dump of the memory transaction registers of a cpu.
608  */
m88k_memory_transaction_debug_dump(struct cpu * cpu,int n)609 static void m88k_memory_transaction_debug_dump(struct cpu *cpu, int n)
610 {
611 	uint32_t dmt = cpu->cd.m88k.dmt[n];
612 
613 	debug("[ DMT%i: ", n);
614 	if (dmt & DMT_VALID) {
615 		if (dmt & DMT_BO)
616 			debug("Little-Endian, ");
617 		else
618 			debug("Big-Endian, ");
619 		if (dmt & DMT_DAS)
620 			debug("Supervisor, ");
621 		else
622 			debug("User, ");
623 		if (dmt & DMT_DOUB1)
624 			debug("DOUB1, ");
625 		if (dmt & DMT_LOCKBAR)
626 			debug("LOCKBAR, ");
627 		if (dmt & DMT_WRITE)
628 			debug("store, ");
629 		else {
630 			debug("load.%c(r%i), ",
631 			    dmt & DMT_SIGNED? 's' : 'u',
632 			    DMT_DREGBITS(dmt));
633 		}
634 		debug("bytebits=0x%x ]\n", DMT_ENBITS(dmt));
635 
636 		debug("[ DMD%i: 0x%08" PRIx32"; ", n, cpu->cd.m88k.dmd[n]);
637 		debug("DMA%i: 0x%08" PRIx32" ]\n", n, cpu->cd.m88k.dma[n]);
638 	} else
639 		debug("not valid ]\n");
640 }
641 
642 
643 /*
644  *  m88k_exception():
645  *
646  *  Cause an exception.
647  */
m88k_exception(struct cpu * cpu,int vector,int is_trap)648 void m88k_exception(struct cpu *cpu, int vector, int is_trap)
649 {
650 	int update_shadow_regs = 1;
651 
652 	debug("[ EXCEPTION 0x%03x: ", vector);
653 	switch (vector) {
654 	case M88K_EXCEPTION_RESET:
655 		debug("RESET"); break;
656 	case M88K_EXCEPTION_INTERRUPT:
657 		debug("INTERRUPT"); break;
658 	case M88K_EXCEPTION_INSTRUCTION_ACCESS:
659 		debug("INSTRUCTION_ACCESS"); break;
660 	case M88K_EXCEPTION_DATA_ACCESS:
661 		debug("DATA_ACCESS"); break;
662 	case M88K_EXCEPTION_MISALIGNED_ACCESS:
663 		debug("MISALIGNED_ACCESS"); break;
664 	case M88K_EXCEPTION_UNIMPLEMENTED_OPCODE:
665 		debug("UNIMPLEMENTED_OPCODE"); break;
666 	case M88K_EXCEPTION_PRIVILEGE_VIOLATION:
667 		debug("PRIVILEGE_VIOLATION"); break;
668 	case M88K_EXCEPTION_BOUNDS_CHECK_VIOLATION:
669 		debug("BOUNDS_CHECK_VIOLATION"); break;
670 	case M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE:
671 		debug("ILLEGAL_INTEGER_DIVIDE"); break;
672 	case M88K_EXCEPTION_INTEGER_OVERFLOW:
673 		debug("INTEGER_OVERFLOW"); break;
674 	case M88K_EXCEPTION_ERROR:
675 		debug("ERROR"); break;
676 	case M88K_EXCEPTION_SFU1_PRECISE:
677 		debug("SFU1_PRECISE"); break;
678 	case M88K_EXCEPTION_SFU1_IMPRECISE:
679 		debug("SFU1_IMPRECISE"); break;
680 	case 0x80:	/*  up to OpenBSD 5.2  */
681 	case 0x1c2:	/*  from OpenBSD 5.3 and forward...  */
682 #if 0
683 		fatal("[ syscall %i(", cpu->cd.m88k.r[13]);
684 		m88k_cpu_functioncall_trace(cpu, 8);
685 		fatal(") ]\n");
686 #endif
687 		debug("syscall, r13=%i", cpu->cd.m88k.r[13]); break;
688 	case MVMEPROM_VECTOR:
689 		debug("MVMEPROM_VECTOR"); break;
690 	default:debug("unknown"); break;
691 	}
692 	debug(" ]\n");
693 
694 	/*  Stuff common for all exceptions:  */
695 	if (cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_SFRZ) {
696 		/*
697 		 *  Non-trap exceptions when the shadow freeze bit is already
698 		 *  set result in an Error exception:
699 		 */
700 		if (!is_trap) {
701 			vector = M88K_EXCEPTION_ERROR;
702 			fatal("[ SFRZ already set in PSR => ERROR ]\n");
703 		}
704 
705 		update_shadow_regs = 0;
706 	} else {
707 		/*  Freeze shadow registers, and save the PSR:  */
708 		cpu->cd.m88k.cr[M88K_CR_EPSR] = cpu->cd.m88k.cr[M88K_CR_PSR];
709 	}
710 
711 	m88k_stcr(cpu, cpu->cd.m88k.cr[M88K_CR_PSR]
712 	    | M88K_PSR_SFRZ	/*  Freeze shadow registers,          */
713 	    | M88K_PSR_IND	/*  disable interrupts,               */
714 	    | M88K_PSR_SFD1	/*  disable the floating point unit,  */
715 	    | M88K_PSR_MODE,	/*  and switch to supervisor mode.    */
716 	    M88K_CR_PSR, 0);
717 
718 	if (update_shadow_regs) {
719 		cpu->cd.m88k.cr[M88K_CR_SSBR] = 0;
720 
721 		cpu->cd.m88k.cr[M88K_CR_SXIP] = cpu->pc | M88K_XIP_V;
722 
723 		/*  SNIP is the address to return to, when executing rte:  */
724 		if (cpu->delay_slot) {
725 			if (vector == M88K_EXCEPTION_DATA_ACCESS) {
726 				cpu->cd.m88k.cr[M88K_CR_SNIP] = cpu->cd.m88k.delay_target | M88K_NIP_V;
727 				cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->cd.m88k.cr[M88K_CR_SNIP]+4;
728 			} else if (vector == M88K_EXCEPTION_INSTRUCTION_ACCESS) {
729 				/*  If we are in a delay slot, then pc is
730 				    something like 0xc6000 here (not 0xc5ffc).  */
731 				cpu->cd.m88k.cr[M88K_CR_SNIP] = cpu->cd.m88k.delay_target | M88K_NIP_V;
732 				cpu->cd.m88k.cr[M88K_CR_SFIP] = 0;
733 			} else {
734 				/*  Perhaps something like this could work:  */
735 				cpu->cd.m88k.cr[M88K_CR_SNIP] = (cpu->pc + 4) | M88K_NIP_V;
736 				cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->cd.m88k.delay_target | M88K_NIP_V;
737 			}
738 		} else {
739 			cpu->cd.m88k.cr[M88K_CR_SNIP] = (cpu->pc + 4) | M88K_NIP_V;
740 			cpu->cd.m88k.cr[M88K_CR_SFIP] = cpu->cd.m88k.cr[M88K_CR_SNIP]+4;
741 		}
742 
743 		if (vector == M88K_EXCEPTION_INSTRUCTION_ACCESS)
744 			cpu->cd.m88k.cr[M88K_CR_SXIP] |= M88K_XIP_E;
745 	}
746 
747 	cpu->pc = cpu->cd.m88k.cr[M88K_CR_VBR] + 8 * vector;
748 
749 	if (cpu->delay_slot)
750 		cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
751 	else
752 		cpu->delay_slot = NOT_DELAYED;
753 
754 	/*  Default to no memory transactions:  */
755 	cpu->cd.m88k.cr[M88K_CR_DMT0] = 0;
756 	cpu->cd.m88k.cr[M88K_CR_DMD0] = 0;
757 	cpu->cd.m88k.cr[M88K_CR_DMA0] = 0;
758 	cpu->cd.m88k.cr[M88K_CR_DMT1] = 0;
759 	cpu->cd.m88k.cr[M88K_CR_DMD1] = 0;
760 	cpu->cd.m88k.cr[M88K_CR_DMA1] = 0;
761 	cpu->cd.m88k.cr[M88K_CR_DMT2] = 0;
762 	cpu->cd.m88k.cr[M88K_CR_DMD2] = 0;
763 	cpu->cd.m88k.cr[M88K_CR_DMA2] = 0;
764 
765 	/*  Vector-specific handling:  */
766 	if (vector < M88K_EXCEPTION_USER_TRAPS_START) {
767 		switch (vector) {
768 
769 		case M88K_EXCEPTION_RESET:
770 			fatal("[ m88k_exception: reset ]\n");
771 			exit(1);
772 
773 		case M88K_EXCEPTION_INTERRUPT:
774 			/*  When returning with rte, we want to re-  */
775 			/*  execute the interrupted instruction:  */
776 			cpu->cd.m88k.cr[M88K_CR_SNIP] -= 4;
777 			cpu->cd.m88k.cr[M88K_CR_SFIP] -= 4;
778 			break;
779 
780 		case M88K_EXCEPTION_INSTRUCTION_ACCESS:
781 			/*  When returning with rte, we want to re-  */
782 			/*  execute the instruction in SXIP, not SNIP/SFIP,  */
783 			/*  (unless the exception was in a delay-slot):  */
784 			if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
785 				cpu->cd.m88k.cr[M88K_CR_SNIP] = 0;
786 				cpu->cd.m88k.cr[M88K_CR_SFIP] = 0;
787 			}
788 			break;
789 
790 		case M88K_EXCEPTION_DATA_ACCESS:
791 			/*  Update the memory transaction registers:  */
792 			cpu->cd.m88k.cr[M88K_CR_DMT0] = cpu->cd.m88k.dmt[0];
793 			cpu->cd.m88k.cr[M88K_CR_DMD0] = cpu->cd.m88k.dmd[0];
794 			cpu->cd.m88k.cr[M88K_CR_DMA0] = cpu->cd.m88k.dma[0];
795 			cpu->cd.m88k.cr[M88K_CR_DMT1] = cpu->cd.m88k.dmt[1];
796 			cpu->cd.m88k.cr[M88K_CR_DMD1] = cpu->cd.m88k.dmd[1];
797 			cpu->cd.m88k.cr[M88K_CR_DMA1] = cpu->cd.m88k.dma[1];
798 			cpu->cd.m88k.cr[M88K_CR_DMT2] = 0;
799 			cpu->cd.m88k.cr[M88K_CR_DMD2] = 0;
800 			cpu->cd.m88k.cr[M88K_CR_DMA2] = 0;
801 			m88k_memory_transaction_debug_dump(cpu, 0);
802 			m88k_memory_transaction_debug_dump(cpu, 1);
803 			break;
804 
805 #if 0
806 		case M88K_EXCEPTION_ILLEGAL_INTEGER_DIVIDE:
807 			/*  TODO: Is it correct to continue on the instruction
808 			    _after_ the division by zero? Or should the PC
809 			    be backed up one step?  */
810 			break;
811 #endif
812 
813 #if 0
814 		// TODO: Read up more about SFU1 exceptions and how the
815 		// control registers look when they happen.
816 		case M88K_EXCEPTION_SFU1_PRECISE:
817 			cpu->cd.m88k.cr[M88K_CR_SNIP] = 0; //?
818 			cpu->cd.m88k.cr[M88K_CR_SFIP] = 0;
819 			//cpu->cd.m88k.cr[M88K_CR_SNIP] -= 4;
820 			//cpu->cd.m88k.cr[M88K_CR_SFIP] -= 4;
821 			break;
822 #endif
823 
824 		default:fatal("m88k_exception(): 0x%x: SXIP=0x%08x pc=0x%08x TODO\n",
825 			vector,
826 			cpu->cd.m88k.cr[M88K_CR_SXIP],
827 			(int)cpu->pc);
828 			fflush(stdout);
829 			exit(1);
830 		}
831 	}
832 
833 	m88k_pc_to_pointers(cpu);
834 }
835 
836 
837 /*
838  *  m88k_cpu_disassemble_instr():
839  *
840  *  Convert an instruction word into human readable format, for instruction
841  *  tracing.
842  *
843  *  If running is 1, cpu->pc should be the address of the instruction.
844  *
845  *  If running is 0, things that depend on the runtime environment (eg.
846  *  register contents) will not be shown, and dumpaddr will be used instead of
847  *  cpu->pc for relative addresses.
848  */
m88k_cpu_disassemble_instr(struct cpu * cpu,unsigned char * ib,int running,uint64_t dumpaddr)849 int m88k_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
850         int running, uint64_t dumpaddr)
851 {
852 	int supervisor = cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE;
853 	uint32_t iw;
854 	const char *symbol, *mnem = NULL;
855 	uint64_t offset;
856 	uint32_t op26, op10, op11, d, s1, s2, w5, cr6, imm16;
857 	int32_t d16, d26;
858 
859 	if (running)
860 		dumpaddr = cpu->pc;
861 
862 	symbol = get_symbol_name(&cpu->machine->symbol_context,
863 	    dumpaddr, &offset);
864 	if (symbol != NULL && offset == 0 && supervisor)
865 		debug("<%s>\n", symbol);
866 
867 	if (cpu->machine->ncpus > 1 && running)
868 		debug("cpu%i:\t", cpu->cpu_id);
869 
870 	debug("%c%08" PRIx32": ",
871 	    cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE? 's' : 'u',
872 	    (uint32_t) dumpaddr);
873 
874 	if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
875 		iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
876 	else
877 		iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
878 
879 	debug("%08" PRIx32, (uint32_t) iw);
880 
881 	if (running && cpu->delay_slot)
882 		debug(" (d)");
883 
884 	debug("\t");
885 
886 	op26   = (iw >> 26) & 0x3f;
887 	op11   = (iw >> 11) & 0x1f;
888 	op10   = (iw >> 10) & 0x3f;
889 	d      = (iw >> 21) & 0x1f;
890 	s1     = (iw >> 16) & 0x1f;
891 	s2     =  iw        & 0x1f;
892 	imm16  = iw & 0xffff;
893 	w5     = (iw >>  5) & 0x1f;
894 	cr6    = (iw >>  5) & 0x3f;
895 	d16    = ((int16_t) (iw & 0xffff)) * 4;
896 	d26    = ((int32_t)((iw & 0x03ffffff) << 6)) >> 4;
897 
898 	switch (op26) {
899 
900 	case 0x00:	/*  xmem.bu  */
901 	case 0x01:	/*  xmem     */
902 	case 0x02:	/*  ld.hu    */
903 	case 0x03:	/*  ld.bu    */
904 	case 0x04:	/*  ld.d     */
905 	case 0x05:	/*  ld       */
906 	case 0x06:	/*  ld.h     */
907 	case 0x07:	/*  ld.b     */
908 	case 0x08:	/*  st.d     */
909 	case 0x09:	/*  st       */
910 	case 0x0a:	/*  st.h     */
911 	case 0x0b:	/*  st.b     */
912 		if (iw == 0x00000000) {
913 			debug("-\n");
914 			break;
915 		}
916 		switch (op26) {
917 		case 0x00:  debug("xmem.bu"); break;
918 		case 0x01:  debug("xmem"); break;
919 		case 0x02:  debug("ld.hu"); break;
920 		case 0x03:  debug("ld.bu"); break;
921 		default:    debug("%s%s", op26 >= 0x08? "st" : "ld",
922 				memop[op26 & 3]);
923 		}
924 		debug("\tr%i,r%i,0x%x", d, s1, imm16);
925 		if (running) {
926 			uint32_t tmpaddr = cpu->cd.m88k.r[s1] + imm16;
927 			symbol = get_symbol_name(&cpu->machine->symbol_context,
928 			    tmpaddr, &offset);
929 			if (symbol != NULL && supervisor)
930 				debug("\t; [<%s>]", symbol);
931 			else
932 				debug("\t; [0x%08" PRIx32"]", tmpaddr);
933 			if (op26 >= 0x08) {
934 				/*  Store:  */
935 				debug(" = ");
936 				switch (op26 & 3) {
937 				case 0:	debug("0x%016" PRIx64, (uint64_t)
938 					    ((((uint64_t) cpu->cd.m88k.r[d])
939 					    << 32) + ((uint64_t)
940 					    cpu->cd.m88k.r[d+1])) );
941 					break;
942 				case 1:	debug("0x%08" PRIx32,
943 					    (uint32_t) cpu->cd.m88k.r[d]);
944 					break;
945 				case 2:	debug("0x%04" PRIx16,
946 					    (uint16_t) cpu->cd.m88k.r[d]);
947 					break;
948 				case 3:	debug("0x%02" PRIx8,
949 					    (uint8_t) cpu->cd.m88k.r[d]);
950 					break;
951 				}
952 			} else {
953 				/*  Load:  */
954 				/*  TODO  */
955 			}
956 		} else {
957 			/*
958 			 *  Not running, but the following instruction
959 			 *  sequence is quite common:
960 			 *
961 			 *  or.u      rX,r0,A
962 			 *  st_or_ld  rY,rX,B
963 			 */
964 
965 			/*  Try loading the instruction before the
966 			    current one.  */
967 			uint32_t iw2 = 0;
968 			cpu->memory_rw(cpu, cpu->mem,
969 			    dumpaddr - sizeof(uint32_t), (unsigned char *)&iw2,
970 			    sizeof(iw2), MEM_READ, CACHE_INSTRUCTION
971 			    | NO_EXCEPTIONS);
972 			if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
973 				 iw2 = LE32_TO_HOST(iw2);
974 			else
975 				 iw2 = BE32_TO_HOST(iw2);
976 			if ((iw2 >> 26) == 0x17 &&	/*  or.u  */
977 			    ((iw2 >> 21) & 0x1f) == s1) {
978 				uint32_t tmpaddr = (iw2 << 16) + imm16;
979 				symbol = get_symbol_name(
980 				    &cpu->machine->symbol_context,
981 				    tmpaddr, &offset);
982 				if (symbol != NULL && supervisor)
983 					debug("\t; [<%s>]", symbol);
984 				else
985 					debug("\t; [0x%08" PRIx32"]", tmpaddr);
986 			}
987 		}
988 		debug("\n");
989 		break;
990 
991 	case 0x10:	/*  and     */
992 	case 0x11:	/*  and.u   */
993 	case 0x12:	/*  mask    */
994 	case 0x13:	/*  mask.u  */
995 	case 0x14:	/*  xor     */
996 	case 0x15:	/*  xor.u   */
997 	case 0x16:	/*  or      */
998 	case 0x17:	/*  or.u    */
999 		if (d == M88K_ZERO_REG)
1000 			debug("nop");
1001 
1002 		switch (op26) {
1003 		case 0x10:
1004 		case 0x11:	mnem = "and"; break;
1005 		case 0x12:
1006 		case 0x13:	mnem = "mask"; break;
1007 		case 0x14:
1008 		case 0x15:	mnem = "xor"; break;
1009 		case 0x16:
1010 		case 0x17:	mnem = "or"; break;
1011 		}
1012 
1013 		if (d != M88K_ZERO_REG || op26 != 0x16 || s1 != M88K_ZERO_REG) {
1014 			if (d == M88K_ZERO_REG)
1015 				debug("\t\t; weird nop encoding: ");
1016 			debug("%s%s\t", mnem, op26 & 1? ".u" : "");
1017 			debug("r%i,r%i,0x%x", d, s1, imm16);
1018 		}
1019 
1020 		if (op26 == 0x16 && d != M88K_ZERO_REG) {
1021 			/*
1022 			 *  The following instruction sequence is common:
1023 			 *
1024 			 *  or.u   rX,r0,A
1025 			 *  or     rY,rX,B	; rY = AAAABBBB
1026 			 */
1027 
1028 			/*  Try loading the instruction before the
1029 			    current one.  */
1030 			uint32_t iw2 = 0;
1031 			cpu->memory_rw(cpu, cpu->mem,
1032 			    dumpaddr - sizeof(uint32_t), (unsigned char *)&iw2,
1033 			    sizeof(iw2), MEM_READ, CACHE_INSTRUCTION
1034 			    | NO_EXCEPTIONS);
1035 			if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1036 				 iw2 = LE32_TO_HOST(iw2);
1037 			else
1038 				 iw2 = BE32_TO_HOST(iw2);
1039 			if ((iw2 >> 26) == 0x17 &&	/*  or.u  */
1040 			    ((iw2 >> 21) & 0x1f) == s1) {
1041 				uint32_t tmpaddr = (iw2 << 16) + imm16;
1042 				symbol = get_symbol_name(
1043 				    &cpu->machine->symbol_context,
1044 				    tmpaddr, &offset);
1045 				debug("\t; ");
1046 				if (symbol != NULL && supervisor)
1047 					debug("<%s>", symbol);
1048 				else
1049 					debug("0x%08" PRIx32, tmpaddr);
1050 			}
1051 		}
1052 
1053 		debug("\n");
1054 		break;
1055 
1056 	case 0x18:	/*  addu    */
1057 	case 0x19:	/*  subu    */
1058 	case 0x1a:	/*  divu    */
1059 	case 0x1b:	/*  mulu    */
1060 	case 0x1c:	/*  add    */
1061 	case 0x1d:	/*  sub    */
1062 	case 0x1e:	/*  div    */
1063 	case 0x1f:	/*  cmp    */
1064 		switch (op26) {
1065 		case 0x18:	mnem = "addu"; break;
1066 		case 0x19:	mnem = "subu"; break;
1067 		case 0x1a:	mnem = "divu"; break;
1068 		case 0x1b:	mnem = "mulu"; break;
1069 		case 0x1c:	mnem = "add"; break;
1070 		case 0x1d:	mnem = "sub"; break;
1071 		case 0x1e:	mnem = "div"; break;
1072 		case 0x1f:	mnem = "cmp"; break;
1073 		}
1074 		debug("%s\tr%i,r%i,%i\n", mnem, d, s1, imm16);
1075 		break;
1076 
1077 	case 0x20:
1078 		if ((iw & 0x001ff81f) == 0x00004000) {
1079 			debug("ldcr\tr%i,%s", d, m88k_cr_name(cpu, cr6));
1080 			if (running)
1081 				debug("\t\t; %s = 0x%08x", m88k_cr_name(cpu, cr6), cpu->cd.m88k.cr[cr6]);
1082 			debug("\n");
1083 		} else if ((iw & 0x001ff81f) == 0x00004800) {
1084 			debug("fldcr\tr%i,%s\n", d, m88k_fcr_name(cpu, cr6));
1085 		} else if ((iw & 0x03e0f800) == 0x00008000) {
1086 			debug("stcr\tr%i,%s", s1, m88k_cr_name(cpu, cr6));
1087 			if (s1 != s2)
1088 				debug("\t\t; NOTE: weird encoding: "
1089 				    "low 5 bits = 0x%02x", s2);
1090 			if (running)
1091 				debug("\t\t; r%i = 0x%08x", s1, cpu->cd.m88k.r[s1]);
1092 			debug("\n");
1093 		} else if ((iw & 0x03e0f800) == 0x00008800) {
1094 			debug("fstcr\tr%i,%s", s1,
1095 			    m88k_fcr_name(cpu, cr6));
1096 			if (s1 != s2)
1097 				debug("\t\t; NOTE: weird encoding: "
1098 				    "low 5 bits = 0x%02x", s2);
1099 			debug("\n");
1100 		} else if ((iw & 0x0000f800) == 0x0000c000) {
1101 			debug("xcr\tr%i,r%i,%s", d, s1,
1102 			    m88k_cr_name(cpu, cr6));
1103 			if (s1 != s2)
1104 				debug("\t\t; NOTE: weird encoding: "
1105 				    "low 5 bits = 0x%02x", s2);
1106 			debug("\n");
1107 		} else if ((iw & 0x0000f800) == 0x0000c800) {
1108 			debug("fxcr\tr%i,r%i,%s", d, s1,
1109 			    m88k_fcr_name(cpu, cr6));
1110 			if (s1 != s2)
1111 				debug("\t\t; NOTE: weird encoding: "
1112 				    "low 5 bits = 0x%02x", s2);
1113 			debug("\n");
1114 		} else {
1115 			debug("UNIMPLEMENTED 0x20\n");
1116 		}
1117 		break;
1118 
1119 	case 0x21:
1120 		switch (op11) {
1121 		case 0x00:	/*  fmul  */
1122 		case 0x05:	/*  fadd  */
1123 		case 0x06:	/*  fsub  */
1124 		case 0x07:	/*  fcmp  */
1125 		case 0x0e:	/*  fdiv  */
1126 			switch (op11) {
1127 			case 0x00: mnem = "fmul"; break;
1128 			case 0x05: mnem = "fadd"; break;
1129 			case 0x06: mnem = "fsub"; break;
1130 			case 0x07: mnem = "fcmp"; break;
1131 			case 0x0e: mnem = "fdiv"; break;
1132 			}
1133 			debug("%s.%c%c%c r%i,r%i,r%i\n",
1134 			    mnem,
1135 			    ((iw >> 5) & 1)? 'd' : 's',
1136 			    ((iw >> 9) & 1)? 'd' : 's',
1137 			    ((iw >> 7) & 1)? 'd' : 's',
1138 			    d, s1, s2);
1139 			break;
1140 		case 0x04:	/*  flt  */
1141 			switch (op11) {
1142 			case 0x04: mnem = "flt"; break;
1143 			}
1144 			debug("%s.%cs\tr%i,r%i\n",
1145 			    mnem,
1146 			    ((iw >> 5) & 1)? 'd' : 's',
1147 			    d, s2);
1148 			break;
1149 		case 0x09:	/*  int  */
1150 		case 0x0a:	/*  nint  */
1151 		case 0x0b:	/*  trnc  */
1152 			switch (op11) {
1153 			case 0x09: mnem = "int"; break;
1154 			case 0x0a: mnem = "nint"; break;
1155 			case 0x0b: mnem = "trnc"; break;
1156 			}
1157 			debug("%s.s%c r%i,r%i\n",
1158 			    mnem,
1159 			    ((iw >> 7) & 1)? 'd' : 's',
1160 			    d, s2);
1161 			break;
1162 		default:debug("UNIMPLEMENTED 0x21, op11=0x%02x\n", op11);
1163 		}
1164 		break;
1165 
1166 	case 0x30:
1167 	case 0x31:
1168 	case 0x32:
1169 	case 0x33:
1170 		debug("b%sr%s\t",
1171 		    op26 >= 0x32? "s" : "",
1172 		    op26 & 1? ".n" : "");
1173 		debug("0x%08" PRIx32, (uint32_t) (dumpaddr + d26));
1174 		symbol = get_symbol_name(&cpu->machine->symbol_context,
1175 		    dumpaddr + d26, &offset);
1176 		if (symbol != NULL && supervisor)
1177 			debug("\t; <%s>", symbol);
1178 		debug("\n");
1179 		break;
1180 
1181 	case 0x34:	/*  bb0    */
1182 	case 0x35:	/*  bb0.n  */
1183 	case 0x36:	/*  bb1    */
1184 	case 0x37:	/*  bb1.n  */
1185 	case 0x3a:	/*  bcnd    */
1186 	case 0x3b:	/*  bcnd.n  */
1187 		switch (op26) {
1188 		case 0x34:
1189 		case 0x35: mnem = "bb0"; break;
1190 		case 0x36:
1191 		case 0x37: mnem = "bb1"; break;
1192 		case 0x3a:
1193 		case 0x3b: mnem = "bcnd"; break;
1194 		}
1195 		debug("%s%s\t", mnem, op26 & 1? ".n" : "");
1196 		if (op26 == 0x3a || op26 == 0x3b) {
1197 			/*  Attempt to decode bcnd condition:  */
1198 			switch (d) {
1199 			case 0x1: debug("gt0"); break;
1200 			case 0x2: debug("eq0"); break;
1201 			case 0x3: debug("ge0"); break;
1202 			case 0x7: debug("not_maxneg"); break;
1203 			case 0x8: debug("maxneg"); break;
1204 			case 0xc: debug("lt0"); break;
1205 			case 0xd: debug("ne0"); break;
1206 			case 0xe: debug("le0"); break;
1207 			default:  debug("unimplemented_%i", d);
1208 			}
1209 		} else {
1210 			debug("%i", d);
1211 		}
1212 		debug(",r%i,0x%08" PRIx32, s1, (uint32_t) (dumpaddr + d16));
1213 		symbol = get_symbol_name(&cpu->machine->symbol_context,
1214 		    dumpaddr + d16, &offset);
1215 		if (symbol != NULL && supervisor)
1216 			debug("\t; <%s>", symbol);
1217 		debug("\n");
1218 		break;
1219 
1220 	case 0x3c:
1221 		if ((iw & 0x0000f000)==0x1000 || (iw & 0x0000f000)==0x2000) {
1222 			int scale = 0;
1223 
1224 			/*  Load/store:  */
1225 			debug("%s", (iw & 0x0000f000) == 0x1000? "ld" : "st");
1226 			switch (iw & 0x00000c00) {
1227 			case 0x000: scale = 8; debug(".d"); break;
1228 			case 0x400: scale = 4; break;
1229 			case 0x800: debug(".x"); break;
1230 			default: debug(".UNIMPLEMENTED");
1231 			}
1232 			if (iw & 0x100)
1233 				debug(".usr");
1234 			if (iw & 0x80)
1235 				debug(".wt");
1236 			debug("\tr%i,r%i", d, s1);
1237 			if (iw & 0x200)
1238 				debug("[r%i]", s2);
1239 			else
1240 				debug(",r%i", s2);
1241 
1242 			if (running && scale >= 1) {
1243 				uint32_t tmpaddr = cpu->cd.m88k.r[s1];
1244 				if (iw & 0x200)
1245 					tmpaddr += scale * cpu->cd.m88k.r[s2];
1246 				else
1247 					tmpaddr += cpu->cd.m88k.r[s2];
1248 				symbol = get_symbol_name(&cpu->machine->
1249 				    symbol_context, tmpaddr, &offset);
1250 				if (symbol != NULL && supervisor)
1251 					debug("\t; [<%s>]", symbol);
1252 				else
1253 					debug("\t; [0x%08" PRIx32"]", tmpaddr);
1254 			}
1255 
1256 			debug("\n");
1257 		} else switch (op10) {
1258 		case 0x20:	/*  clr  */
1259 		case 0x22:	/*  set  */
1260 		case 0x24:	/*  ext  */
1261 		case 0x26:	/*  extu  */
1262 		case 0x28:	/*  mak  */
1263 		case 0x2a:	/*  rot  */
1264 			switch (op10) {
1265 			case 0x20: mnem = "clr"; break;
1266 			case 0x22: mnem = "set"; break;
1267 			case 0x24: mnem = "ext"; break;
1268 			case 0x26: mnem = "extu"; break;
1269 			case 0x28: mnem = "mak"; break;
1270 			case 0x2a: mnem = "rot"; break;
1271 			}
1272 			debug("%s\tr%i,r%i,", mnem, d, s1);
1273 			/*  Don't include w5 for the rot instruction:  */
1274 			if (op10 != 0x2a)
1275 				debug("%i", w5);
1276 			/*  Note: o5 = s2:  */
1277 			debug("<%i>\n", s2);
1278 			break;
1279 		case 0x34:	/*  tb0  */
1280 		case 0x36:	/*  tb1  */
1281 			switch (op10) {
1282 			case 0x34: mnem = "tb0"; break;
1283 			case 0x36: mnem = "tb1"; break;
1284 			}
1285 			debug("%s\t%i,r%i,0x%x\n", mnem, d, s1, iw & 0x1ff);
1286 			break;
1287 		default:debug("UNIMPLEMENTED 0x3c, op10=0x%02x\n", op10);
1288 		}
1289 		break;
1290 
1291 	case 0x3d:
1292 		if ((iw & 0xf000) <= 0x3fff) {
1293 			int scale = 0;
1294 
1295 			/*  Load, Store, xmem, and lda:  */
1296 			switch (iw & 0xf000) {
1297 			case 0x2000: debug("st"); break;
1298 			case 0x3000: debug("lda"); break;
1299 			default:     if ((iw & 0xf800) >= 0x0800)
1300 					  debug("ld");
1301 				     else
1302 					  debug("xmem");
1303 			}
1304 			if ((iw & 0xf000) >= 0x1000) {
1305 				/*  ld, st, lda  */
1306 				scale = 1 << (3 - ((iw >> 10) & 3));
1307 				debug("%s", memop[(iw >> 10) & 3]);
1308 			} else if ((iw & 0xf800) == 0x0000) {
1309 				/*  xmem  */
1310 				if (iw & 0x400)
1311 					scale = 4;
1312 				else
1313 					debug(".bu"), scale = 1;
1314 			} else {
1315 				/*  ld  */
1316 				if ((iw & 0xf00) < 0xc00)
1317 					debug(".hu"), scale = 2;
1318 				else
1319 					debug(".bu"), scale = 1;
1320 			}
1321 			if (iw & 0x100)
1322 				debug(".usr");
1323 			if (iw & 0x80)
1324 				debug(".wt");
1325 			debug("\tr%i,r%i", d, s1);
1326 			if (iw & 0x200)
1327 				debug("[r%i]", s2);
1328 			else
1329 				debug(",r%i", s2);
1330 
1331 			if (running && scale >= 1) {
1332 				uint32_t tmpaddr = cpu->cd.m88k.r[s1];
1333 				if (iw & 0x200)
1334 					tmpaddr += scale * cpu->cd.m88k.r[s2];
1335 				else
1336 					tmpaddr += cpu->cd.m88k.r[s2];
1337 				symbol = get_symbol_name(&cpu->machine->
1338 				    symbol_context, tmpaddr, &offset);
1339 				if (symbol != NULL && supervisor)
1340 					debug("\t; [<%s>]", symbol);
1341 				else
1342 					debug("\t; [0x%08" PRIx32"]", tmpaddr);
1343 			}
1344 
1345 			debug("\n");
1346 		} else switch ((iw >> 8) & 0xff) {
1347 		case 0x40:	/*  and  */
1348 		case 0x44:	/*  and.c  */
1349 		case 0x50:	/*  xor  */
1350 		case 0x54:	/*  xor.c  */
1351 		case 0x58:	/*  or  */
1352 		case 0x5c:	/*  or.c  */
1353 		case 0x60:	/*  addu  */
1354 		case 0x61:	/*  addu.co  */
1355 		case 0x62:	/*  addu.ci  */
1356 		case 0x63:	/*  addu.cio  */
1357 		case 0x64:	/*  subu  */
1358 		case 0x65:	/*  subu.co  */
1359 		case 0x66:	/*  subu.ci  */
1360 		case 0x67:	/*  subu.cio  */
1361 		case 0x68:	/*  divu  */
1362 		case 0x69:	/*  divu.d  */
1363 		case 0x6c:	/*  mul  */
1364 		case 0x6d:	/*  mulu.d  */
1365 		case 0x6e:	/*  muls  */
1366 		case 0x70:	/*  add  */
1367 		case 0x71:	/*  add.co  */
1368 		case 0x72:	/*  add.ci  */
1369 		case 0x73:	/*  add.cio  */
1370 		case 0x74:	/*  sub  */
1371 		case 0x75:	/*  sub.co  */
1372 		case 0x76:	/*  sub.ci  */
1373 		case 0x77:	/*  sub.cio  */
1374 		case 0x78:	/*  div  */
1375 		case 0x7c:	/*  cmp  */
1376 		case 0x80:	/*  clr  */
1377 		case 0x88:	/*  set  */
1378 		case 0x90:	/*  ext  */
1379 		case 0x98:	/*  extu  */
1380 		case 0xa0:	/*  mak  */
1381 		case 0xa8:	/*  rot  */
1382 			/*  Three-register opcodes:  */
1383 			switch ((iw >> 8) & 0xff) {
1384 			case 0x40: mnem = "and"; break;
1385 			case 0x44: mnem = "and.c"; break;
1386 			case 0x50: mnem = "xor"; break;
1387 			case 0x54: mnem = "xor.c"; break;
1388 			case 0x58: mnem = "or"; break;
1389 			case 0x5c: mnem = "or.c"; break;
1390 			case 0x60: mnem = "addu"; break;
1391 			case 0x61: mnem = "addu.co"; break;
1392 			case 0x62: mnem = "addu.ci"; break;
1393 			case 0x63: mnem = "addu.cio"; break;
1394 			case 0x64: mnem = "subu"; break;
1395 			case 0x65: mnem = "subu.co"; break;
1396 			case 0x66: mnem = "subu.ci"; break;
1397 			case 0x67: mnem = "subu.cio"; break;
1398 			case 0x68: mnem = "divu"; break;
1399 			case 0x69: mnem = "divu.d"; break;
1400 			case 0x6c: mnem = "mul"; break;
1401 			case 0x6d: mnem = "mulu.d"; break;
1402 			case 0x6e: mnem = "muls"; break;
1403 			case 0x70: mnem = "add"; break;
1404 			case 0x71: mnem = "add.co"; break;
1405 			case 0x72: mnem = "add.ci"; break;
1406 			case 0x73: mnem = "add.cio"; break;
1407 			case 0x74: mnem = "sub"; break;
1408 			case 0x75: mnem = "sub.co"; break;
1409 			case 0x76: mnem = "sub.ci"; break;
1410 			case 0x77: mnem = "sub.cio"; break;
1411 			case 0x78: mnem = "div"; break;
1412 			case 0x7c: mnem = "cmp"; break;
1413 			case 0x80: mnem = "clr"; break;
1414 			case 0x88: mnem = "set"; break;
1415 			case 0x90: mnem = "ext"; break;
1416 			case 0x98: mnem = "extu"; break;
1417 			case 0xa0: mnem = "mak"; break;
1418 			case 0xa8: mnem = "rot"; break;
1419 			}
1420 
1421 			if (((iw >> 8) & 0xff) == 0x58 && d == M88K_ZERO_REG)
1422 				debug("nop");
1423 
1424 			if (((iw >> 8) & 0xff) != 0x58 || d != M88K_ZERO_REG) {
1425 				if (d == M88K_ZERO_REG)
1426 					debug("\t\t; weird nop encoding: ");
1427 				debug("%s\tr%i,r%i,r%i", mnem, d, s1, s2);
1428 			}
1429 
1430 			debug("\n");
1431 			break;
1432 		case 0xc0:	/*  jmp  */
1433 		case 0xc4:	/*  jmp.n  */
1434 		case 0xc8:	/*  jsr  */
1435 		case 0xcc:	/*  jsr.n  */
1436 			debug("%s%s\t(r%i)",
1437 			    op11 & 1? "jsr" : "jmp",
1438 			    iw & 0x400? ".n" : "",
1439 			    s2);
1440 			if (running) {
1441 				uint32_t tmpaddr = cpu->cd.m88k.r[s2];
1442 				symbol = get_symbol_name(&cpu->machine->
1443 				    symbol_context, tmpaddr, &offset);
1444 				debug("\t\t; ");
1445 				if (symbol != NULL && supervisor)
1446 					debug("<%s>", symbol);
1447 				else
1448 					debug("0x%08" PRIx32, tmpaddr);
1449 			}
1450 			debug("\n");
1451 			break;
1452 		case 0xe8:	/*  ff1  */
1453 		case 0xec:	/*  ff0  */
1454 			debug("%s\tr%i,r%i\n",
1455 			    ((iw >> 8) & 0xff) == 0xe8 ? "ff1" : "ff0", d, s2);
1456 			break;
1457 		case 0xf8:	/*  tbnd  */
1458 			debug("tbnd\tr%i,r%i\n", s1, s2);
1459 			break;
1460 		case 0xfc:
1461 			switch (iw & 0xff) {
1462 			case 0x00:
1463 				debug("rte\n");
1464 				break;
1465 			case 0x01:
1466 			case 0x02:
1467 			case 0x03:
1468 				debug("illop%i\n", iw & 0xff);
1469 				break;
1470 			case (M88K_PROM_INSTR & 0xff):
1471 				debug("gxemul_prom_call\n");
1472 				break;
1473 			default:debug("UNIMPLEMENTED 0x3d,0xfc: 0x%02x\n",
1474 				    iw & 0xff);
1475 			}
1476 			break;
1477 		default:debug("UNIMPLEMENTED 0x3d, opbyte = 0x%02x\n",
1478 			    (iw >> 8) & 0xff);
1479 		}
1480 		break;
1481 
1482 	case 0x3e:
1483 		debug("tbnd\tr%i,0x%x\n", s1, imm16);
1484 		break;
1485 
1486 	default:debug("UNIMPLEMENTED op26=0x%02x\n", op26);
1487 	}
1488 
1489 	return sizeof(uint32_t);
1490 }
1491 
1492 
1493 #include "tmp_m88k_tail.cc"
1494 
1495 
1496