xref: /netbsd-src/sys/arch/m68k/m68k/db_disasm.c (revision 5ae0a955493425be9125d9bd3239f6810ff39e12)
1 /*	$NetBSD: db_disasm.c,v 1.47 2023/09/26 14:33:55 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Christian E. Hopps
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Christian E. Hopps.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  * Notes:
34  *
35  * Much can be done with this format, with a lot of hacking even
36  * a moto emul. could be built.  However things like symbol lookup
37  * and reference are needed right away.
38  *
39  * the only functions that use the "get_xxx()" notation should be
40  * ones that modify things in a dis_buffer_t besides the buffers.
41  * (namely the used field)
42  *
43  * An attempt has been made to *always* increment dbuf->used++ immediately
44  * after referencing a value beyond the current "short *" address.
45  * this meant either only referencing the value once or placing it in
46  * a local var.  If you play with this keep this style. Its very useful
47  * in eliminating a very easy to make hard to find logic error.
48  *
49  * I broke style in 2 ways with one macro ``addchar()''
50  * However it makes sense, consider that it is called *a lot* and
51  * commonly with things like ","'s
52  *
53  * *dbuf->casm++ = ','; || ADDCHAR(dbuf,','); || addchar(dbuf,',');
54  * I chose:
55  *	addchar(',');
56  *
57  * If this is not enough to convince you, please load up you emacs or
58  * vi and do a fancy regex-replace, and compare for yourself.
59  * (The 2 rules of style I broke if you failed to notice are:
60  *  1: lower case macro name 2: implicit reference to local var name.)
61  *
62  * (chopps - March 1, 1994)
63  */
64 
65 #include <sys/cdefs.h>
66 __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.47 2023/09/26 14:33:55 tsutsui Exp $");
67 
68 #include <sys/param.h>
69 #ifdef _KERNEL
70 #include <sys/systm.h>
71 #endif
72 
73 #include <machine/db_machdep.h>
74 
75 #include <ddb/db_interface.h>
76 #include <ddb/db_output.h>
77 #include <ddb/db_sym.h>
78 #include <m68k/m68k/db_disasm.h>
79 
80 static void	get_modregstr(dis_buffer_t *, int, int, int, int);
81 static void	get_modregstr_moto(dis_buffer_t *, int, int, int, int);
82 static void	get_modregstr_mit(dis_buffer_t *, int, int, int, int);
83 #if 0
84 static u_long	get_areg_val(int reg);
85 #endif
86 static void	get_immed(dis_buffer_t *, int);
87 static void	get_fpustdGEN(dis_buffer_t *, u_short, const char *);
88 static void	addstr(dis_buffer_t *, const char *s);
89 static void	prints(dis_buffer_t *, int, int);
90 static void	printu(dis_buffer_t *, u_int, int);
91 static void	prints_wb(dis_buffer_t *, int, int, int);
92 static void	printu_wb(dis_buffer_t *, u_int, int, int);
93 static void	prints_bf(dis_buffer_t *, int, int, int);
94 static void	printu_bf(dis_buffer_t *, u_int, int, int);
95 static void	iaddstr(dis_buffer_t *, const char *s);
96 #if 0
97 static void	iprints(dis_buffer_t *, int, int);
98 #endif
99 static void	iprintu(dis_buffer_t *, u_int, int);
100 #if 0
101 static void	iprints_wb(dis_buffer_t *, int, int, int);
102 #endif
103 static void	iprintu_wb(dis_buffer_t *, u_int, int, int);
104 static void	make_cond(dis_buffer_t *, int , const char *);
105 static void	print_fcond(dis_buffer_t *, char);
106 static void	print_mcond(dis_buffer_t *, char);
107 static void	print_disp(dis_buffer_t *, int, int, int);
108 static void	print_addr(dis_buffer_t *, u_long);
109 static void	print_reglist(dis_buffer_t *, int, u_short);
110 static void	print_freglist(dis_buffer_t *, int, u_short, int);
111 static void	print_fcode(dis_buffer_t *, u_short);
112 
113 /* groups */
114 static void	opcode_bitmanip(dis_buffer_t *, u_short);
115 static void	opcode_move(dis_buffer_t *, u_short);
116 static void	opcode_misc(dis_buffer_t *, u_short);
117 static void	opcode_branch(dis_buffer_t *, u_short);
118 static void	opcode_coproc(dis_buffer_t *, u_short);
119 static void	opcode_0101(dis_buffer_t *, u_short);
120 static void	opcode_1000(dis_buffer_t *, u_short);
121 static void	opcode_addsub(dis_buffer_t *, u_short);
122 static void	opcode_1010(dis_buffer_t *, u_short);
123 static void	opcode_1011(dis_buffer_t *, u_short);
124 static void	opcode_1100(dis_buffer_t *, u_short);
125 static void	opcode_1110(dis_buffer_t *, u_short);
126 static void	opcode_fpu(dis_buffer_t *, u_short);
127 static void	opcode_mmu(dis_buffer_t *, u_short);
128 static void	opcode_mmu040(dis_buffer_t *, u_short);
129 static void	opcode_move16(dis_buffer_t *, u_short);
130 
131 /* subs of groups */
132 static void	opcode_movec(dis_buffer_t *, u_short);
133 static void	opcode_divmul(dis_buffer_t *, u_short);
134 static void	opcode_movem(dis_buffer_t *, u_short);
135 static void	opcode_fmove_ext(dis_buffer_t *, u_short, u_short);
136 static void	opcode_pmove(dis_buffer_t *, u_short, u_short);
137 static void	opcode_pflush(dis_buffer_t *, u_short, u_short);
138 
139 #define addchar(ch) (*dbuf->casm++ = ch)
140 #define iaddchar(ch) (*dbuf->cinfo++ = ch)
141 
142 typedef void dis_func_t(dis_buffer_t *, u_short);
143 
144 static dis_func_t *const opcode_map[16] = {
145 	opcode_bitmanip, opcode_move, opcode_move, opcode_move,
146 	opcode_misc, opcode_0101, opcode_branch, opcode_move,
147 	opcode_1000, opcode_addsub, opcode_1010, opcode_1011,
148 	opcode_1100, opcode_addsub, opcode_1110, opcode_coproc
149 };
150 
151 static const char *const cc_table[16] = {
152 	"t", "f", "hi", "ls",
153 	"cc", "cs", "ne", "eq",
154 	"vc", "vs", "pl", "mi",
155 	"ge", "lt", "gt", "le"
156 };
157 
158 static const char *const fpcc_table[32] = {
159 	"f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or",
160 	"un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t",
161 	"sf", "seq", "gt", "ge", "lt", "le", "gl", "gle",
162 	"ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st" };
163 
164 static const char *const mmcc_table[16] = {
165 	"bs", "bc", "ls", "lc", "ss", "sc", "as", "sc",
166 	"ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" };
167 
168 
169 static const char *const aregs[8] = {"a0","a1","a2","a3","a4","a5","a6","sp"};
170 static const char *const dregs[8] = {"d0","d1","d2","d3","d4","d5","d6","d7"};
171 static const char *const fpregs[8] = {
172 	"fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7" };
173 static const char *const fpcregs[3] = { "fpiar", "fpsr", "fpcr" };
174 #ifndef _KERNEL
175 static const char hexdigits[] = "0123456789abcdef";
176 #endif
177 
178 /*
179  * Disassemble instruction at location ``loc''.
180  * Returns location of next instruction.
181  */
182 
183 static char asm_buffer[256];
184 static char info_buffer[256];
185 
186 db_addr_t
db_disasm(db_addr_t loc,bool moto_syntax)187 db_disasm(db_addr_t loc, bool moto_syntax)
188 {
189 	u_short opc;
190 	dis_func_t *func;
191 	dis_buffer_t dbuf;
192 
193 	dbuf.casm = dbuf.dasm = asm_buffer;
194 	dbuf.cinfo = dbuf.info = info_buffer;
195 	dbuf.used = 0;
196 	dbuf.val = (short *)loc;
197 	dbuf.mit = moto_syntax ? 0 : 1;
198 
199 	dbuf.dasm[0] = 0;
200 	dbuf.info[0] = 0;
201 
202 	opc = *dbuf.val;
203 	dbuf.used++;
204 
205 	func = opcode_map[OPCODE_MAP(opc)];
206 	func(&dbuf, opc);
207 
208 	db_printf("%s",asm_buffer);
209 	if (info_buffer[0])
210 		db_printf("\t[%s]\n",info_buffer);
211 	else
212 		db_printf("\n");
213 	return loc + sizeof(short) * dbuf.used;
214 }
215 /*
216  * Bit manipulation/MOVEP/Immediate.
217  */
218 static void
opcode_bitmanip(dis_buffer_t * dbuf,u_short opc)219 opcode_bitmanip(dis_buffer_t *dbuf, u_short opc)
220 {
221 	const char *tmp;
222 	u_short ext;
223 	int sz;
224 
225 	tmp = NULL;
226 
227 	switch (opc) {
228 	case ANDITOCCR_INST:
229 		tmp = "andib\t";
230 		break;
231 	case ANDIROSR_INST:
232 		tmp = "andiw\t";
233 		break;
234 	case EORITOCCR_INST:
235 		tmp = "eorib\t";
236 		break;
237 	case EORITOSR_INST:
238 		tmp = "eoriw\t";
239 		break;
240 	case ORITOCCR_INST:
241 		tmp = "orib\t";
242 		break;
243 	case ORITOSR_INST:
244 		tmp = "oriw\t";
245 		break;
246 	}
247 	if (tmp) {
248 		addstr(dbuf, tmp);
249 		if (ISBITSET(opc,6)) {
250 			get_immed(dbuf, SIZE_WORD);
251 			addstr(dbuf, ",sr");
252 		} else {
253 			get_immed(dbuf, SIZE_BYTE);
254 			addstr(dbuf, ",ccr");
255 		}
256 		return;
257 	}
258 
259 	if (IS_INST(RTM,opc)) {
260 		addstr(dbuf, "rtm\t");
261 		if (ISBITSET(opc,3))
262 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
263 		else
264 			PRINT_DREG(dbuf, BITFIELD(opc,2,0));
265 		return;
266 	}
267 
268 	if (IS_INST(MOVEP,opc)) {
269 		addstr(dbuf, "movp");
270 		if (ISBITSET(opc,6))
271 			addchar('l');
272 		else
273 			addchar('w');
274 		addchar('\t');
275 		if (ISBITSET(opc,7)) {
276 			PRINT_DREG(dbuf, BITFIELD(opc, 11, 9));
277 			addchar(',');
278 		}
279 		PRINT_AREG(dbuf, BITFIELD(opc, 2, 0));
280 		addchar('@');
281 		addchar('(');
282 		print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD,
283 		    BITFIELD(opc, 2, 0));
284 		dbuf->used++;
285 		addchar(')');
286 		if (!ISBITSET(opc,7)) {
287 			addchar(',');
288 			PRINT_DREG(dbuf, BITFIELD(opc, 11, 9));
289 		}
290 		return;
291 	}
292 
293 	switch (opc & BCHGD_MASK) {
294 	case BCHGD_INST:
295 		tmp = "bchg\t";
296 		break;
297 	case BCLRD_INST:
298 		tmp = "bclr\t";
299 		break;
300 	case BSETD_INST:
301 		tmp = "bset\t";
302 		break;
303 	case BTSTD_INST:
304 		tmp = "btst\t";
305 		break;
306 	}
307 	if (tmp) {
308 		addstr(dbuf, tmp);
309 		PRINT_DREG(dbuf, BITFIELD(opc,11,9));
310 		addchar(',');
311 		get_modregstr(dbuf,5,GETMOD_BEFORE,0,0);
312 		return;
313 	}
314 
315 	switch (opc & BCHGS_MASK) {
316 	case BCHGS_INST:
317 		tmp = "bchg\t";
318 		break;
319 	case BCLRS_INST:
320 		tmp = "bclr\t";
321 		break;
322 	case BSETS_INST:
323 		tmp = "bset\t";
324 		break;
325 	case BTSTS_INST:
326 		tmp = "btst\t";
327 		break;
328 	}
329 	if (tmp) {
330 		addstr(dbuf, tmp);
331 		get_immed(dbuf, SIZE_BYTE);
332 		addchar(',');
333 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1);
334 		return;
335 	}
336 
337 	if (IS_INST(CAS2,opc)) {
338 		u_short ext2;
339 
340 		ext = *(dbuf->val + 1);
341 		ext2 = *(dbuf->val + 2);
342 		dbuf->used += 2;
343 
344 		if (ISBITSET(opc,9))
345 			addstr(dbuf, "cas2l\t");
346 		else
347 			addstr(dbuf, "cas2w\t");
348 
349 		PRINT_DREG(dbuf, BITFIELD(ext,2,0));
350 		addchar(':');
351 		PRINT_DREG(dbuf, BITFIELD(ext2,2,0));
352 		addchar(',');
353 
354 		PRINT_DREG(dbuf, BITFIELD(ext,8,6));
355 		addchar(':');
356 		PRINT_DREG(dbuf, BITFIELD(ext2,8,6));
357 		addchar(',');
358 
359 		if (ISBITSET(ext,15))
360 			PRINT_AREG(dbuf, BITFIELD(ext,14,12));
361 		else
362 			PRINT_DREG(dbuf, BITFIELD(ext,14,12));
363 		addchar('@');
364 		addchar(':');
365 		if (ISBITSET(ext2,15))
366 			PRINT_AREG(dbuf, BITFIELD(ext2,14,12));
367 		else
368 			PRINT_DREG(dbuf, BITFIELD(ext2,14,12));
369 		addchar('@');
370 		return;
371 	}
372 
373 	switch (opc & CAS_MASK) {
374 	case CAS_INST:
375 		ext = *(dbuf->val + 1);
376 		dbuf->used++;
377 
378 		addstr(dbuf,"cas");
379 		sz = BITFIELD(opc,10,9);
380 		if (sz == 0) {
381 			sz = SIZE_BYTE;
382 			addchar('b');
383 		} else if (sz == 1) {
384 			sz = SIZE_WORD;
385 			addchar('w');
386 		} else {
387 			sz = SIZE_LONG;
388 			addchar('l');
389 		}
390 		addchar('\t');
391 		PRINT_DREG(dbuf, BITFIELD(ext, 2, 0));
392 		addchar(',');
393 		PRINT_DREG(dbuf, BITFIELD(ext, 8, 6));
394 		addchar(',');
395 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
396 		return;
397 	case CHK2_INST:
398 	/* case CMP2_INST: */
399 		ext = *(dbuf->val + 1);
400 		dbuf->used++;
401 
402 		if (ISBITSET(ext,11))
403 			addstr(dbuf,"chk2");
404 		else
405 			addstr(dbuf,"cmp2");
406 
407 		sz = BITFIELD(opc,10,9);
408 		if (sz == 0) {
409 			sz = SIZE_BYTE;
410 			addchar('b');
411 		} else if (sz == 1) {
412 			sz = SIZE_WORD;
413 			addchar('w');
414 		} else {
415 			sz = SIZE_LONG;
416 			addchar('l');
417 		}
418 		addchar('\t');
419 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
420 
421 		addchar(',');
422 		if(ISBITSET(ext,15))
423 			PRINT_AREG(dbuf, BITFIELD(ext, 14, 12));
424 		else
425 			PRINT_DREG(dbuf, BITFIELD(ext, 14, 12));
426 		return;
427 	}
428 
429 	switch (ADDI_MASK & opc) {
430 	case MOVES_INST:
431 		addstr(dbuf, "movs");
432 		sz = BITFIELD(opc,7,6);
433 		if (sz == 0) {
434 			addchar('b');
435 			sz = SIZE_BYTE;
436 		} else if (sz == 1) {
437 			addchar('w');
438 			sz = SIZE_WORD;
439 		} else {
440 			addchar ('l');
441 			sz = SIZE_LONG;
442 		}
443 		addchar('\t');
444 
445 		ext = *(dbuf->val + 1);
446 		dbuf->used++;
447 
448 		if (ISBITSET(ext,11)) {
449 			if (ISBITSET(ext,15))
450 				PRINT_AREG(dbuf,BITFIELD(ext,14,12));
451 			else
452 				PRINT_DREG(dbuf,BITFIELD(ext,14,12));
453 			addchar(',');
454 			get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
455 		} else {
456 			get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
457 			addchar(',');
458 			if (ISBITSET(ext,15))
459 				PRINT_AREG(dbuf,BITFIELD(ext,14,12));
460 			else
461 				PRINT_DREG(dbuf,BITFIELD(ext,14,12));
462 		}
463 		return;
464 	case ADDI_INST:
465 		tmp = "addi";
466 		break;
467 	case ANDI_INST:
468 		tmp = "andi";
469 		break;
470 	case CMPI_INST:
471 		tmp = "cmpi";
472 		break;
473 	case EORI_INST:
474 		tmp = "eori";
475 		break;
476 	case ORI_INST:
477 		tmp = "ori";
478 		break;
479 	case SUBI_INST:
480 		tmp = "subi";
481 		break;
482 	}
483 	if (tmp) {
484 		addstr(dbuf, tmp);
485 		sz = BITFIELD(opc,7,6);
486 		switch (sz) {
487 		case 0:
488 			addchar('b');
489 			addchar('\t');
490 			sz = SIZE_BYTE;
491 			break;
492 		case 1:
493 			addchar('w');
494 			addchar('\t');
495 			sz = SIZE_WORD;
496 			break;
497 		case 2:
498 			addchar ('l');
499 			addchar('\t');
500 			get_immed(dbuf,SIZE_LONG);
501 			addchar(',');
502 			get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,2);
503 			return;
504 		}
505 		get_immed(dbuf,sz);
506 		addchar(',');
507 		get_modregstr(dbuf,5,GETMOD_BEFORE,sz,1);
508 		return;
509 	}
510 }
511 
512 /*
513  * move byte/word/long and q
514  * 00xx (01==.b 10==.l 11==.w) and 0111(Q)
515  */
516 static void
opcode_move(dis_buffer_t * dbuf,u_short opc)517 opcode_move(dis_buffer_t *dbuf, u_short opc)
518 {
519 	int sz, lused;
520 
521 	sz = 0;
522 	switch (OPCODE_MAP(opc)) {
523 	case 0x1:		/* move.b */
524 		sz = SIZE_BYTE;
525 		break;
526 	case 0x3:		/* move.w */
527 		sz = SIZE_WORD;
528 		break;
529 	case 0x2:		/* move.l */
530 		sz = SIZE_LONG;
531 		break;
532 	case 0x7:		/* moveq */
533 		addstr(dbuf, "movq\t#");
534 		prints_bf(dbuf, opc, 7, 0);
535 		addchar(',');
536 		PRINT_DREG(dbuf,BITFIELD(opc,11,9));
537 		return;
538 	}
539 	addstr(dbuf, "mov");
540 
541 	if (BITFIELD(opc,8,6) == AR_DIR)
542 		addchar('a');
543 
544 	if (sz == SIZE_BYTE)
545 		addchar('b');
546 	else if (sz == SIZE_WORD)
547 		addchar('w');
548 	else
549 		addchar('l');
550 
551 	addchar('\t');
552 	lused = dbuf->used;
553 	get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
554 	addchar(',');
555 	get_modregstr(dbuf, 11, GETMOD_AFTER, sz, dbuf->used - lused);
556 }
557 
558 /*
559  * misc opcodes.
560  */
561 static void
opcode_misc(dis_buffer_t * dbuf,u_short opc)562 opcode_misc(dis_buffer_t *dbuf, u_short opc)
563 {
564 	const char *tmp;
565 	int sz;
566 
567 	tmp = NULL;
568 
569 	/* Check against no option instructions */
570 	switch (opc) {
571 	case BGND_INST:
572 		tmp = "bgnd";
573 		break;
574 	case ILLEGAL_INST:
575 		tmp = "illegal";
576 		break;
577 	case MOVEFRC_INST:
578 	case MOVETOC_INST:
579 		opcode_movec(dbuf, opc);
580 		return;
581 	case NOP_INST:
582 		tmp = "nop";
583 		break;
584 	case RESET_INST:
585 		tmp = "reset";
586 		break;
587 	case RTD_INST:
588 		addstr(dbuf, "rtd\t");
589 		get_immed(dbuf, SIZE_WORD);
590 		return;
591 	case RTE_INST:
592 		tmp = "rte";
593 		break;
594 	case RTR_INST:
595 		tmp = "rtr";
596 		break;
597 	case RTS_INST:
598 		tmp = "rts";
599 		break;
600 	case STOP_INST:
601 		addstr(dbuf, "stop\t");
602 		get_immed(dbuf, SIZE_WORD);
603 		return;
604 	case TRAPV_INST:
605 		tmp = "trapv";
606 		break;
607 	default:
608 		break;
609 	}
610 	if (tmp) {
611 		addstr(dbuf, tmp);
612 		return;
613 	}
614 
615 	switch (opc & BKPT_MASK) {
616 	case BKPT_INST:
617 		addstr(dbuf, "bkpt\t#");
618 		printu_bf(dbuf, opc, 2, 0);
619 		return;
620 	case EXTBW_INST:
621 		addstr(dbuf, "extw\t");
622 		get_modregstr(dbuf,2,DR_DIR,0,0);
623 		return;
624 	case EXTWL_INST:
625 		addstr(dbuf, "extl\t");
626 		get_modregstr(dbuf,2,DR_DIR,0,0);
627 		return;
628 	case EXTBL_INST:
629 		addstr(dbuf, "extbl\t");
630 		get_modregstr(dbuf,2,DR_DIR,0,0);
631 		return;
632 	case LINKW_INST:
633 	case LINKL_INST:
634 		if ((LINKW_MASK & opc) == LINKW_INST) {
635 			addstr(dbuf, "linkw\t");
636 			get_modregstr(dbuf, 2, AR_DIR, 0, 1);
637 		} else {
638 			addstr(dbuf, "linkl\t");
639 			get_modregstr(dbuf, 2, AR_DIR, 0, 2);
640 		}
641 		addchar(',');
642 		if ((LINKW_MASK & opc) == LINKW_INST)
643 			get_immed(dbuf, SIZE_WORD);
644 		else
645 			get_immed(dbuf,SIZE_LONG);
646 		return;
647 	case MOVETOUSP_INST:
648 	case MOVEFRUSP_INST:
649 		addstr(dbuf, "movl\t");
650 		if (!ISBITSET(opc,3)) {
651 			get_modregstr(dbuf, 2, AR_DIR, 0, 0);
652 			addchar(',');
653 		}
654 		addstr(dbuf, "usp");
655 		if (ISBITSET(opc,3)) {
656 			addchar(',');
657 			get_modregstr(dbuf, 2, AR_DIR, 0, 0);
658 		}
659 		return;
660 	case SWAP_INST:
661 		addstr(dbuf, "swap\t");
662 		get_modregstr(dbuf, 2, DR_DIR, 0, 0);
663 		return;
664 	case UNLK_INST:
665 		addstr(dbuf, "unlk\t");
666 		get_modregstr(dbuf, 2, AR_DIR, 0, 0);
667 		return;
668 	}
669 
670 	if ((opc & TRAP_MASK) == TRAP_INST) {
671 		addstr(dbuf, "trap\t#");
672 		printu_bf(dbuf, opc, 3, 0);
673 		return;
674 	}
675 
676 	sz = 0;
677 	switch (DIVSL_MASK & opc) {
678 	case DIVSL_INST:
679 	case MULSL_INST:
680 		opcode_divmul(dbuf, opc);
681 		return;
682 	case JMP_INST:
683 		tmp = "jmp\t";
684 		break;
685 	case JSR_INST:
686 		tmp = "jsr\t";
687 		break;
688 	case MOVEFRCCR_INST:
689 		tmp = "mov\tccr,";
690 		break;
691 	case MOVEFRSR_INST:
692 		tmp = "mov\tsr,";
693 		break;
694 	case NBCD_INST:
695 		tmp = "nbcd\t";
696 		break;
697 	case PEA_INST:
698 		tmp = "pea\t";
699 		break;
700 	case TAS_INST:
701 		tmp = "tas\t";
702 		break;
703 	case MOVETOCCR_INST:
704 	case MOVETOSR_INST:
705 		tmp = "mov\t";
706 		sz = SIZE_WORD;
707 		break;
708 	}
709 	if (tmp) {
710 		addstr(dbuf, tmp);
711 		get_modregstr(dbuf,5, GETMOD_BEFORE, sz, 0);
712 		if(IS_INST(MOVETOSR,opc))
713 			addstr(dbuf, ",sr");
714 		else if(IS_INST(MOVETOCCR,opc))
715 			addstr(dbuf, ",ccr");
716 		return;
717 	}
718 
719 	if ((opc & MOVEM_MASK) == MOVEM_INST) {
720 		opcode_movem(dbuf, opc);
721 		return;
722 	}
723 
724 	switch (opc & CLR_MASK) {
725 	case CLR_INST:
726 		tmp = "clr";
727 		break;
728 	case NEG_INST:
729 		tmp = "neg";
730 		break;
731 	case NEGX_INST:
732 		tmp = "negx";
733 		break;
734 	case NOT_INST:
735 		tmp = "not";
736 		break;
737 	case TST_INST:
738 		tmp = "tst";
739 		break;
740 	}
741 	if (tmp) {
742 		int msz;
743 
744 		addstr(dbuf, tmp);
745 
746 		msz = BITFIELD(opc,7,6);
747 		if (msz == 0) {
748 			tmp = "b\t";
749 			sz = SIZE_BYTE;
750 		} else if (msz == 1) {
751 			tmp = "w\t";
752 			sz = SIZE_WORD;
753 		} else {
754 			tmp = "l\t";
755 			sz = SIZE_LONG;
756 		}
757 		addstr(dbuf, tmp);
758 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
759 		return;
760 	}
761 
762 	if ((opc & LEA_MASK) == LEA_INST) {
763 		addstr(dbuf, "lea\t");
764 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0);
765 		addchar(',');
766 		get_modregstr(dbuf, 11, AR_DIR, 0, 0);
767 		return;
768 	} else if ((opc & CHK_MASK) == CHK_INST) {
769 		if (BITFIELD(opc,8,7) == 0x3) {
770 			addstr(dbuf, "chkw\t");
771 			get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0);
772 		} else {
773 			addstr(dbuf, "chkl\t");
774 			get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0);
775 		}
776 		addchar(',');
777 		get_modregstr(dbuf, 11, DR_DIR, 0, 0);
778 		return;
779 	}
780 }
781 
782 /*
783  * ADDQ/SUBQ/Scc/DBcc/TRAPcc
784  */
785 static void
opcode_0101(dis_buffer_t * dbuf,u_short opc)786 opcode_0101(dis_buffer_t *dbuf, u_short opc)
787 {
788 	int data;
789 
790 	if (IS_INST(TRAPcc, opc) && BITFIELD(opc,2,0) > 1) {
791 		int opmode;
792 
793 		opmode = BITFIELD(opc,2,0);
794 		make_cond(dbuf,11,"trap");
795 
796 		if (opmode == 0x2) {
797 			addchar('w');
798 			addchar('\t');
799 			get_immed(dbuf, SIZE_WORD);
800 		} else if (opmode == 0x3) {
801 			addchar('l');
802 			addchar('\t');
803 			get_immed(dbuf, SIZE_LONG);
804 		}
805 		return;
806 	} else if (IS_INST(DBcc, opc)) {
807 		make_cond(dbuf,11,"db");
808 		addchar('\t');
809 		PRINT_DREG(dbuf, BITFIELD(opc,2,0));
810 		addchar(',');
811 		print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD, -1);
812 		dbuf->used++;
813 		return;
814 	} else if (IS_INST(Scc,opc)) {
815 		make_cond(dbuf,11,"s");
816 		addchar('\t');
817 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 0);
818 		return;
819 	} else if (IS_INST(ADDQ, opc) || IS_INST(SUBQ, opc)) {
820 		int size = BITFIELD(opc,7,6);
821 
822 		if (IS_INST(SUBQ, opc))
823 			addstr(dbuf, "subq");
824 		else
825 			addstr(dbuf, "addq");
826 
827 		if (size == 0x1)
828 			addchar('w');
829 		else if (size == 0x2)
830 			addchar('l');
831 		else
832 			addchar('b');
833 
834 		addchar('\t');
835 		addchar('#');
836 		data = BITFIELD(opc,11,9);
837 		if (data == 0)
838 			data = 8;
839 		printu(dbuf, data, SIZE_BYTE);
840 		addchar(',');
841 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0);
842 
843 		return;
844 	}
845 }
846 
847 /*
848  * Bcc/BSR/BRA
849  */
850 static void
opcode_branch(dis_buffer_t * dbuf,u_short opc)851 opcode_branch(dis_buffer_t *dbuf, u_short opc)
852 {
853 	int disp;
854 
855 	if (IS_INST(BRA,opc))
856 		addstr(dbuf, "bra");
857 	else if (IS_INST(BSR,opc))
858 		addstr(dbuf, "bsr");
859 	else
860 		make_cond(dbuf,11,"b");
861 
862 	disp = BITFIELD(opc,7,0);
863 	if (disp == 0) {
864 		/* 16-bit signed displacement */
865 		disp = *(dbuf->val + 1);
866 		dbuf->used++;
867 		addchar('w');
868 	} else if (disp == 0xff) {
869 		/* 32-bit signed displacement */
870 		disp = *(long *)(dbuf->val + 1);
871 		dbuf->used += 2;
872 		addchar('l');
873 	} else {
874 		/* 8-bit signed displacement in opcode. */
875 		/* Needs to be sign-extended... */
876 		if (ISBITSET(disp,7))
877 			disp -= 256;
878 		addchar('b');
879 	}
880 	addchar('\t');
881 	print_addr(dbuf, disp + (u_long)dbuf->val + 2);
882 }
883 
884 /*
885  * ADD/ADDA/ADDX/SUB/SUBA/SUBX
886  */
887 static void
opcode_addsub(dis_buffer_t * dbuf,u_short opc)888 opcode_addsub(dis_buffer_t *dbuf, u_short opc)
889 {
890 	int sz, ch, amode;
891 
892 	sz = BITFIELD(opc,7,6);
893 	amode = 0;
894 
895 	if (sz == 0) {
896 		ch = 'b';
897 		sz = SIZE_BYTE;
898 	} else if (sz == 1) {
899 		ch = 'w';
900 		sz = SIZE_WORD;
901 	} else if (sz == 2) {
902 		ch = 'l';
903 		sz = SIZE_LONG;
904 	} else {
905 		amode = 1;
906 		if (!ISBITSET(opc,8))  {
907 			sz = SIZE_WORD;
908 			ch = 'w';
909 		} else {
910 			sz = SIZE_LONG;
911 			ch = 'l';
912 		}
913 	}
914 
915 	if (!amode && (IS_INST(ADDX,opc) || IS_INST(SUBX,opc))) {
916 		if (IS_INST(ADDX,opc))
917 			addstr(dbuf,"addx");
918 		else
919 			addstr(dbuf,"subx");
920 
921 		addchar(ch);
922 		addchar('\t');
923 
924 		if (ISBITSET(opc,3)) {
925 			PRINT_AREG(dbuf,BITFIELD(opc,2,0));
926 			addchar('@');
927 			addchar('-');
928 			addchar(',');
929 			PRINT_AREG(dbuf,BITFIELD(opc,11,9));
930 			addchar('@');
931 			addchar('-');
932 		} else {
933 			PRINT_DREG(dbuf,BITFIELD(opc,2,0));
934 			addchar(',');
935 			PRINT_DREG(dbuf,BITFIELD(opc,11,9));
936 		}
937 	} else {
938 		if (IS_INST(ADD,opc))
939 			addstr(dbuf, "add");
940 		else
941 			addstr(dbuf, "sub");
942 
943 		if (amode)
944 			addchar('a');
945 		addchar(ch);
946 		addchar('\t');
947 
948 		if (ISBITSET(opc,8) && amode == 0) {
949 			PRINT_DREG(dbuf,BITFIELD(opc,11,9));
950 			addchar(',');
951 			get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
952 		} else {
953 			get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
954 			addchar(',');
955 			if (amode)
956 				PRINT_AREG(dbuf,BITFIELD(opc,11,9));
957 			else
958 				PRINT_DREG(dbuf,BITFIELD(opc,11,9));
959 		}
960 	}
961 	return;
962 }
963 
964 /*
965  * Shift/Rotate/Bit Field
966  */
967 static void
opcode_1110(dis_buffer_t * dbuf,u_short opc)968 opcode_1110(dis_buffer_t *dbuf, u_short opc)
969 {
970 	const char *tmp;
971 	u_short ext;
972 	int type, sz;
973 
974 	tmp = NULL;
975 
976 	switch (opc & BFCHG_MASK) {
977 	case BFCHG_INST:
978 		tmp = "bfchg";
979 		break;
980 	case BFCLR_INST:
981 		tmp = "bfclr";
982 		break;
983 	case BFEXTS_INST:
984 		tmp = "bfexts";
985 		break;
986 	case BFEXTU_INST:
987 		tmp = "bfextu";
988 		break;
989 	case BFFFO_INST:
990 		tmp = "bfffo";
991 		break;
992 	case BFINS_INST:
993 		tmp = "bfins";
994 		break;
995 	case BFSET_INST:
996 		tmp = "bfset";
997 		break;
998 	case BFTST_INST:
999 		tmp = "bftst";
1000 		break;
1001 	}
1002 	if (tmp) {
1003 		short bf;
1004 
1005 		addstr(dbuf, tmp);
1006 		addchar('\t');
1007 
1008 		ext = *(dbuf->val + 1);
1009 		dbuf->used++;
1010 
1011 		if (IS_INST(BFINS,opc)) {
1012 			PRINT_DREG(dbuf, BITFIELD(ext,14,12));
1013 			addchar(',');
1014 		}
1015 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1);
1016 		addchar('{');
1017 
1018 		bf = BITFIELD(ext,10,6);
1019 		if (ISBITSET(ext, 11))
1020 			PRINT_DREG(dbuf, bf);
1021 		else
1022 			printu_wb(dbuf, bf, SIZE_BYTE, 10);
1023 
1024 		addchar(':');
1025 
1026 		bf = BITFIELD(ext, 4, 0);
1027 		if (ISBITSET(ext, 5))
1028 			PRINT_DREG(dbuf, bf);
1029 		else {
1030 			if (bf == 0)
1031 				bf = 32;
1032 			printu_wb(dbuf, bf, SIZE_BYTE, 10);
1033 		}
1034 		addchar('}');
1035 		if (ISBITSET(opc,8) && !IS_INST(BFINS,opc)) {
1036 			addchar(',');
1037 			PRINT_DREG(dbuf, BITFIELD(ext,14,12));
1038 		} else
1039 			*dbuf->casm = 0;
1040 		return;
1041 	}
1042 	sz = BITFIELD(opc,7,6);
1043 	if (sz == 0x3)
1044 		type = BITFIELD(opc, 10, 9);
1045 	else
1046 		type = BITFIELD(opc, 4, 3);
1047 
1048 	switch (type) {
1049 	case AS_TYPE:
1050 		addchar('a');
1051 		addchar('s');
1052 		break;
1053 	case LS_TYPE:
1054 		addchar('l');
1055 		addchar('s');
1056 		break;
1057 	case RO_TYPE:
1058 		addchar('r');
1059 		addchar('o');
1060 		break;
1061 	case ROX_TYPE:
1062 		addchar('r');
1063 		addchar('o');
1064 		addchar('x');
1065 		break;
1066 	}
1067 
1068 	if (ISBITSET(opc,8))
1069 		addchar('l');
1070 	else
1071 		addchar('r');
1072 
1073 	switch (sz) {
1074 	case 0:
1075 		sz = SIZE_BYTE;
1076 		addchar('b');
1077 		break;
1078 	case 3:
1079 	case 1:
1080 		sz = SIZE_WORD;
1081 		addchar('w');
1082 		break;
1083 	case 2:
1084 		sz = SIZE_LONG;
1085 		addchar('l');
1086 		break;
1087 
1088 	}
1089 	addchar('\t');
1090 	if(BITFIELD(opc,7,6) == 0x3) {
1091 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
1092 		return;
1093 	} else if (ISBITSET(opc,5))
1094 		PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1095 	else {
1096 		addchar('#');
1097 		sz = BITFIELD(opc,11,9);
1098 		if (sz == 0)
1099 			sz = 8;
1100 		printu_wb(dbuf, sz, SIZE_BYTE, 10);
1101 	}
1102 	addchar(',');
1103 	PRINT_DREG(dbuf, BITFIELD(opc,2,0));
1104 	return;
1105 }
1106 
1107 /*
1108  * CMP/CMPA/EOR
1109  */
1110 static void
opcode_1011(dis_buffer_t * dbuf,u_short opc)1111 opcode_1011(dis_buffer_t *dbuf, u_short opc)
1112 {
1113 	int sz;
1114 
1115 	if (IS_INST(CMPA,opc)) {
1116 		addstr(dbuf, "cmpa");
1117 
1118 		if (ISBITSET(opc, 8)) {
1119 			addchar('l');
1120 			sz = SIZE_LONG;
1121 		} else {
1122 			addchar('w');
1123 			sz = SIZE_WORD;
1124 		}
1125 		addchar('\t');
1126 	} else {
1127 		if (IS_INST(CMP, opc))
1128 			addstr(dbuf, "cmp");
1129 		else
1130 			addstr(dbuf, "eor");
1131 
1132 		sz = BITFIELD(opc,7,6);
1133 		switch (sz) {
1134 		case 0:
1135 			addchar('b');
1136 			sz = SIZE_BYTE;
1137 			break;
1138 		case 1:
1139 			addchar('w');
1140 			sz = SIZE_WORD;
1141 			break;
1142 		case 2:
1143 			addchar('l');
1144 			sz = SIZE_LONG;
1145 			break;
1146 		}
1147 		addchar('\t');
1148 		if (IS_INST(EOR,opc)) {
1149 			PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1150 			addchar(',');
1151 		}
1152 	}
1153 	get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
1154 
1155 	if (IS_INST(CMPA,opc)) {
1156 		addchar(',');
1157 		PRINT_AREG(dbuf, BITFIELD(opc,11,9));
1158 	} else if (IS_INST(CMP,opc)) {
1159 		addchar(',');
1160 		PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1161 	}
1162 	return;
1163 }
1164 
1165 /*
1166  * OR/DIV/SBCD
1167  */
1168 static void
opcode_1000(dis_buffer_t * dbuf,u_short opc)1169 opcode_1000(dis_buffer_t *dbuf, u_short opc)
1170 {
1171 	int sz;
1172 
1173 	if (IS_INST(UNPKA,opc)) {
1174 		addstr(dbuf, "unpk\t");
1175 		PRINT_AREG(dbuf,BITFIELD(opc,2,0));
1176 		addstr(dbuf, "@-,");
1177 		PRINT_AREG(dbuf,BITFIELD(opc,11,9));
1178 		addstr(dbuf, "@-,");
1179 		get_immed(dbuf,SIZE_WORD);
1180 	} else if (IS_INST(UNPKD,opc)) {
1181 		addstr(dbuf, "unpk\t");
1182 		PRINT_DREG(dbuf,BITFIELD(opc,2,0));
1183 		addchar(',');
1184 		PRINT_DREG(dbuf,BITFIELD(opc,11,9));
1185 		addchar(',');
1186 		get_immed(dbuf,SIZE_WORD);
1187 	} else if (IS_INST(SBCDA,opc)) {
1188 		addstr(dbuf, "sbcd\t");
1189 		PRINT_AREG(dbuf,BITFIELD(opc,2,0));
1190 		addstr(dbuf, "@-,");
1191 		PRINT_AREG(dbuf,BITFIELD(opc,11,9));
1192 		addstr(dbuf, "@-");
1193 	} else if (IS_INST(SBCDD,opc)) {
1194 		addstr(dbuf, "sbcd\t");
1195 		PRINT_DREG(dbuf,BITFIELD(opc,2,0));
1196 		addchar(',');
1197 		PRINT_DREG(dbuf,BITFIELD(opc,11,9));
1198 	} else if (IS_INST(DIVSW,opc) || IS_INST(DIVUW,opc)) {
1199 		if (IS_INST(DIVSW,opc))
1200 			addstr(dbuf, "divsw\t");
1201 		else
1202 			addstr(dbuf, "divuw\t");
1203 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0);
1204 		addchar(',');
1205 		PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1206 	} else {
1207 		addstr(dbuf, "or");
1208 
1209 		sz = BITFIELD(opc,7,6);
1210 		switch (sz) {
1211 		case 0:
1212 			addchar('b');
1213 			sz = SIZE_BYTE;
1214 			break;
1215 		case 1:
1216 			addchar('w');
1217 			sz = SIZE_WORD;
1218 			break;
1219 		case 2:
1220 			addchar('l');
1221 			sz = SIZE_LONG;
1222 			break;
1223 		}
1224 		addchar('\t');
1225 		if (ISBITSET(opc,8)) {
1226 			PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1227 			addchar(',');
1228 		}
1229 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
1230 		if (!ISBITSET(opc,8)) {
1231 			addchar(',');
1232 			PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1233 		}
1234 	}
1235 }
1236 
1237 /*
1238  * AND/MUL/ABCD/EXG (1100)
1239  */
1240 static void
opcode_1100(dis_buffer_t * dbuf,u_short opc)1241 opcode_1100(dis_buffer_t *dbuf, u_short opc)
1242 {
1243 	int sz;
1244 
1245 	if (IS_INST(ABCDA,opc)) {
1246 		addstr(dbuf, "abcd\t");
1247 		PRINT_AREG(dbuf,BITFIELD(opc,2,0));
1248 		addstr(dbuf, "@-,");
1249 		PRINT_AREG(dbuf,BITFIELD(opc,11,9));
1250 		addstr(dbuf, "@-");
1251 	} else if (IS_INST(ABCDD,opc)) {
1252 		addstr(dbuf, "abcd\t");
1253 		PRINT_DREG(dbuf,BITFIELD(opc,2,0));
1254 		addchar(',');
1255 		PRINT_DREG(dbuf,BITFIELD(opc,11,9));
1256 	} else if (IS_INST(MULSW,opc) || IS_INST(MULUW,opc)) {
1257 		if (IS_INST(MULSW,opc))
1258 			addstr(dbuf, "mulsw\t");
1259 		else
1260 			addstr(dbuf, "muluw\t");
1261 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0);
1262 		addchar(',');
1263 		PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1264 	} else if (IS_INST(EXG,opc)) {
1265 		addstr(dbuf, "exg\t");
1266 		if (ISBITSET(opc,7)) {
1267 			PRINT_DREG(dbuf,BITFIELD(opc,11,9));
1268 			addchar(',');
1269 			PRINT_AREG(dbuf,BITFIELD(opc,2,0));
1270 		} else if (ISBITSET(opc,3)) {
1271 			PRINT_AREG(dbuf,BITFIELD(opc,11,9));
1272 			addchar(',');
1273 			PRINT_AREG(dbuf,BITFIELD(opc,2,0));
1274 		} else {
1275 			PRINT_DREG(dbuf,BITFIELD(opc,11,9));
1276 			addchar(',');
1277 			PRINT_DREG(dbuf,BITFIELD(opc,2,0));
1278 		}
1279 	} else {
1280 		addstr(dbuf, "and");
1281 
1282 		sz = BITFIELD(opc,7,6);
1283 		switch (sz) {
1284 		case 0:
1285 			addchar('b');
1286 			sz = SIZE_BYTE;
1287 			break;
1288 		case 1:
1289 			addchar('w');
1290 			sz = SIZE_WORD;
1291 			break;
1292 		case 2:
1293 			addchar('l');
1294 			sz = SIZE_LONG;
1295 			break;
1296 		}
1297 		addchar('\t');
1298 
1299 		if (ISBITSET(opc,8)) {
1300 			PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1301 			addchar(',');
1302 		}
1303 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0);
1304 		if (!ISBITSET(opc,8)) {
1305 			addchar(',');
1306 			PRINT_DREG(dbuf, BITFIELD(opc,11,9));
1307 		}
1308 	}
1309 }
1310 
1311 /*
1312  * Coprocessor instruction
1313  */
1314 static void
opcode_coproc(dis_buffer_t * dbuf,u_short opc)1315 opcode_coproc(dis_buffer_t *dbuf, u_short opc)
1316 {
1317 	switch (BITFIELD(*dbuf->val,11,9)) {
1318 	case 1:
1319 		opcode_fpu(dbuf, opc);
1320 		return;
1321 	case 0:
1322 		opcode_mmu(dbuf, opc);
1323 		return;
1324 	case 2:
1325 		opcode_mmu040(dbuf, opc);
1326 		return;
1327 	case 3:
1328 		opcode_move16(dbuf, opc);
1329 		return;
1330 	}
1331 	switch (BITFIELD(opc,8,6)) {
1332 	case 0:
1333 		dbuf->used++;
1334 		break;
1335 	case 3:
1336 		dbuf->used++;
1337 		/*FALLTHROUGH*/
1338 	case 2:
1339 		dbuf->used++;
1340 		break;
1341 	case 1:
1342 		dbuf->used++;
1343 	case 4:
1344 	case 5:
1345 	default:
1346 		/* Nothing */ ;
1347 	}
1348 	addstr(dbuf, "UNKNOWN COPROC OPCODE");
1349 	return;
1350 }
1351 
1352 /*
1353  * Resvd
1354  */
1355 static void
opcode_1010(dis_buffer_t * dbuf,u_short opc)1356 opcode_1010(dis_buffer_t *dbuf, u_short opc)
1357 {
1358 	addstr(dbuf, "RSVD");
1359 	dbuf->used++;
1360 }
1361 
1362 static void
opcode_fpu(dis_buffer_t * dbuf,u_short opc)1363 opcode_fpu(dis_buffer_t *dbuf, u_short opc)
1364 {
1365 	u_short ext;
1366 	int type, opmode;
1367 
1368 	type = BITFIELD(opc,8,6);
1369 	switch (type) {
1370 	/* cpGEN */
1371 	case 0:
1372 		ext = *(dbuf->val + 1);
1373 		dbuf->used++;
1374 		opmode = BITFIELD(ext,5,0);
1375 
1376 		if (BITFIELD(opc,5,0) == 0 && BITFIELD(ext,15,10) == 0x17) {
1377 			addstr(dbuf,"fmovcrx #");
1378 			printu(dbuf,BITFIELD(ext,6,0),SIZE_BYTE);
1379 			return;
1380 		}
1381 		if (ISBITSET(ext,15) || ISBITSET(ext,13)) {
1382 			opcode_fmove_ext(dbuf, opc, ext);
1383 			return;
1384 		}
1385 
1386 		switch(opmode) {
1387 		case FMOVE:
1388 			get_fpustdGEN(dbuf,ext,"fmov");
1389 			return;
1390 		case FABS:
1391 			get_fpustdGEN(dbuf,ext,"fabs");
1392 			return;
1393 		case FACOS:
1394 			get_fpustdGEN(dbuf,ext,"facos");
1395 			return;
1396 		case FADD:
1397 			get_fpustdGEN(dbuf,ext,"fadd");
1398 			return;
1399 		case FASIN:
1400 			get_fpustdGEN(dbuf,ext,"fasin");
1401 			return;
1402 		case FATAN:
1403 			get_fpustdGEN(dbuf,ext,"fatan");
1404 			return;
1405 		case FATANH:
1406 			get_fpustdGEN(dbuf,ext,"fatanh");
1407 			return;
1408 		case FCMP:
1409 			get_fpustdGEN(dbuf,ext,"fcmp");
1410 			return;
1411 		case FCOS:
1412 			get_fpustdGEN(dbuf,ext,"fcos");
1413 			return;
1414 		case FCOSH:
1415 			get_fpustdGEN(dbuf,ext,"fcosh");
1416 			return;
1417 		case FDIV:
1418 			get_fpustdGEN(dbuf,ext,"fdiv");
1419 			return;
1420 		case FETOX:
1421 			get_fpustdGEN(dbuf,ext,"fetox");
1422 			return;
1423 		case FGETEXP:
1424 			get_fpustdGEN(dbuf,ext,"fgetexp");
1425 			return;
1426 		case FGETMAN:
1427 			get_fpustdGEN(dbuf,ext,"fgetman");
1428 			return;
1429 		case FINT:
1430 			get_fpustdGEN(dbuf,ext,"fint");
1431 			return;
1432 		case FINTRZ:
1433 			get_fpustdGEN(dbuf,ext,"fintrz");
1434 			return;
1435 		case FLOG10:
1436 			get_fpustdGEN(dbuf,ext,"flog10");
1437 			return;
1438 		case FLOG2:
1439 			get_fpustdGEN(dbuf,ext,"flog2");
1440 			return;
1441 		case FLOGN:
1442 			get_fpustdGEN(dbuf,ext,"flogn");
1443 			return;
1444 		case FLOGNP1:
1445 			get_fpustdGEN(dbuf,ext,"flognp1");
1446 			return;
1447 		case FMOD:
1448 			get_fpustdGEN(dbuf,ext,"fmod");
1449 			return;
1450 		case FMUL:
1451 			get_fpustdGEN(dbuf,ext,"fmul");
1452 			return;
1453 		case FNEG:
1454 			get_fpustdGEN(dbuf,ext,"fneg");
1455 			return;
1456 		case FREM:
1457 			get_fpustdGEN(dbuf,ext,"frem");
1458 			return;
1459 		case FSCALE:
1460 			get_fpustdGEN(dbuf,ext,"fscale");
1461 			return;
1462 		case FSGLDIV:
1463 			get_fpustdGEN(dbuf,ext,"fsgldiv");
1464 			return;
1465 		case FSGLMUL:
1466 			get_fpustdGEN(dbuf,ext,"fsglmul");
1467 			return;
1468 		case FSIN:
1469 			get_fpustdGEN(dbuf,ext,"fsin");
1470 			return;
1471 		case FSINH:
1472 			get_fpustdGEN(dbuf,ext,"fsinh");
1473 			return;
1474 		case FSQRT:
1475 			get_fpustdGEN(dbuf,ext,"fsqrt");
1476 			return;
1477 		case FSUB:
1478 			get_fpustdGEN(dbuf,ext,"fsub");
1479 			return;
1480 		case FTAN:
1481 			get_fpustdGEN(dbuf,ext,"ftan");
1482 			return;
1483 		case FTANH:
1484 			get_fpustdGEN(dbuf,ext,"ftanh");
1485 			return;
1486 		case FTENTOX:
1487 			get_fpustdGEN(dbuf,ext,"ftentox");
1488 			return;
1489 		case FTST:
1490 			get_fpustdGEN(dbuf,ext,"ftst");
1491 			return;
1492 		case FTWOTOX:
1493 			get_fpustdGEN(dbuf,ext,"ftwotox");
1494 			return;
1495 
1496 		}
1497 		/* FALLTHROUGH */
1498 	/* cpBcc */
1499 	case 2:
1500 		if (BITFIELD(opc,5,0) == 0 && *(dbuf->val + 1) == 0) {
1501 			dbuf->used++;
1502 			addstr (dbuf, "fnop");
1503 			return;
1504 		}
1505 		/* FALLTHROUGH */
1506 	case 3:
1507 		addstr(dbuf, "fb");
1508 		print_fcond(dbuf, BITFIELD(opc,5,0));
1509 		if (type == 2) {
1510 			addchar('w');
1511 			addchar('\t');
1512 			print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1);
1513 			dbuf->used++;
1514 		} else {
1515 			addchar('l');
1516 			addchar('\t');
1517 			print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG,
1518 				 -1);
1519 			dbuf->used += 2;
1520 		}
1521 		return;
1522 	/* cpDBcc/cpScc/cpTrap */
1523 	case 1:
1524 		ext = *(dbuf->val + 1);
1525 		dbuf->used++;
1526 
1527 		if (BITFIELD(opc,5,3) == 0x1) {
1528 			/* fdbcc */
1529 			addstr(dbuf,"fdb");
1530 			print_fcond(dbuf,BITFIELD(ext,5,0));
1531 			addchar('\t');
1532 			PRINT_DREG(dbuf, BITFIELD(opc,2,0));
1533 			addchar(',');
1534 			print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1);
1535 			dbuf->used++;
1536 		} else if (BITFIELD(opc,5,3) == 0x7 &&
1537 		    BITFIELD(opc,2,0) > 1) {
1538 			addstr(dbuf,"ftrap");
1539 			print_fcond(dbuf,BITFIELD(ext,5,0));
1540 
1541 			if (BITFIELD(opc,2,0) == 0x2) {
1542 				addchar('w');
1543 				addchar('\t');
1544 				dbuf->val++;
1545 				get_immed(dbuf, SIZE_WORD);
1546 				dbuf->val--;
1547 			} else if (BITFIELD(opc,2,0) == 0x3) {
1548 				addchar('l');
1549 				addchar('\t');
1550 				dbuf->val++;
1551 				get_immed(dbuf, SIZE_LONG);
1552 				dbuf->val--;
1553 			}
1554 		} else {
1555 			addstr(dbuf,"fs");
1556 			print_fcond(dbuf,BITFIELD(ext,5,0));
1557 			addchar('\t');
1558 			get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1);
1559 		}
1560 		return;
1561 	case 4:
1562 		addstr(dbuf,"fsave\t");
1563 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0);
1564 		return;
1565 	case 5:
1566 		addstr(dbuf,"frestor\t");
1567 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0);
1568 		return;
1569 	}
1570 }
1571 
1572 /*
1573  * XXX - This screws up on:  fmovem  a0@(312),fpcr/fpsr/fpi
1574  */
1575 static void
opcode_fmove_ext(dis_buffer_t * dbuf,u_short opc,u_short ext)1576 opcode_fmove_ext(dis_buffer_t *dbuf, u_short opc, u_short ext)
1577 {
1578 	int sz;
1579 
1580 	sz = 0;
1581 	if (BITFIELD(ext,15,13) == 3) {
1582 		/* fmove r ==> m */
1583 		addstr(dbuf, "fmov");
1584 		switch (BITFIELD(ext,12,10)) {
1585 		case 0:
1586 			addchar('l');
1587 			sz = SIZE_LONG;
1588 			break;
1589 		case 1:
1590 			addchar('s');
1591 			sz = SIZE_SINGLE;
1592 			break;
1593 		case 2:
1594 			addchar('x');
1595 			sz = SIZE_EXTENDED;
1596 			break;
1597 		case 7:
1598 		case 3:
1599 			addchar('p');
1600 			sz = SIZE_PACKED;
1601 			break;
1602 		case 4:
1603 			addchar('w');
1604 			sz = SIZE_WORD;
1605 			break;
1606 		case 5:
1607 			addchar('d');
1608 			sz = SIZE_DOUBLE;
1609 			break;
1610 		case 6:
1611 			addchar('b');
1612 			sz = SIZE_BYTE;
1613 			break;
1614 		}
1615 		addchar('\t');
1616 		PRINT_FPREG(dbuf, BITFIELD(ext,9,7));
1617 		addchar(',');
1618 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
1619 		if (sz == SIZE_PACKED) {
1620 			addchar('{');
1621 			if (ISBITSET(ext,12)) {
1622 				PRINT_DREG(dbuf,BITFIELD(ext,6,4));
1623 			} else {
1624 				addchar('#');
1625 				prints_bf(dbuf, ext, 6, 4);
1626 			}
1627 			addchar('}');
1628 		}
1629 		return;
1630 	}
1631 	addstr(dbuf,"fmovm");
1632 
1633 	if (!ISBITSET(ext,14)) {
1634 		/* fmove[m] control reg */
1635 		addchar('l');
1636 		addchar('\t');
1637 
1638 		if (ISBITSET(ext,13)) {
1639 			print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1);
1640 			addchar(',');
1641 		}
1642 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1);
1643 		if (!ISBITSET(ext,13)) {
1644 			addchar(',');
1645 			print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1);
1646 		}
1647 		return;
1648 	}
1649 	addchar('x');
1650 	addchar('\t');
1651 
1652 	if (ISBITSET(ext,11)) {
1653 		if (ISBITSET(ext,13)) {
1654 			PRINT_DREG(dbuf,BITFIELD(ext,6,4));
1655 			addchar(',');
1656 		}
1657 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1);
1658 		if (!ISBITSET(ext,13)) {
1659 			addchar(',');
1660 			PRINT_DREG(dbuf,BITFIELD(ext,6,4));
1661 		}
1662 	} else {
1663 		if (ISBITSET(ext,13)) {
1664 			print_freglist(dbuf, BITFIELD(opc,5,3),
1665 			    BITFIELD(ext,7,0), 0);
1666 			addchar(',');
1667 		}
1668 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1);
1669 		if (!ISBITSET(ext,13)) {
1670 			addchar(',');
1671 			print_freglist(dbuf, BITFIELD(opc,5,3),
1672 			    BITFIELD(ext,7,0), 0);
1673 		}
1674 	}
1675 }
1676 
1677 static void
opcode_mmu(dis_buffer_t * dbuf,u_short opc)1678 opcode_mmu(dis_buffer_t *dbuf, u_short opc)
1679 {
1680 	u_short ext;
1681 	int type;
1682 
1683 	type = BITFIELD(opc,8,6);
1684 	switch (type) {
1685 	/* cpGEN? */
1686 	case 0:
1687 		ext = *(dbuf->val + 1);
1688 		dbuf->used++;
1689 
1690 		switch(BITFIELD(ext,15,13)) {
1691 		case 5:
1692 		case 1:
1693 			opcode_pflush(dbuf, opc, ext);
1694 			return;
1695 		case 0:
1696 		case 3:
1697 		case 2:
1698 			opcode_pmove(dbuf, opc, ext);
1699 			return;
1700 		case 4:
1701 			addstr(dbuf, "ptest");
1702 			if (ISBITSET(ext,9))
1703 				addchar('r');
1704 			else
1705 				addchar('w');
1706 			addchar('\t');
1707 			print_fcode(dbuf, BITFIELD(ext, 5, 0));
1708 			addchar(',');
1709 			get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1);
1710 			addchar(',');
1711 			addchar('#');
1712 			printu_bf(dbuf, ext, 12, 10);
1713 			if (ISBITSET(ext, 8)) {
1714 				addchar(',');
1715 				PRINT_AREG(dbuf, BITFIELD(ext, 7, 5));
1716 			}
1717 		}
1718 		return;
1719 	case 2:
1720 	case 3:
1721 		addstr(dbuf, "pb");
1722 		print_mcond(dbuf, BITFIELD(opc,5,0));
1723 		if (type == 2) {
1724 			addchar('w');
1725 			addchar('\t');
1726 			print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1);
1727 			dbuf->used++;
1728 		} else {
1729 			addchar('l');
1730 			addchar('\t');
1731 			print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG,
1732 				 -1);
1733 			dbuf->used += 2;
1734 		}
1735 		return;
1736 	case 1:
1737 		ext = *(dbuf->val + 1);
1738 		dbuf->used++;
1739 
1740 		if (BITFIELD(opc,5,3) == 0x1) {
1741 			/* fdbcc */
1742 			addstr(dbuf,"pdb");
1743 			print_fcond(dbuf,BITFIELD(ext,5,0));
1744 			addchar('\t');
1745 			PRINT_DREG(dbuf, BITFIELD(opc,2,0));
1746 			addchar(',');
1747 			print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1);
1748 			dbuf->used++;
1749 		} else if (BITFIELD(opc,5,3) == 0x7 &&
1750 		    BITFIELD(opc,2,0) > 1) {
1751 			addstr(dbuf,"ptrap");
1752 			print_fcond(dbuf,BITFIELD(ext,5,0));
1753 
1754 			if (BITFIELD(opc,2,0) == 0x2) {
1755 				addchar('w');
1756 				addchar('\t');
1757 				dbuf->val++;
1758 				get_immed(dbuf, SIZE_WORD);
1759 				dbuf->val--;
1760 			} else if (BITFIELD(opc,2,0) == 0x3) {
1761 				addchar('l');
1762 				addchar('\t');
1763 				dbuf->val++;
1764 				get_immed(dbuf, SIZE_LONG);
1765 				dbuf->val--;
1766 			}
1767 		} else {
1768 			addstr(dbuf,"ps");
1769 			print_fcond(dbuf,BITFIELD(ext,5,0));
1770 			addchar('\t');
1771 			get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1);
1772 		}
1773 		return;
1774 	case 4:
1775 		addstr(dbuf,"psave\t");
1776 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0);
1777 		return;
1778 	case 5:
1779 		addstr(dbuf,"prestore\t");
1780 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0);
1781 		return;
1782 	}
1783 }
1784 
1785 static void
opcode_pflush(dis_buffer_t * dbuf,u_short opc,u_short ext)1786 opcode_pflush(dis_buffer_t *dbuf, u_short opc, u_short ext)
1787 {
1788 	u_short mode, mask, fc;
1789 
1790 	mode = BITFIELD(ext,12,10);
1791 	mask = BITFIELD(ext,8,5);
1792 	fc = BITFIELD(ext, 5, 0);
1793 
1794 	if (ext == 0xa000) {
1795 		addstr(dbuf,"pflushr\t");
1796 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1);
1797 		return;
1798 	}
1799 
1800 	if (mode == 0) {
1801 		addstr(dbuf,"pload");
1802 		if (ISBITSET(ext,9))
1803 			addchar('r');
1804 		else
1805 			addchar('w');
1806 		addchar(' ');
1807 		print_fcode(dbuf, fc);
1808 	}
1809 
1810 	addstr(dbuf,"pflush");
1811 	switch (mode) {
1812 	case 1:
1813 		addchar('a');
1814 		*dbuf->casm = 0;
1815 		break;
1816 	case 7:
1817 	case 5:
1818 		addchar('s');
1819 		/*FALLTHROUGH*/
1820 	case 6:
1821 	case 4:
1822 		addchar('\t');
1823 		print_fcode(dbuf, fc);
1824 		addchar(',');
1825 		addchar('#');
1826 		printu(dbuf, mask, SIZE_BYTE);
1827 		if (!ISBITSET(mode,1))
1828 			break;
1829 		addchar(',');
1830 		get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1);
1831 	}
1832 }
1833 
1834 static void
opcode_pmove(dis_buffer_t * dbuf,u_short opc,u_short ext)1835 opcode_pmove(dis_buffer_t *dbuf, u_short opc, u_short ext)
1836 {
1837 	const char *reg;
1838 	int rtom, sz, preg;
1839 
1840 	reg  = "???";
1841 	sz   = 0;
1842 	rtom = ISBITSET(ext, 9);
1843 	preg = BITFIELD(ext, 12, 10);
1844 
1845 	addstr(dbuf,"pmov");
1846 	if (ISBITSET(ext,8)) {
1847 		addchar('f');
1848 		addchar('d');
1849 	}
1850 	switch (BITFIELD(ext, 15, 13)) {
1851 	case 0: /* tt regs 030o */
1852 		switch (preg) {
1853 		case 2:
1854 			reg = "tt0";
1855 			break;
1856 		case 3:
1857 			reg = "tt1";
1858 			break;
1859 		}
1860 		sz = SIZE_LONG;
1861 		break;
1862 	case 2:
1863 		switch (preg) {
1864 		case 0:
1865 			reg = "tc";
1866 			sz = SIZE_LONG;
1867 			break;
1868 		case 1:
1869 			reg = "drp";
1870 			sz = SIZE_QUAD;
1871 			break;
1872 		case 2:
1873 			reg = "srp";
1874 			sz = SIZE_QUAD;
1875 			break;
1876 		case 3:
1877 			reg = "crp";
1878 			sz = SIZE_QUAD;
1879 			break;
1880 		case 4:
1881 			reg = "cal";
1882 			sz = SIZE_BYTE;
1883 			break;
1884 		case 5:
1885 			reg = "val";
1886 			sz = SIZE_BYTE;
1887 			break;
1888 		case 6:
1889 			reg = "scc";
1890 			sz = SIZE_BYTE;
1891 			break;
1892 		case 7:
1893 			reg = "ac";
1894 			sz = SIZE_WORD;
1895 		}
1896 		break;
1897 	case 3:
1898 		switch (preg) {
1899 		case 0:
1900 			reg = "mmusr";
1901 			break;
1902 		case 1:
1903 			reg = "pcsr";
1904 			break;
1905 		case 4:
1906 			reg = "bad";
1907 			break;
1908 		case 5:
1909 			reg = "bac";
1910 			break;
1911 		}
1912 		sz = SIZE_WORD;
1913 		break;
1914 	}
1915 	switch (sz) {
1916 	case SIZE_BYTE:
1917 		addchar ('b');
1918 		break;
1919 	case SIZE_WORD:
1920 		addchar ('w');
1921 		break;
1922 	case SIZE_LONG:
1923 		addchar ('l');
1924 		break;
1925 	case SIZE_QUAD:
1926 		addchar ('d');
1927 		break;
1928 	}
1929 	addchar('\t');
1930 
1931 	if (!rtom) {
1932 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
1933 		addchar(',');
1934 	}
1935 	addstr(dbuf, reg);
1936 	if (BITFIELD(ext, 15, 13) == 3 && preg > 1)
1937 		printu_bf(dbuf, ext, 4, 2);
1938 	if (rtom) {
1939 		addchar(',');
1940 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
1941 	}
1942 	return;
1943 }
1944 
1945 static void
print_fcode(dis_buffer_t * dbuf,u_short fc)1946 print_fcode(dis_buffer_t *dbuf, u_short fc)
1947 {
1948 	if (ISBITSET(fc, 4))
1949 		printu_bf(dbuf, fc, 3, 0);
1950 	else if (ISBITSET(fc, 3))
1951 		PRINT_DREG(dbuf, BITFIELD(fc, 2, 0));
1952 	else if (fc == 1)
1953 		addstr(dbuf, "sfc");
1954 	else
1955 		addstr(dbuf, "dfc");
1956 }
1957 
1958 static void
opcode_mmu040(dis_buffer_t * dbuf,u_short opc)1959 opcode_mmu040(dis_buffer_t *dbuf, u_short opc)
1960 {
1961 	if (ISBITSET(opc, 6)) {
1962 		addstr(dbuf, "ptest");
1963 		if (ISBITSET(opc, 5))
1964 			addchar('r');
1965 		else
1966 			addchar('w');
1967 		addchar('\t');
1968 		PRINT_AREG(dbuf, BITFIELD(opc,2,0));
1969 		addchar('@');
1970 	} else {
1971 		addstr(dbuf, "pflush");
1972 		switch (BITFIELD(opc, 4, 3)) {
1973 		case 3:
1974 			addchar('a');
1975 			break;
1976 		case 2:
1977 			addchar('a');
1978 			addchar('n');
1979 			break;
1980 		case 0:
1981 			addchar('n');
1982 			/*FALLTHROUGH*/
1983 		case 1:
1984 			addchar('\t');
1985 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
1986 			addchar('@');
1987 			break;
1988 		}
1989 	}
1990 	*dbuf->casm = 0;
1991 }
1992 
1993 /*
1994  * disassemble long format (64b) divs/muls divu/mulu opcode.
1995  * Note: opcode's dbuf->used already accounted for.
1996  */
1997 static void
opcode_divmul(dis_buffer_t * dbuf,u_short opc)1998 opcode_divmul(dis_buffer_t *dbuf, u_short opc)
1999 {
2000 	u_short ext;
2001 	int iq, hr;
2002 
2003 	ext = *(dbuf->val + 1);
2004 	dbuf->used++;
2005 
2006 	iq = BITFIELD(ext,14,12);
2007 	hr = BITFIELD(ext,2,0);
2008 
2009 	if (IS_INST(DIVSL,opc))
2010 		addstr(dbuf, "div");
2011 	else
2012 		addstr(dbuf, "mul");
2013 	if (ISBITSET(ext,11))
2014 		addchar('s');
2015 	else
2016 		addchar('u');
2017 	addchar('l');
2018 	if (IS_INST(DIVSL,opc) && !ISBITSET(ext,10) && iq != hr)
2019 		addchar('l');
2020 	addchar('\t');
2021 
2022 	get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,1);
2023 	addchar(',');
2024 
2025 	if (ISBITSET(ext,10) ||
2026 	    (iq != hr && IS_INST(DIVSL,opc))) {
2027 		/* 64 bit version */
2028 		PRINT_DREG(dbuf, hr);
2029 		if (dbuf->mit)
2030 			addchar(',');
2031 		else
2032 			addchar(':');
2033 	}
2034 	PRINT_DREG(dbuf, iq);
2035 }
2036 
2037 static void
print_reglist(dis_buffer_t * dbuf,int mod,u_short rl)2038 print_reglist(dis_buffer_t *dbuf, int mod, u_short rl)
2039 {
2040 	static const char *const regs[16] = {
2041 		"d0","d1","d2","d3","d4","d5","d6","d7",
2042 		"a0","a1","a2","a3","a4","a5","a6","a7" };
2043 	int bit, list;
2044 
2045 	if (mod == AR_DEC) {
2046 		list = rl;
2047 		rl = 0;
2048 		/* I am sure there is some trick... */
2049 		for (bit = 0; bit < 16; bit++)
2050 			if (list & (1 << bit))
2051 				rl |= (0x8000 >> bit);
2052 	}
2053 	for (bit = 0, list = 0; bit < 16; bit++) {
2054 		if (ISBITSET(rl,bit) && bit != 8) {
2055 			if (list == 0) {
2056 				list = 1;
2057 				addstr(dbuf, regs[bit]);
2058 			} else if (list == 1) {
2059 				list++;
2060 				addchar('-');
2061 			}
2062 		} else {
2063 			if (list) {
2064 				if (list > 1)
2065 					addstr(dbuf, regs[bit-1]);
2066 				addchar('/');
2067 				list = 0;
2068 			}
2069 			if (ISBITSET(rl,bit)) {
2070 				addstr(dbuf, regs[bit]);
2071 				list = 1;
2072 			}
2073 		}
2074 	}
2075 	if (list > 1)
2076 		addstr(dbuf, regs[15]);
2077 
2078 	if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-')
2079 		dbuf->casm--;
2080 	*dbuf->casm = 0;
2081 }
2082 
2083 static void
print_freglist(dis_buffer_t * dbuf,int mod,u_short rl,int cntl)2084 print_freglist(dis_buffer_t *dbuf, int mod, u_short rl, int cntl)
2085 {
2086 	const char *const * regs;
2087 	int bit, list, upper;
2088 
2089 	regs = cntl ? fpcregs : fpregs;
2090 	upper = cntl ? 3 : 8;
2091 
2092 	if (!cntl && mod != AR_DEC) {
2093 		list = rl;
2094 		rl = 0;
2095 		/* I am sure there is some trick... */
2096 		for (bit = 0; bit < upper; bit++)
2097 			if (list & (1 << bit))
2098 				rl |= (0x80 >> bit);
2099 	}
2100 	for (bit = 0, list = 0; bit < upper; bit++) {
2101 		if (ISBITSET(rl,bit)) {
2102 			if (list == 0) {
2103 				addstr(dbuf, regs[bit]);
2104 				if (cntl)
2105 					addchar('/');
2106 				else
2107 					list = 1;
2108 			} else if (list == 1) {
2109 				list++;
2110 				addchar('-');
2111 			}
2112 		} else {
2113 			if (list) {
2114 				if (list > 1)
2115 					addstr(dbuf, regs[bit-1]);
2116 				addchar('/');
2117 				list = 0;
2118 			}
2119 		}
2120 	}
2121 	if (list > 1)
2122 		addstr(dbuf, regs[upper-1]);
2123 
2124 	if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-')
2125 		dbuf->casm--;
2126 	*dbuf->casm = 0;
2127 }
2128 
2129 /*
2130  * disassemble movem opcode.
2131  */
2132 static void
opcode_movem(dis_buffer_t * dbuf,u_short opc)2133 opcode_movem(dis_buffer_t *dbuf, u_short opc)
2134 {
2135 	u_short rl;
2136 
2137 	rl = *(dbuf->val + 1);
2138 	dbuf->used++;
2139 
2140 	if (ISBITSET(opc,6))
2141 		addstr(dbuf, "movml\t");
2142 	else
2143 		addstr(dbuf, "movmw\t");
2144 	if (ISBITSET(opc,10)) {
2145 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1);
2146 		addchar(',');
2147 		print_reglist(dbuf, BITFIELD(opc,5,3), rl);
2148 	} else {
2149 		print_reglist(dbuf, BITFIELD(opc,5,3), rl);
2150 		addchar(',');
2151 		get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1);
2152 	}
2153 }
2154 
2155 /*
2156  * disassemble movec opcode.
2157  */
2158 static void
opcode_movec(dis_buffer_t * dbuf,u_short opc)2159 opcode_movec(dis_buffer_t *dbuf, u_short opc)
2160 {
2161 	const char *tmp;
2162 	u_short ext;
2163 
2164 	ext = *(dbuf->val + 1);
2165 	dbuf->used++;
2166 
2167 	addstr(dbuf, "movc\t");
2168 	if (ISBITSET(opc,0)) {
2169 		dbuf->val++;
2170 		if (ISBITSET(ext,15))
2171 			get_modregstr(dbuf,14,AR_DIR,0,0);
2172 		else
2173 			get_modregstr(dbuf,14,DR_DIR,0,0);
2174 		dbuf->val--;
2175 		addchar(',');
2176 	}
2177 	switch (BITFIELD(ext,11,0)) {
2178 		/* 010/020/030/040/CPU32/060 */
2179 	case 0x000:
2180 		tmp = "sfc";
2181 		break;
2182 	case 0x001:
2183 		tmp = "dfc";
2184 		break;
2185 	case 0x800:
2186 		tmp = "usp";
2187 		break;
2188 	case 0x801:
2189 		tmp = "vbr";
2190 		break;
2191 		/* 020/030 */
2192 	case 0x802:
2193 		tmp = "caar";
2194 		break;
2195 		/* 020/030/040/060 */
2196 	case 0x002:
2197 		tmp = "cacr";
2198 		break;
2199 		/* 020/030/040 */
2200 	case 0x803:
2201 		tmp = "msp";
2202 		break;
2203 	case 0x804:
2204 		tmp = "isp";
2205 		break;
2206 		/* 040/060 */
2207 	case 0x003:
2208 		tmp = "tc";
2209 		break;
2210 	case 0x004:
2211 		tmp = "itt0";
2212 		break;
2213 	case 0x005:
2214 		tmp = "itt1";
2215 		break;
2216 	case 0x006:
2217 		tmp = "dtt0";
2218 		break;
2219 	case 0x007:
2220 		tmp = "dtt1";
2221 		break;
2222 		/* 040 */
2223 	case 0x805:
2224 		tmp = "mmusr";
2225 		break;
2226 		/* 040/060 */
2227 	case 0x806:
2228 		tmp = "urp";
2229 		break;
2230 	case 0x807:
2231 		tmp = "srp";
2232 		break;
2233 		/* 060 */
2234 	case 0x008:
2235 		tmp = "buscr";
2236 		break;
2237 	case 0x808:
2238 		tmp = "pcr";
2239 		break;
2240 	default:
2241 		tmp = "INVALID";
2242 		break;
2243 	}
2244 	addstr(dbuf, tmp);
2245 	if (!ISBITSET(opc,0)) {
2246 		dbuf->val++;
2247 		addchar(',');
2248 		if (ISBITSET(ext,15))
2249 			get_modregstr(dbuf,14,AR_DIR,0,0);
2250 		else
2251 			get_modregstr(dbuf,14,DR_DIR,0,0);
2252 		dbuf->val--;
2253 	}
2254 }
2255 
2256 /*
2257  * disassemble move16 opcode.
2258  */
2259 static void
opcode_move16(dis_buffer_t * dbuf,u_short opc)2260 opcode_move16(dis_buffer_t *dbuf, u_short opc)
2261 {
2262 	u_short ext;
2263 
2264 	addstr(dbuf, "move16\t");
2265 
2266 	if (ISBITSET(opc, 5)) {
2267 		PRINT_AREG(dbuf, BITFIELD(opc,2,0));
2268 		addstr(dbuf, "@+,");
2269 		ext = *(dbuf->val + 1);
2270 		PRINT_AREG(dbuf, BITFIELD(ext,14,12));
2271 		addstr(dbuf, "@+");
2272 		dbuf->used++;
2273 	} else {
2274 		switch (BITFIELD(opc,4,3)) {
2275 		case 0:
2276 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
2277 			addstr(dbuf, "@+,");
2278 			get_immed(dbuf, SIZE_LONG);
2279 			break;
2280 		case 1:
2281 			get_immed(dbuf, SIZE_LONG);
2282 			addchar(',');
2283 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
2284 			addstr(dbuf, "@+");
2285 			break;
2286 		case 2:
2287 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
2288 			addstr(dbuf, "@,");
2289 			get_immed(dbuf, SIZE_LONG);
2290 			break;
2291 		case 3:
2292 			get_immed(dbuf, SIZE_LONG);
2293 			addchar(',');
2294 			PRINT_AREG(dbuf, BITFIELD(opc,2,0));
2295 			addchar('@');
2296 			break;
2297 		}
2298 	}
2299 }
2300 
2301 /*
2302  * copy const string 's' into ``dbuf''->casm
2303  */
2304 static void
addstr(dis_buffer_t * dbuf,const char * s)2305 addstr(dis_buffer_t *dbuf, const char *s)
2306 {
2307 	while ((*dbuf->casm++ = *s++))
2308 		;
2309 	dbuf->casm--;
2310 }
2311 
2312 /*
2313  * copy const string 's' into ``dbuf''->cinfo
2314  */
2315 static void
iaddstr(dis_buffer_t * dbuf,const char * s)2316 iaddstr(dis_buffer_t *dbuf, const char *s)
2317 {
2318 	while ((*dbuf->cinfo++ = *s++))
2319 		;
2320 	dbuf->cinfo--;
2321 }
2322 
2323 static void
get_modregstr_moto(dis_buffer_t * dbuf,int bit,int mod,int sz,int dd)2324 get_modregstr_moto(dis_buffer_t *dbuf, int bit, int mod, int sz, int dd)
2325 {
2326 	u_char scale, idx;
2327 	const short *nval;
2328 	u_short ext;
2329 	int disp, odisp, bd, od, reg;
2330 
2331 	odisp = 0;
2332 
2333 	/* check to see if we have been given the mod */
2334 	if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER)
2335 		reg = BITFIELD(*dbuf->val, bit, bit-2);
2336 	else if (mod == GETMOD_BEFORE) {
2337 		mod = BITFIELD(*dbuf->val, bit, bit-2);
2338 		reg = BITFIELD(*dbuf->val, bit-3, bit-5);
2339 	} else {
2340 		reg = BITFIELD(*dbuf->val, bit, bit-2);
2341 		mod = BITFIELD(*dbuf->val, bit-3, bit-5);
2342 	}
2343 	switch (mod) {
2344 	case DR_DIR:
2345 	case AR_DIR:
2346 		if (mod == DR_DIR)
2347 			PRINT_DREG(dbuf, reg);
2348 		else
2349 			PRINT_AREG(dbuf, reg);
2350 		break;
2351 	case AR_DIS:
2352 		print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD,reg);
2353 		dbuf->used++;
2354 		/*FALLTHROUGH*/
2355 	case AR_IND:
2356 	case AR_INC:
2357 	case AR_DEC:
2358 		if (mod == AR_DEC)
2359 			addchar('-');
2360 		addchar('(');
2361 		PRINT_AREG(dbuf, reg);
2362 		addchar(')');
2363 		if (mod == AR_INC)
2364 			addchar('+');
2365 		break;
2366 	/* mod 6 & 7 are the biggies. */
2367 	case MOD_SPECIAL:
2368 		if (reg == 0) {
2369 			/* abs short addr */
2370 			print_addr(dbuf, *(dbuf->val + 1 + dd));
2371 			dbuf->used++;
2372 			addchar('.');
2373 			addchar('w');
2374 			break;
2375 		} else if (reg == 1) {
2376 			/* abs long addr */
2377 			print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd));
2378 			dbuf->used += 2;
2379 			addchar('.');
2380 			addchar('l');
2381 			break;
2382 		} else if (reg == 2) {
2383 			/* pc ind displ. xxx(PC) */
2384 			dbuf->used++;
2385 			print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD,
2386 				   -1);
2387 			addstr(dbuf,"(pc)");
2388 			break;
2389 		} else if (reg == 4) {
2390 			/* uses ``sz'' to figure immediate data. */
2391 			if (sz == SIZE_BYTE) {
2392 				addchar('#');
2393 				prints(dbuf,
2394 				    *((char *)dbuf->val + 3+ (dd * 2)), sz);
2395 				dbuf->used++;
2396 			} else if (sz == SIZE_WORD) {
2397 				addchar('#');
2398 				prints(dbuf, *(dbuf->val + 1 + dd), sz);
2399 				dbuf->used++;
2400 			} else if (sz == SIZE_LONG) {
2401 				addchar('#');
2402 				prints(dbuf, *(long *)(dbuf->val + 1 + dd),
2403 				    sz);
2404 				dbuf->used += 2;
2405 			} else if (sz == SIZE_QUAD) {
2406 				dbuf->used += 4;
2407 				addstr(dbuf,"#<quad>");
2408 			} else if (sz == SIZE_SINGLE) {
2409 				dbuf->used += 2;
2410 				addstr(dbuf,"#<single>");
2411 			} else if (sz == SIZE_DOUBLE) {
2412 				dbuf->used += 4;
2413 				addstr(dbuf,"#<double>");
2414 			} else if (sz == SIZE_PACKED) {
2415 				dbuf->used += 6;
2416 				addstr(dbuf,"#<packed>");
2417 			} else if (sz == SIZE_EXTENDED) {
2418 				dbuf->used += 6;
2419 				addstr(dbuf,"#<extended>");
2420 			}
2421 			break;
2422 		}
2423 		/* standrd PC stuff. */
2424 		/*FALLTHROUGH*/
2425 	case AR_IDX:
2426 		ext = *(dbuf->val + 1 + dd);
2427 		dbuf->used++;
2428 		nval = dbuf->val + 2 + dd; /* set to possible displacements */
2429 		scale = BITFIELD(ext,10,9);
2430 		idx = BITFIELD(ext,14,12);
2431 
2432 		if (ISBITSET(ext,8)) {
2433 			/* either base disp, or memory indirect */
2434 			bd = BITFIELD(ext,5,4);
2435 			od = BITFIELD(ext,1,0);
2436 			if (bd == 1)
2437 				disp = 0;
2438 			else if (bd == 2) {
2439 				dbuf->used++;
2440 				disp = *nval++;
2441 			} else {
2442 				dbuf->used += 2;
2443 				disp = *(const long *)nval;
2444 				nval += 2;
2445 			}
2446 
2447 			if (od == 1)
2448 				odisp = 0;
2449 			else if (od == 2) {
2450 				dbuf->used++;
2451 				odisp = *nval++;
2452 			} else if (od == 3) {
2453 				dbuf->used += 2;
2454 				odisp = *(const long *)nval;
2455 				nval += 2;
2456 			}
2457 		} else {
2458 			/*
2459 			 * We set od and bd to zero, these values are
2460 			 * not allowed in opcodes that use base and
2461 			 * outer displacement, e.g. we can tell if we
2462 			 * are using on of those modes by checking
2463 			 * `bd' and `od'.
2464 			 */
2465 			od = 0;
2466 			bd = 0;
2467 			disp = (char)BITFIELD(ext,7,0);
2468 		}
2469 		/*
2470 		 * write everything into buf
2471 		 */
2472 		addchar('(');
2473 		if (od)
2474 			addchar('['); /* begin memory indirect xxx-indexed */
2475 		prints(dbuf, disp,
2476 		    bd == 2 ? SIZE_WORD :
2477 		    bd == 3 ? SIZE_LONG :
2478 		    SIZE_BYTE);
2479 		addchar(',');
2480 		if (bd && ISBITSET(ext,7)) {
2481 			addchar('z');
2482 			if (mod != MOD_SPECIAL)
2483 				PRINT_AREG(dbuf,reg);
2484 			else {
2485 				addchar('p');
2486 				addchar('c');
2487 			}
2488 		} else if (mod == AR_IDX)
2489 			PRINT_AREG(dbuf, reg);
2490 		else {
2491 			addchar('p');
2492 			addchar('c');
2493 		}
2494 
2495 		if (od && ISBITSET(ext,2))
2496 			addchar(']'); /* post-indexed. */
2497 		addchar(',');
2498 		if (bd && ISBITSET(ext,6))
2499 			addchar('0');
2500 		else {
2501 			if (0x8000 & ext)
2502 				PRINT_AREG(dbuf, idx);
2503 			else
2504 				PRINT_DREG(dbuf, idx);
2505 			addchar('.');
2506 			addchar(0x800 & ext ? 'l' : 'w');
2507 			if (scale) {
2508 				addchar('*');
2509 				addchar('0' + (1 << scale));
2510 			}
2511 		}
2512 		if (od) {
2513 			if (!ISBITSET(ext,2))
2514 				addchar(']'); /* pre-indexed */
2515 			addchar(',');
2516 			prints(dbuf, odisp,
2517 			    od == 2 ? SIZE_WORD :
2518 			    od == 3 ? SIZE_LONG :
2519 			    SIZE_BYTE);
2520 		}
2521 		addchar(')');
2522 		break;
2523 	}
2524 	*dbuf->casm = 0;
2525 }
2526 
2527 /* mit syntax makes for spaghetti parses */
2528 static void
get_modregstr_mit(dis_buffer_t * dbuf,int bit,int mod,int sz,int dd)2529 get_modregstr_mit(dis_buffer_t *dbuf, int bit, int mod, int sz, int dd)
2530 {
2531 	u_char scale, idx;
2532 	const short *nval;
2533 	u_short ext;
2534 	int disp, odisp, bd, od, reg;
2535 
2536 	disp = odisp = 0;
2537 	/* check to see if we have been given the mod */
2538 	if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER)
2539 		reg = BITFIELD(*dbuf->val, bit, bit-2);
2540 	else if (mod == GETMOD_BEFORE) {
2541 		mod = BITFIELD(*dbuf->val, bit, bit-2);
2542 		reg = BITFIELD(*dbuf->val, bit-3, bit-5);
2543 	} else {
2544 		reg = BITFIELD(*dbuf->val, bit, bit-2);
2545 		mod = BITFIELD(*dbuf->val, bit-3, bit-5);
2546 	}
2547 	switch (mod) {
2548 	case DR_DIR:
2549 	case AR_DIR:
2550 		if (mod == DR_DIR)
2551 			PRINT_DREG(dbuf, reg);
2552 		else
2553 			PRINT_AREG(dbuf, reg);
2554 		break;
2555 	case AR_DIS:
2556 		dbuf->used++;	/* tell caller we used an ext word. */
2557 		disp = *(dbuf->val + 1 + dd);
2558 		/*FALLTHROUGH*/
2559 	case AR_IND:
2560 	case AR_INC:
2561 	case AR_DEC:
2562 		PRINT_AREG(dbuf, reg);
2563 		addchar('@' );
2564 		if (mod == AR_DEC)
2565 			addchar('-');
2566 		else if (mod == AR_INC)
2567 			addchar('+');
2568 		else if (mod == AR_DIS) {
2569 			addchar('(');
2570 			print_disp(dbuf, disp, SIZE_WORD, reg);
2571 			addchar(')');
2572 		}
2573 		break;
2574 	/* mod 6 & 7 are the biggies. */
2575 	case MOD_SPECIAL:
2576 		if (reg == 0) {
2577 			/* abs short addr */
2578 			print_addr(dbuf, *(dbuf->val + 1 + dd));
2579 			dbuf->used++;
2580 			break;
2581 		} else if (reg == 1) {
2582 			/* abs long addr */
2583 			print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd));
2584 			dbuf->used += 2;
2585 			break;
2586 		} else if (reg == 2) {
2587 			/* pc ind displ. pc@(xxx) */
2588 			addstr(dbuf,"pc@(");
2589 			print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD, -1);
2590 			dbuf->used++;
2591 			addchar(')');
2592 			break;
2593 		} else if (reg == 4) {
2594 			/* uses ``sz'' to figure immediate data. */
2595 			if (sz == SIZE_BYTE) {
2596 				addchar('#');
2597 				prints(dbuf,
2598 				    *((char *)dbuf->val + 3 + (dd * 2)), sz);
2599 				dbuf->used++;
2600 			} else if (sz == SIZE_WORD) {
2601 				addchar('#');
2602 				prints(dbuf, *(dbuf->val + 1 + dd), sz);
2603 				dbuf->used++;
2604 			} else if (sz == SIZE_LONG) {
2605 				addchar('#');
2606 				prints(dbuf, *(long *)(dbuf->val + 1 + dd),
2607 				    sz);
2608 				dbuf->used += 2;
2609 			} else if (sz == SIZE_QUAD) {
2610 				dbuf->used += 4;
2611 				addstr(dbuf,"#<quad>");
2612 			} else if (sz == SIZE_SINGLE) {
2613 				dbuf->used += 2;
2614 				addstr(dbuf,"#<single>");
2615 			} else if (sz == SIZE_DOUBLE) {
2616 				dbuf->used += 4;
2617 				addstr(dbuf,"#<double>");
2618 			} else if (sz == SIZE_PACKED) {
2619 				dbuf->used += 6;
2620 				addstr(dbuf,"#<packed>");
2621 			} else if (sz == SIZE_EXTENDED) {
2622 				dbuf->used += 6;
2623 				addstr(dbuf,"#<extended>");
2624 			}
2625 			break;
2626 		}
2627 		/* standrd PC stuff. */
2628 		/*FALLTHROUGH*/
2629 	case AR_IDX:
2630 		dbuf->used++;	/* indicate use of ext word. */
2631 		ext = *(dbuf->val + 1 + dd);
2632 		nval = dbuf->val + 2 + dd; /* set to possible displacements */
2633 		scale = BITFIELD(ext,10,9);
2634 		idx = BITFIELD(ext,14,12);
2635 
2636 		if (ISBITSET(ext,8)) {
2637 			/* either base disp, or memory indirect */
2638 			bd = BITFIELD(ext,5,4);
2639 			od = BITFIELD(ext,1,0);
2640 			if (bd == 1)
2641 				disp = 0;
2642 			else if (bd == 2) {
2643 				dbuf->used++;
2644 				disp = *nval++;
2645 			} else {
2646 				dbuf->used += 2;
2647 				disp = *(const long *)nval;
2648 				nval += 2;
2649 			}
2650 
2651 			if (od == 1)
2652 				odisp = 0;
2653 			else if (od == 2) {
2654 				dbuf->used++;
2655 				odisp = *nval++;
2656 			} else if (od == 3) {
2657 				dbuf->used += 2;
2658 				odisp = *(const long *)nval;
2659 				nval += 2;
2660 			}
2661 		} else {
2662 			/*
2663 			 * We set od and bd to zero, these values are
2664 			 * not allowed in opcodes that use base and
2665 			 * outer displacement, e.g. we can tell if we
2666 			 * are using on of those modes by checking
2667 			 * `bd' and `od'.
2668 			 */
2669 			od = 0;
2670 			bd = 0;
2671 			disp = (char)BITFIELD(ext,7,0);
2672 		}
2673 		/*
2674 		 * write everything into buf
2675 		 */
2676 		/* if base register not suppresed */
2677 		if (mod == AR_IDX && (!bd || !ISBITSET(ext,7)))
2678 			PRINT_AREG(dbuf, reg);
2679 		else if (mod == MOD_SPECIAL && ISBITSET(ext,7)) {
2680 			addchar('z');
2681 			addchar('p');
2682 			addchar('c');
2683 		} else if (mod == MOD_SPECIAL) {
2684 			addchar('p');
2685 			addchar('c');
2686 		}
2687 		addchar('@');
2688 		addchar('(');
2689 
2690 		if (bd && bd != 1) {
2691 			prints(dbuf, disp,
2692 			    bd == 2 ? SIZE_WORD :
2693 			    bd == 3 ? SIZE_LONG :
2694 			    SIZE_BYTE);
2695 			if (od && !ISBITSET(ext,6) && !ISBITSET(ext,2))
2696 				/* Pre-indexed and not suppressing index */
2697 				addchar(',');
2698 			else if (od && ISBITSET(ext,2)) {
2699 				/* Post-indexed */
2700 				addchar(')');
2701 				addchar('@');
2702 				addchar('(');
2703 			} else if (!od)
2704 				addchar(',');
2705 		} else if (!bd) {
2706 			/* don't forget simple 8 bit displacement. */
2707 			prints(dbuf, disp,
2708 			    bd == 2 ? SIZE_WORD :
2709 			    bd == 3 ? SIZE_LONG :
2710 			    SIZE_BYTE);
2711 			addchar(',');
2712 		}
2713 
2714 		/* Post-indexed? */
2715 		if (od && ISBITSET(ext,2)) {
2716 			/* have displacement? */
2717 			if (od != 1) {
2718 				prints(dbuf, odisp,
2719 				    od == 2 ? SIZE_WORD :
2720 				    od == 3 ? SIZE_LONG :
2721 				    SIZE_BYTE);
2722 				addchar(',');
2723 			}
2724 		}
2725 
2726 		if (!bd || !ISBITSET(ext,6)) {
2727 			if (ISBITSET(ext,15))
2728 				PRINT_AREG(dbuf,idx);
2729 			else
2730 				PRINT_DREG(dbuf,idx);
2731 			addchar(':');
2732 			addchar(ISBITSET(ext,11) ? 'l' : 'w');
2733 			if (scale) {
2734 				addchar(':');
2735 				addchar('0' + (1 << scale));
2736 			}
2737 		}
2738 		/* pre-indexed? */
2739 		if (od && !ISBITSET(ext,2)) {
2740 			if (od != 1) {
2741 				addchar(')');
2742 				addchar('@');
2743 				addchar('(');
2744 				prints(dbuf, odisp,
2745 				    od == 2 ? SIZE_WORD :
2746 				    od == 3 ? SIZE_LONG :
2747 				    SIZE_BYTE);
2748 			}
2749 		}
2750 		addchar(')');
2751 		break;
2752 	}
2753 	*dbuf->casm = 0;
2754 }
2755 
2756 /*
2757  * Given a disassembly buffer ``dbuf'' and a starting bit of the
2758  * mod|reg field ``bit'' (or just a reg field if ``mod'' is not
2759  * GETMOD_BEFORE or GETMOD_AFTER), disassemble and write into ``dbuf''
2760  * the mod|reg pair.
2761  */
2762 static void
get_modregstr(dis_buffer_t * dbuf,int bit,int mod,int sz,int dispdisp)2763 get_modregstr(dis_buffer_t *dbuf, int bit, int mod, int sz, int dispdisp)
2764 {
2765 	if (dbuf->mit)
2766 		get_modregstr_mit(dbuf,bit,mod,sz,dispdisp);
2767 	else
2768 		get_modregstr_moto(dbuf,bit,mod,sz,dispdisp);
2769 }
2770 
2771 /*
2772  * given a bit position ``bit'' in the current ``dbuf''->val
2773  * and the ``base'' string of the opcode, append the full
2774  * opcode name including condition found at ``bit''.
2775  */
2776 static void
make_cond(dis_buffer_t * dbuf,int bit,const char * base)2777 make_cond(dis_buffer_t *dbuf, int bit, const char *base)
2778 {
2779 	int cc;
2780 	const char *ccs;
2781 
2782 	cc = BITFIELD(*dbuf->val,bit,bit-3);
2783 	ccs = cc_table[cc&15];
2784 
2785 	addstr(dbuf, base);
2786 	addstr(dbuf, ccs);
2787 }
2788 
2789 static void
print_fcond(dis_buffer_t * dbuf,char cp)2790 print_fcond(dis_buffer_t *dbuf, char cp)
2791 {
2792 	addstr(dbuf,fpcc_table[cp&31]);		/* XXX - not 63 ?*/
2793 }
2794 
2795 static void
print_mcond(dis_buffer_t * dbuf,char cp)2796 print_mcond(dis_buffer_t *dbuf, char cp)
2797 {
2798 	addstr(dbuf,mmcc_table[cp&15]);
2799 }
2800 
2801 /*
2802  * given dis_buffer_t ``dbuf'' get the immediate value from the
2803  * extension words following current instruction, output a
2804  * hash (``#'') sign and the value.  Increment the ``dbuf''->used
2805  * field accordingly.
2806  */
2807 static void
get_immed(dis_buffer_t * dbuf,int sz)2808 get_immed(dis_buffer_t *dbuf,int sz)
2809 {
2810 	addchar('#');
2811 	switch (sz) {
2812 	case SIZE_BYTE:
2813 		prints(dbuf, BITFIELD(*(dbuf->val + 1),7,0), SIZE_BYTE);
2814 		dbuf->used++;
2815 		break;
2816 	case SIZE_WORD:
2817 		prints(dbuf, *(dbuf->val + 1), SIZE_WORD);
2818 		dbuf->used++;
2819 		break;
2820 	case SIZE_LONG:
2821 		prints(dbuf, *(long *)(dbuf->val + 1), SIZE_LONG);
2822 		dbuf->used += 2;
2823 		break;
2824 	}
2825 	return;
2826 }
2827 
2828 static void
get_fpustdGEN(dis_buffer_t * dbuf,u_short ext,const char * name)2829 get_fpustdGEN(dis_buffer_t *dbuf, u_short ext, const char *name)
2830 {
2831 	int sz;
2832 
2833 	/*
2834 	 * If bit seven is set, its a 040 s/d opcode, then if bit 2 is
2835 	 * set its "d".  This is not documented, however thats the way
2836 	 * it is.
2837 	 */
2838 
2839 	sz = 0;
2840 	addchar(*name++);
2841 	if (ISBITSET(ext,7)) {
2842 		if(ISBITSET(ext,2))
2843 			addchar('d');
2844 		else
2845 			addchar('s');
2846 	}
2847 	addstr(dbuf,name);
2848 
2849 	if (ISBITSET(ext,14)) {
2850 		switch (BITFIELD(ext,12,10)) {
2851 		case 0:
2852 			addchar('l');
2853 			sz = SIZE_LONG;
2854 			break;
2855 		case 1:
2856 			addchar('s');
2857 			sz = SIZE_SINGLE;
2858 			break;
2859 		case 2:
2860 			addchar('x');
2861 			sz = SIZE_EXTENDED;
2862 			break;
2863 		case 3:
2864 			addchar('p');
2865 			sz = SIZE_PACKED;
2866 			break;
2867 		case 4:
2868 			addchar('w');
2869 			sz = SIZE_WORD;
2870 			break;
2871 		case 5:
2872 			addchar('d');
2873 			sz = SIZE_DOUBLE;
2874 			break;
2875 		case 6:
2876 			addchar('b');
2877 			sz = SIZE_BYTE;
2878 			break;
2879 		}
2880 		addchar('\t');
2881 		get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1);
2882 		if (BITFIELD(ext,6,3) == 6) {
2883 			addchar(',');
2884 			PRINT_FPREG(dbuf, BITFIELD(ext,2,0));
2885 			addchar(':');
2886 			PRINT_FPREG(dbuf, BITFIELD(ext,9,7));
2887 		} else if (BITFIELD(ext,5,0) != FTST) {
2888 			addchar(',');
2889 			PRINT_FPREG(dbuf, BITFIELD(ext,9,7));
2890 		}
2891 	} else {
2892 		addchar('x');
2893 		addchar('\t');
2894 		PRINT_FPREG(dbuf, BITFIELD(ext,12,10));
2895 		if (BITFIELD(ext,6,3) == 6) {
2896 			addchar(',');
2897 			PRINT_FPREG(dbuf, BITFIELD(ext,2,0));
2898 			addchar(':');
2899 			PRINT_FPREG(dbuf, BITFIELD(ext,9,7));
2900 		} else if (BITFIELD(ext,5,0) != FTST) {
2901 			addchar(',');
2902 			PRINT_FPREG(dbuf, BITFIELD(ext,9,7));
2903 		}
2904 	}
2905 }
2906 
2907 #if 0
2908 static u_long
2909 get_areg_val(int reg)
2910 {
2911 	return 0;
2912 }
2913 #endif
2914 
2915 /*
2916  * given value ``disp'' print it to ``dbuf''->buf. ``rel'' is a
2917  * register number 0-7 (a0-a7), or -1 (pc). Thus possible extra info
2918  * could be output to the ``dbuf''->info buffer.
2919  */
2920 static void
print_disp(dis_buffer_t * dbuf,int disp,int sz,int rel)2921 print_disp(dis_buffer_t *dbuf, int disp, int sz, int rel)
2922 {
2923 	db_expr_t diff;
2924 	db_sym_t sym;
2925 	const char *symname;
2926 	u_long nv;
2927 
2928 	prints(dbuf, disp, sz);
2929 
2930 	if (rel == -1)
2931 		/* XXX This may be wrong for a couple inst. */
2932 		nv = disp + (u_int)dbuf->val + 2;
2933 	else
2934 		return; /* nv = get_areg_val(rel); */
2935 
2936 	diff = INT_MAX;
2937 	symname = NULL;
2938 	sym = db_search_symbol(nv, DB_STGY_PROC, &diff);
2939 	db_symbol_values(sym, &symname, 0);
2940 
2941 	if (symname) {
2942 		iaddstr(dbuf, "disp:");
2943 		iaddstr(dbuf, symname);
2944 		iaddchar('+');
2945 		iprintu(dbuf, diff, SIZE_LONG);
2946 		iaddchar(' ');
2947 		*dbuf->cinfo = 0;
2948 	}
2949 }
2950 
2951 static void
print_addr(dis_buffer_t * dbuf,u_long addr)2952 print_addr(dis_buffer_t *dbuf, u_long addr)
2953 {
2954 	db_expr_t diff;
2955 	db_sym_t sym;
2956 	const char *symname;
2957 
2958 	diff = INT_MAX;
2959 	symname = NULL;
2960 	sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
2961 	db_symbol_values(sym, &symname, 0);
2962 
2963 	if (symname) {
2964 		if (diff == 0)
2965 			addstr(dbuf,symname);
2966 		else {
2967 			addchar('<');
2968 			addstr(dbuf,symname);
2969 			addchar('+');
2970 			printu(dbuf, diff, SIZE_LONG);
2971 			addchar('>');
2972 			*dbuf->casm = 0;
2973 		}
2974 		iaddstr(dbuf,"addr:");
2975 		iprintu(dbuf, addr, SIZE_LONG);
2976 		iaddchar(' ');
2977 		*dbuf->cinfo = 0;
2978 	} else {
2979 		printu(dbuf, addr, SIZE_LONG);
2980 	}
2981 }
2982 
2983 static void
prints(dis_buffer_t * dbuf,int val,int sz)2984 prints(dis_buffer_t *dbuf, int val, int sz)
2985 {
2986 	extern int db_radix;
2987 
2988 	if (val == 0) {
2989 		dbuf->casm[0] = '0';
2990 		dbuf->casm[1] = 0;
2991 	} else if (sz == SIZE_BYTE)
2992 		prints_wb(dbuf, (char)val, sz, db_radix);
2993 	else if (sz == SIZE_WORD)
2994 		prints_wb(dbuf, (short)val, sz, db_radix);
2995 	else
2996 		prints_wb(dbuf, (long)val, sz, db_radix);
2997 
2998 	dbuf->casm = &dbuf->casm[strlen(dbuf->casm)];
2999 }
3000 
3001 #if 0
3002 static void
3003 iprints(dis_buffer_t *dbuf, int val, int sz)
3004 {
3005 	extern int db_radix;
3006 
3007 	if (val == 0) {
3008 		dbuf->cinfo[0] = '0';
3009 		dbuf->cinfo[1] = 0;
3010 	} else if (sz == SIZE_BYTE)
3011 		iprints_wb(dbuf, (char)val, sz, db_radix);
3012 	else if (sz == SIZE_WORD)
3013 		iprints_wb(dbuf, (short)val, sz, db_radix);
3014 	else
3015 		iprints_wb(dbuf, (long)val, sz, db_radix);
3016 
3017 	dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)];
3018 }
3019 #endif
3020 
3021 static void
printu(dis_buffer_t * dbuf,u_int val,int sz)3022 printu(dis_buffer_t *dbuf, u_int val, int sz)
3023 {
3024 	extern int db_radix;
3025 
3026 	if (val == 0) {
3027 		dbuf->casm[0] = '0';
3028 		dbuf->casm[1] = 0;
3029 	} else if (sz == SIZE_BYTE)
3030 		printu_wb(dbuf, (u_char)val, sz, db_radix);
3031 	else if (sz == SIZE_WORD)
3032 		printu_wb(dbuf, (u_short)val, sz, db_radix);
3033 	else
3034 		printu_wb(dbuf, (u_long)val, sz, db_radix);
3035 	dbuf->casm = &dbuf->casm[strlen(dbuf->casm)];
3036 }
3037 
3038 static void
iprintu(dis_buffer_t * dbuf,u_int val,int sz)3039 iprintu(dis_buffer_t *dbuf, u_int val, int sz)
3040 {
3041 	extern int db_radix;
3042 
3043 	if (val == 0) {
3044 		dbuf->cinfo[0] = '0';
3045 		dbuf->cinfo[1] = 0;
3046 	} else if (sz == SIZE_BYTE)
3047 		iprintu_wb(dbuf, (u_char)val, sz, db_radix);
3048 	else if (sz == SIZE_WORD)
3049 		iprintu_wb(dbuf, (u_short)val, sz, db_radix);
3050 	else
3051 		iprintu_wb(dbuf, (u_long)val, sz, db_radix);
3052 	dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)];
3053 }
3054 
3055 static void
printu_wb(dis_buffer_t * dbuf,u_int val,int sz,int base)3056 printu_wb(dis_buffer_t *dbuf, u_int val, int sz, int base)
3057 {
3058 	static char buf[sizeof(long) * NBBY / 3 + 2];
3059 	char *p, ch;
3060 
3061 	if (base != 10) {
3062 		addchar('0');
3063 		if (base != 8) {
3064 			base = 16;
3065 			addchar('x');
3066 		}
3067 	}
3068 
3069 	p = buf;
3070 	do {
3071 		*++p = hexdigits[val % base];
3072 	} while (val /= base);
3073 
3074 	while ((ch = *p--))
3075 		addchar(ch);
3076 
3077 	*dbuf->casm = 0;
3078 }
3079 
3080 static void
prints_wb(dis_buffer_t * dbuf,int val,int sz,int base)3081 prints_wb(dis_buffer_t *dbuf, int val, int sz, int base)
3082 {
3083 	if (val < 0) {
3084 		addchar('-');
3085 		val = -val;
3086 	}
3087 	printu_wb(dbuf, val, sz, base);
3088 }
3089 
3090 static void
iprintu_wb(dis_buffer_t * dbuf,u_int val,int sz,int base)3091 iprintu_wb(dis_buffer_t *dbuf, u_int val, int sz, int base)
3092 {
3093 	static char buf[sizeof(long) * NBBY / 3 + 2];
3094 	char *p, ch;
3095 
3096 	if (base != 10) {
3097 		iaddchar('0');
3098 		if (base != 8) {
3099 			base = 16;
3100 			iaddchar('x');
3101 		}
3102 	}
3103 
3104 	p = buf;
3105 	do {
3106 		*++p = hexdigits[val % base];
3107 	} while (val /= base);
3108 
3109 	while ((ch = *p--))
3110 		iaddchar(ch);
3111 
3112 	*dbuf->cinfo = 0;
3113 }
3114 
3115 #if 0
3116 static void
3117 iprints_wb(dis_buffer_t *dbuf, int val, int sz, int base)
3118 {
3119 	if (val < 0) {
3120 		iaddchar('-');
3121 		val = -val;
3122 	}
3123 	iprintu_wb(dbuf, val, sz, base);
3124 }
3125 #endif
3126 
3127 static void
prints_bf(dis_buffer_t * dbuf,int val,int sb,int eb)3128 prints_bf(dis_buffer_t *dbuf, int val, int sb, int eb)
3129 {
3130 	if (ISBITSET(val,sb))
3131 		val = (~0 & ~BITFIELD(~0, sb, eb)) | BITFIELD(val, sb, eb);
3132 	else
3133 		val = BITFIELD(val,sb,eb);
3134 
3135 	prints(dbuf, val, SIZE_LONG);
3136 }
3137 
3138 static void
printu_bf(dis_buffer_t * dbuf,u_int val,int sb,int eb)3139 printu_bf(dis_buffer_t *dbuf, u_int val, int sb, int eb)
3140 {
3141 	printu(dbuf,BITFIELD(val,sb,eb),SIZE_LONG);
3142 }
3143