1/* $OpenBSD: db_disasm.c,v 1.25 2019/11/07 14:44:52 mpi Exp $ */
2/* $NetBSD: db_disasm.c,v 1.8 2000/05/25 19:57:30 jhawk Exp $ */
3
4/*
5 * Mach Operating System
6 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
7 * All Rights Reserved.
8 *
9 * Permission to use, copy, modify and distribute this software and its
10 * documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
14 *
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 *
19 * Carnegie Mellon requests users of this software to return to
20 *
21 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22 *  School of Computer Science
23 *  Carnegie Mellon University
24 *  Pittsburgh PA 15213-3890
25 *
26 * any improvements or extensions that they make and grant Carnegie Mellon
27 * the rights to redistribute these changes.
28 */
29
30/*
31 *	File: db_disasm.c
32 * 	Author: Alessandro Forin, Carnegie Mellon University
33 *	Date:	11/91
34 *
35 *	Disassembler for Alpha
36 *
37 *	Modified for NetBSD/alpha by:
38 *
39 *	Christopher G. Demetriou, Carnegie Mellon University
40 *
41 *	Jason R. Thorpe, Numerical Aerospace Simulation Facility,
42 *	NASA Ames Research Center
43 *
44 *	This code was derived exclusively from information available in
45 *	"Alpha Architecture Reference Manual", Richard L. Sites ed.
46 *	Digital Press, Burlington, MA 01803
47 *	ISBN 1-55558-098-X, Order no. EY-L520E-DP
48 */
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/proc.h>
53#include <machine/db_machdep.h>
54#include <alpha/alpha/db_instruction.h>
55
56#include <machine/pal.h>
57
58#include <ddb/db_access.h>
59#include <ddb/db_sym.h>
60#include <ddb/db_output.h>
61#include <ddb/db_interface.h>
62
63/*
64 * This would belong in a header file, except noone else needs it
65 *
66 * XXX THESE SHOULD BE CONVERTED TO ra, rb, rc FORMAT.
67 */
68typedef union {
69	/*
70	 *	All instructions are 32 bits wide, PAL included
71	 */
72	unsigned int	bits;
73
74	/*
75	 *	Internal processor register access instrs
76	 *	specify the IPR index, doubly specify the
77	 *	(same) GP register as src/dest, and qualifiers
78	 *	for the IPR set involved (abox/ibox/tmp)
79	 */
80	struct {
81		unsigned	index : 5,
82				regset : 3, /* a,i,p */
83				xxx : 8,
84				rs : 5,
85				rd : 5,
86				opcode : 6;
87	} mXpr_format;
88
89	/*
90	 *	Load/store instructions have a 12 bit displacement,
91	 *	and two register specifiers just as normal ld/st.
92	 *	Four bits have special meanings:
93	 *		phy: bypass the MMU (physical access)
94	 *		alt: use mode in ALT register for checks,
95	 *		     or if PHY is also on locked/linked access
96	 *		rwc: read-with-write-check (probew)
97	 *		qw:  quadword access
98	 */
99	struct {
100		signed int	displacement : 12;
101		unsigned	qw : 1,
102				qualif : 3,
103				rs : 5,
104				rd : 5,
105				opcode : 6;
106	} mem_format;
107
108	/*
109	 *	Return from exception or interrupt has
110	 *	a branch-like encoding, but only one
111	 *	instantiation is actually usable.
112	 */
113	struct {
114		unsigned	xxx : 14,
115				zero : 1,	/* branch prediction! */
116				one : 1,
117				rb : 5,		/* r31 or stall */
118				ra : 5,		/* r31 or stall */
119				opcode : 6;
120	} rei_format;
121
122} pal_instruction;
123
124
125/*
126 * Major opcodes
127 */
128static char *op_name[64] = {
129/* 0 */	"call_pal", "op1", "op2", "op3", "op4",	"op5",	"op6",	"op7",
130/* 8 */	"lda",	"ldah",	"ldbu",	"ldq_u","ldwu",	"stw",	"stb",	"stq_u",
131/*16 */	"arit",	"logical","bit","mul",	"op20",	"vaxf",	"ieeef","anyf",
132/*24 */	"spec",	"hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st",
133/*32 */	"ldf",	"ldg",	"lds",	"ldt",	"stf",	"stg",	"sts",	"stt",
134/*40 */	"ldl",	"ldq",	"ldl_l","ldq_l","stl",	"stq",	"stl_c","stq_c",
135/*48 */	"br",	"fbeq",	"fblt",	"fble",	"bsr",	"fbne",	"fbge",	"fbgt",
136/*56 */	"blbc",	"beq",	"blt",	"ble",	"blbs",	"bne",	"bge",	"bgt"
137};
138
139/*
140 * The function field is too big (7 or 11 bits), so the sub-tables
141 * are addressed in a somewhat complicated manner to save
142 * space.  After all, alu operations is what RISCs are good at.
143 */
144
145struct tbl {
146	const char	*name;
147	int		code;
148};
149
150static const struct tbl pal_op_tbl[] = {
151	/* Common PAL function codes. */
152	{ "halt",		PAL_halt },
153	{ "cflush",		PAL_cflush },
154	{ "draina",		PAL_draina },
155	{ "cserve",		PAL_cserve, },
156	{ "swppal",		PAL_swppal },
157	{ "ipir",		PAL_ipir },
158	{ "bpt",		PAL_bpt },
159	{ "bugchk",		PAL_bugchk },
160	{ "imb",		PAL_imb },
161	{ "rdunique",		PAL_rdunique },
162	{ "wrunique",		PAL_wrunique },
163	{ "gentrap",		PAL_gentrap },
164
165	/* OSF/1 PAL function codes. */
166	{ "osf1_rdmces",	PAL_OSF1_rdmces },
167	{ "osf1_wrmces",	PAL_OSF1_wrmces },
168	{ "osf1_wrfen",		PAL_OSF1_wrfen },
169	{ "osf1_wrvptptr",	PAL_OSF1_wrvptptr },
170	{ "osf1_swpctx",	PAL_OSF1_swpctx },
171	{ "osf1_wrval",		PAL_OSF1_wrval },
172	{ "osf1_rdval",		PAL_OSF1_rdval },
173	{ "osf1_tbi",		PAL_OSF1_tbi },
174	{ "osf1_wrent",		PAL_OSF1_wrent },
175	{ "osf1_swpipl",	PAL_OSF1_swpipl },
176	{ "osf1_rdps",		PAL_OSF1_rdps },
177	{ "osf1_wrkgp",		PAL_OSF1_wrkgp },
178	{ "osf1_wrusp",		PAL_OSF1_wrusp },
179	{ "osf1_wrperfmon",	PAL_OSF1_wrperfmon },
180	{ "osf1_rdusp",		PAL_OSF1_rdusp },
181	{ "osf1_whami",		PAL_OSF1_whami },
182	{ "osf1_retsys",	PAL_OSF1_retsys },
183	{ "osf1_rti",		PAL_OSF1_rti },
184	{ "osf1_callsys",	PAL_OSF1_callsys },
185
186	{ NULL,			-1 },
187};
188
189static const char *pal_opname(int);
190
191static const char *
192pal_opname(op)
193	int op;
194{
195	static char unk[11];
196	int i;
197
198	for (i = 0; pal_op_tbl[i].name != NULL; i++) {
199		if (pal_op_tbl[i].code == op)
200			return (pal_op_tbl[i].name);
201	}
202
203	snprintf(unk, sizeof unk, "0x%x", op);
204	return (unk);
205}
206
207/* HW (PAL) instruction qualifiers, stright tables */
208static const char *mXpr_name[8] = {
209	"", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
210};
211static const char *hwlds_name[8] = {
212	"", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
213};
214
215/*
216 * For this one we take the low nibble (valid values 0/2/9/b/d)
217 * and shift it down one to get the row index.  Within a row
218 * we can just take the high nibble deprived of the high bit
219 * (valid values 0/1/2/3/4/6).  We could have used a flat 64
220 * entry array, but in this way we use just 48 pointers.
221 * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too
222 */
223static const char *arit_c0[8] = {
224	"addl", 0, "addq", 0, "addl/v", 0, "addq/v",
225};
226static const char *arit_c2[8] = {
227	"s4addl", "s8addl", "s4addq", "s8addq",
228};
229static const char *arit_c9[8] = {
230	"subl", 0, "subq", 0, "subl/v", 0, "subq/v",
231};
232static const char *arit_cB[8] = {
233	"s4subl", "s8subl", "s4subq", "s8subq",
234};
235static const char *arit_cD[8] = {
236	0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
237};
238static const char *arit_cF[1] = {
239	"cmpbge"
240};
241static const char **arit_opname[8] = {
242	arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
243};
244
245static __inline const char *arit_name(int);
246static __inline const char *
247arit_name(op)
248	int op;
249{
250	static char unk[32];
251	const char *name = NULL;
252
253	if (arit_opname[((op)&0xe)>>1])
254		name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
255
256	if (name != NULL)
257		return (name);
258
259	snprintf(unk, sizeof unk, "?arit 0x%x?", op);
260	return (unk);
261}
262
263/*
264 * Something similar for this one, except there are only
265 * 16 entries so the row indexing is done by enumeration
266 * of the low nibble (valid values 0/4/6/8).  Then we can
267 * just shift the high nibble to index inside the row
268 * (valid values are 0/2/4 or 1/2/4/6)
269 *
270 * There are two functions that don't play by these simple rules,
271 * so we special-case them.
272 */
273static const char *logical_c0[4] = {
274	"and", "or", "xor", 0
275};
276static const char *logical_c4[4] = {
277	"cmovlbs", "cmoveq", "cmovlt", "cmovle"
278};
279static const char *logical_c6[4] = {
280	"cmovlbc", "cmovne", "cmovge", "cmovgt"
281};
282static const char *logical_c8[4] = {
283	"andnot", "ornot", "xornot", 0
284};
285
286static __inline const char *logical_name(int);
287static __inline const char *
288logical_name(op)
289	int op;
290{
291	static char unk[32];
292	const char *name = NULL;
293
294	if (op == op_amask)
295		return ("amask");
296	else if (op == op_implver)
297		return ("implver");
298
299	switch (op & 0xf) {
300	case 0: name = logical_c0[((op)>>5)&3]; break;
301	case 4: name = logical_c4[((op)>>5)&3]; break;
302	case 6: name = logical_c6[((op)>>5)&3]; break;
303	case 8: name = logical_c8[((op)>>5)&3]; break;
304	}
305
306	if (name != NULL)
307		return (name);
308
309	snprintf(unk, sizeof unk, "?logical 0x%x?", op);
310	return (unk);
311}
312
313/*
314 * This is the messy one. First, we single out the dense
315 * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c).
316 * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7).
317 * For the remaining codes (6/7/a/b) we do as above: high
318 * nibble has valid values 0/1/2 or 5/6/7.  The low nibble
319 * can be used as row index picking bits 0 and 2, for the
320 * high one just the lower two bits.
321 */
322static const char *bitop_c3[8] = {
323	"zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
324};
325static const char *bitop_c2[8] = {
326	"mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
327};
328static const char *bitop_c67ab[4][4] = {
329/* a */	{ 0, "extwh", "extlh", "extqh"},
330/* b */	{ "insbl", "inswl", "insll", 0 },
331/* 6 */	{ "extbl", "extwl", "extll", 0 },
332/* 7 */	{ 0, "inswh", "inslh", "insqh" },
333};
334
335static __inline const char *bitop_name(int);
336static __inline const char *
337bitop_name(op)
338	int op;
339{
340	static char unk[32];
341	const char *name = NULL;
342
343	if ((op & 0x70) == 0x30)
344		name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1];
345	else if ((op & 0xf) == 0x02)
346		name = bitop_c2[(op)>>4];
347	else
348		name =
349		    bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
350
351	if (name != NULL)
352		return (name);
353
354	snprintf(unk, sizeof unk, "?bit 0x%x?", op);
355	return (unk);
356}
357
358/*
359 * Only 5 entries in this one
360 */
361static const char *mul_opname[4] = {
362	"mull", "mulq", "mull/v", "mulq/v"
363};
364
365static __inline const char *mul_name(int);
366static __inline const char *
367mul_name(op)
368	int op;
369{
370	static char unk[32];
371	const char *name = NULL;
372
373	name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
374
375	if (name != NULL)
376		return (name);
377
378	snprintf(unk, sizeof unk, "?mul 0x%x?", op);
379	return (unk);
380}
381
382/*
383 * These are few, the high nibble is usually enough to dispatch.
384 * We single out the `f' case to halve the table size, as
385 * well as the cases in which the high nibble isn't enough.
386 */
387static const char *special_opname[8] = {
388	"trapb", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
389};
390
391static __inline const char *special_name(int);
392static __inline const char *
393special_name(op)
394	int op;
395{
396	static char unk[32];
397	const char *name;
398
399	switch (op) {
400	case op_excb:		name = "excb";		break;
401	case op_wmb:		name = "wmb";		break;
402	case op_ecb:		name = "ecb";		break;
403	case op_rs:		name = "rs";		break;
404	case op_wh64:		name = "wh64";		break;
405	default:
406		name = special_opname[(op)>>13];
407	}
408
409	if (name != NULL)
410		return (name);
411
412	snprintf(unk, sizeof unk, "?special 0x%x?", op);
413	return (unk);
414}
415
416/*
417 * This is trivial
418 */
419static const char *jump_opname[4] = {
420	"jmp", "jsr", "ret", "jcr"
421};
422#define jump_name(ix)	jump_opname[ix]
423
424/*
425 * For all but 4 of these, we can dispatch on the lower nibble of
426 * the "function".
427 */
428static const char *intmisc_opname_3x[16] = {
429	"ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb",
430	"pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8",
431	"maxuw4", "maxsb8", "maxsw4",
432};
433
434static __inline const char *intmisc_name(int);
435static __inline const char *
436intmisc_name(op)
437	int op;
438{
439	static char unk[32];
440
441	if ((op & 0xf0) == 0x30)
442		return (intmisc_opname_3x[op & 0x0f]);
443
444	switch (op) {
445	case op_sextb: return ("sextb");
446	case op_sextw: return ("sextw");
447	case op_ftoit: return ("ftoit");
448	case op_ftois: return ("ftois");
449	}
450
451	snprintf(unk, sizeof unk, "?intmisc 0x%x?", op);
452	return (unk);
453}
454
455static const char *float_name(const struct tbl[], int, const char *type);
456
457static const char *
458float_name(tbl, op, type)
459	const struct tbl tbl[];
460	int op;
461	const char *type;
462{
463	static char unk[32];
464	int i;
465
466	for (i = 0; tbl[i].name != NULL; i++) {
467		if (tbl[i].code == op)
468			return (tbl[i].name);
469	}
470
471	snprintf(unk, sizeof unk, "?%s 0x%x?", type, op);
472	return (unk);
473}
474
475#define vaxf_name(op)	float_name(vaxf_tbl, op, "vaxfl")
476#define ieeef_name(op)	float_name(ieeef_tbl, op, "ieeefl")
477#define anyf_name(op)	float_name(anyf_tbl, op, "anyfl")
478
479static const struct tbl anyf_tbl[] = {
480	{ "cvtlq",	0x010},
481	{ "cpys",	0x020},
482	{ "cpysn",	0x021},
483	{ "cpyse",	0x022},
484	{ "mt_fpcr",	0x024},
485	{ "mf_fpcr",	0x025},
486	{ "fcmoveq",	0x02a},
487	{ "fcmovne",	0x02b},
488	{ "fcmovlt",	0x02c},
489	{ "fcmovge",	0x02d},
490	{ "fcmovle",	0x02e},
491	{ "fcmovgt",	0x02f},
492	{ "cvtql",	0x030},
493	{ "cvtql/v",	0x130},
494	{ "cvtql/sv",	0x530},
495	{ 0, 0},
496};
497
498static const struct tbl ieeef_tbl[] = {
499	{ "adds/c",	0x000},
500	{ "subs/c",	0x001},
501	{ "muls/c",	0x002},
502	{ "divs/c",	0x003},
503	{ "addt/c",	0x020},
504	{ "subt/c",	0x021},
505	{ "mult/c",	0x022},
506	{ "divt/c",	0x023},
507	{ "cvtts/c",	0x02c},
508	{ "cvttq/c",	0x02f},
509	{ "cvtqs/c",	0x03c},
510	{ "cvtqt/c",	0x03e},
511	{ "adds/m",	0x040},
512	{ "subs/m",	0x041},
513	{ "muls/m",	0x042},
514	{ "divs/m",	0x043},
515	{ "addt/m",	0x060},
516	{ "subt/m",	0x061},
517	{ "mult/m",	0x062},
518	{ "divt/m",	0x063},
519	{ "cvtts/m",	0x06c},
520	{ "cvtqs/m",	0x07c},
521	{ "cvtqt/m",	0x07e},
522	{ "adds",	0x080},
523	{ "subs",	0x081},
524	{ "muls",	0x082},
525	{ "divs",	0x083},
526	{ "addt",	0x0a0},
527	{ "subt",	0x0a1},
528	{ "mult",	0x0a2},
529	{ "divt",	0x0a3},
530	{ "cmptun",	0x0a4},
531	{ "cmpteq",	0x0a5},
532	{ "cmptlt",	0x0a6},
533	{ "cmptle",	0x0a7},
534	{ "cvtts",	0x0ac},
535	{ "cvttq",	0x0af},
536	{ "cvtqs",	0x0bc},
537	{ "cvtqt",	0x0be},
538	{ "adds/d",	0x0c0},
539	{ "subs/d",	0x0c1},
540	{ "muls/d",	0x0c2},
541	{ "divs/d",	0x0c3},
542	{ "addt/d",	0x0e0},
543	{ "subt/d",	0x0e1},
544	{ "mult/d",	0x0e2},
545	{ "divt/d",	0x0e3},
546	{ "cvtts/d",	0x0ec},
547	{ "cvtqs/d",	0x0fc},
548	{ "cvtqt/d",	0x0fe},
549	{ "adds/uc",	0x100},
550	{ "subs/uc",	0x101},
551	{ "muls/uc",	0x102},
552	{ "divs/uc",	0x103},
553	{ "addt/uc",	0x120},
554	{ "subt/uc",	0x121},
555	{ "mult/uc",	0x122},
556	{ "divt/uc",	0x123},
557	{ "cvtts/uc",	0x12c},
558	{ "cvttq/vc",	0x12f},
559	{ "adds/um",	0x140},
560	{ "subs/um",	0x141},
561	{ "muls/um",	0x142},
562	{ "divs/um",	0x143},
563	{ "addt/um",	0x160},
564	{ "subt/um",	0x161},
565	{ "mult/um",	0x162},
566	{ "divt/um",	0x163},
567	{ "cvtts/um",	0x16c},
568	{ "adds/u",	0x180},
569	{ "subs/u",	0x181},
570	{ "muls/u",	0x182},
571	{ "divs/u",	0x183},
572	{ "addt/u",	0x1a0},
573	{ "subt/u",	0x1a1},
574	{ "mult/u",	0x1a2},
575	{ "divt/u",	0x1a3},
576	{ "cvtts/u",	0x1ac},
577	{ "cvttq/v",	0x1af},
578	{ "adds/ud",	0x1c0},
579	{ "subs/ud",	0x1c1},
580	{ "muls/ud",	0x1c2},
581	{ "divs/ud",	0x1c3},
582	{ "addt/ud",	0x1e0},
583	{ "subt/ud",	0x1e1},
584	{ "mult/ud",	0x1e2},
585	{ "divt/ud",	0x1e3},
586	{ "cvtts/ud",	0x1ec},
587	{ "adds/suc",	0x500},
588	{ "subs/suc",	0x501},
589	{ "muls/suc",	0x502},
590	{ "divs/suc",	0x503},
591	{ "addt/suc",	0x520},
592	{ "subt/suc",	0x521},
593	{ "mult/suc",	0x522},
594	{ "divt/suc",	0x523},
595	{ "cvtts/suc",	0x52c},
596	{ "cvttq/svc",	0x52f},
597	{ "adds/sum",	0x540},
598	{ "subs/sum",	0x541},
599	{ "muls/sum",	0x542},
600	{ "divs/sum",	0x543},
601	{ "addt/sum",	0x560},
602	{ "subt/sum",	0x561},
603	{ "mult/sum",	0x562},
604	{ "divt/sum",	0x563},
605	{ "cvtts/sum",	0x56c},
606	{ "adds/su",	0x580},
607	{ "subs/su",	0x581},
608	{ "muls/su",	0x582},
609	{ "divs/su",	0x583},
610	{ "addt/su",	0x5a0},
611	{ "subt/su",	0x5a1},
612	{ "mult/su",	0x5a2},
613	{ "divt/su",	0x5a3},
614	{ "cmptun/su",	0x5a4},
615	{ "cmpteq/su",	0x5a5},
616	{ "cmptlt/su",	0x5a6},
617	{ "cmptle/su",	0x5a7},
618	{ "cvtts/su",	0x5ac},
619	{ "cvttq/sv",	0x5af},
620	{ "adds/sud",	0x5c0},
621	{ "subs/sud",	0x5c1},
622	{ "muls/sud",	0x5c2},
623	{ "divs/sud",	0x5c3},
624	{ "addt/sud",	0x5e0},
625	{ "subt/sud",	0x5e1},
626	{ "mult/sud",	0x5e2},
627	{ "divt/sud",	0x5e3},
628	{ "cvtts/sud",	0x5ec},
629	{ "adds/suic",	0x700},
630	{ "subs/suic",	0x701},
631	{ "muls/suic",	0x702},
632	{ "divs/suic",	0x703},
633	{ "addt/suic",	0x720},
634	{ "subt/suic",	0x721},
635	{ "mult/suic",	0x722},
636	{ "divt/suic",	0x723},
637	{ "cvtts/suic",	0x72c},
638	{ "cvttq/svic",	0x72f},
639	{ "cvtqs/suic",	0x73c},
640	{ "cvtqt/suic",	0x73e},
641	{ "adds/suim",	0x740},
642	{ "subs/suim",	0x741},
643	{ "muls/suim",	0x742},
644	{ "divs/suim",	0x743},
645	{ "addt/suim",	0x760},
646	{ "subt/suim",	0x761},
647	{ "mult/suim",	0x762},
648	{ "divt/suim",	0x763},
649	{ "cvtts/suim",	0x76c},
650	{ "cvtqs/suim",	0x77c},
651	{ "cvtqt/suim",	0x77e},
652	{ "adds/sui",	0x780},
653	{ "subs/sui",	0x781},
654	{ "muls/sui",	0x782},
655	{ "divs/sui",	0x783},
656	{ "addt/sui",	0x7a0},
657	{ "subt/sui",	0x7a1},
658	{ "mult/sui",	0x7a2},
659	{ "divt/sui",	0x7a3},
660	{ "cvtts/sui",	0x7ac},
661	{ "cvttq/svi",	0x7af},
662	{ "cvtqs/sui",	0x7bc},
663	{ "cvtqt/sui",	0x7be},
664	{ "adds/suid",	0x7c0},
665	{ "subs/suid",	0x7c1},
666	{ "muls/suid",	0x7c2},
667	{ "divs/suid",	0x7c3},
668	{ "addt/suid",	0x7e0},
669	{ "subt/suid",	0x7e1},
670	{ "mult/suid",	0x7e2},
671	{ "divt/suid",	0x7e3},
672	{ "cvtts/suid",	0x7ec},
673	{ "cvtqs/suid",	0x7fc},
674	{ "cvtqt/suid",	0x7fe},
675	{ 0, 0}
676};
677
678static const struct tbl vaxf_tbl[] = {
679	{ "addf/c",	0x000},
680	{ "subf/c",	0x001},
681	{ "mulf/c",	0x002},
682	{ "divf/c",	0x003},
683	{ "cvtdg/c",	0x01e},
684	{ "addg/c",	0x020},
685	{ "subg/c",	0x021},
686	{ "mulg/c",	0x022},
687	{ "divg/c",	0x023},
688	{ "cvtgf/c",	0x02c},
689	{ "cvtgd/c",	0x02d},
690	{ "cvtgq/c",	0x02f},
691	{ "cvtqf/c",	0x03c},
692	{ "cvtqg/c",	0x03e},
693	{ "addf",	0x080},
694	{ "subf",	0x081},
695	{ "mulf",	0x082},
696	{ "divf",	0x083},
697	{ "cvtdg",	0x09e},
698	{ "addg",	0x0a0},
699	{ "subg",	0x0a1},
700	{ "mulg",	0x0a2},
701	{ "divg",	0x0a3},
702	{ "cmpgeq",	0x0a5},
703	{ "cmpglt",	0x0a6},
704	{ "cmpgle",	0x0a7},
705	{ "cvtgf",	0x0ac},
706	{ "cvtgd",	0x0ad},
707	{ "cvtgq",	0x0af},
708	{ "cvtqf",	0x0bc},
709	{ "cvtqg",	0x0be},
710	{ "addf/uc",	0x100},
711	{ "subf/uc",	0x101},
712	{ "mulf/uc",	0x102},
713	{ "divf/uc",	0x103},
714	{ "cvtdg/uc",	0x11e},
715	{ "addg/uc",	0x120},
716	{ "subg/uc",	0x121},
717	{ "mulg/uc",	0x122},
718	{ "divg/uc",	0x123},
719	{ "cvtgf/uc",	0x12c},
720	{ "cvtgd/uc",	0x12d},
721	{ "cvtgq/vc",	0x12f},
722	{ "addf/u",	0x180},
723	{ "subf/u",	0x181},
724	{ "mulf/u",	0x182},
725	{ "divf/u",	0x183},
726	{ "cvtdg/u",	0x19e},
727	{ "addg/u",	0x1a0},
728	{ "subg/u",	0x1a1},
729	{ "mulg/u",	0x1a2},
730	{ "divg/u",	0x1a3},
731	{ "cvtgf/u",	0x1ac},
732	{ "cvtgd/u",	0x1ad},
733	{ "cvtgq/v",	0x1af},
734	{ "addf/sc",	0x400},
735	{ "subf/sc",	0x401},
736	{ "mulf/sc",	0x402},
737	{ "divf/sc",	0x403},
738	{ "cvtdg/sc",	0x41e},
739	{ "addg/sc",	0x420},
740	{ "subg/sc",	0x421},
741	{ "mulg/sc",	0x422},
742	{ "divg/sc",	0x423},
743	{ "cvtgf/sc",	0x42c},
744	{ "cvtgd/sc",	0x42d},
745	{ "cvtgq/sc",	0x42f},
746	{ "cvtqf/sc",	0x43c},
747	{ "cvtqg/sc",	0x43e},
748	{ "addf/s",	0x480},
749	{ "subf/s",	0x481},
750	{ "mulf/s",	0x482},
751	{ "divf/s",	0x483},
752	{ "cvtdg/s",	0x49e},
753	{ "addg/s",	0x4a0},
754	{ "subg/s",	0x4a1},
755	{ "mulg/s",	0x4a2},
756	{ "divg/s",	0x4a3},
757	{ "cmpgeq/s",	0x4a5},
758	{ "cmpglt/s",	0x4a6},
759	{ "cmpgle/s",	0x4a7},
760	{ "cvtgf/s",	0x4ac},
761	{ "cvtgd/s",	0x4ad},
762	{ "cvtgq/s",	0x4af},
763	{ "cvtqf/s",	0x4bc},
764	{ "cvtqg/s",	0x4be},
765	{ "addf/suc",	0x500},
766	{ "subf/suc",	0x501},
767	{ "mulf/suc",	0x502},
768	{ "divf/suc",	0x503},
769	{ "cvtdg/suc",	0x51e},
770	{ "addg/suc",	0x520},
771	{ "subg/suc",	0x521},
772	{ "mulg/suc",	0x522},
773	{ "divg/suc",	0x523},
774	{ "cvtgf/suc",	0x52c},
775	{ "cvtgd/suc",	0x52d},
776	{ "cvtgq/svc",	0x52f},
777	{ "addf/su",	0x580},
778	{ "subf/su",	0x581},
779	{ "mulf/su",	0x582},
780	{ "divf/su",	0x583},
781	{ "cvtdg/su",	0x59e},
782	{ "addg/su",	0x5a0},
783	{ "subg/su",	0x5a1},
784	{ "mulg/su",	0x5a2},
785	{ "divg/su",	0x5a3},
786	{ "cvtgf/su",	0x5ac},
787	{ "cvtgd/su",	0x5ad},
788	{ "cvtgq/sv",	0x5af},
789	{ 0, 0}
790};
791
792/*
793 * General purpose registers
794 */
795static const char *name_of_register[32] = {
796	"v0",	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",
797	"t7",	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",
798	"a0",	"a1",	"a2",	"a3",	"a4",	"a5",	"t8",	"t9",
799	"t10",	"t11",	"ra",	"pv",	"at",	"gp",	"sp",	"zero"
800};
801
802static int regcount;		/* how many regs used in this inst */
803static int regnum[3];		/* which regs used in this inst */
804
805static const char *register_name(int);
806
807static const char *
808register_name (ireg)
809	int ireg;
810{
811	int	i;
812
813	for (i = 0; i < regcount; i++)
814		if (regnum[i] == ireg)
815			break;
816	if (i >= regcount)
817		regnum[regcount++] = ireg;
818	return (name_of_register[ireg]);
819}
820
821/*
822 * Disassemble instruction at 'loc'.  'altfmt' specifies an
823 * (optional) alternate format.  Return address of start of
824 * next instruction.
825 */
826int	alpha_print_instruction(vaddr_t, alpha_instruction, int);
827
828vaddr_t
829db_disasm(vaddr_t loc, int altfmt)
830{
831	alpha_instruction inst;
832
833	inst.bits = db_get_value(loc, 4, 0);
834
835	loc += alpha_print_instruction(loc, inst, altfmt);
836	return (loc);
837}
838
839int
840alpha_print_instruction(vaddr_t iadr, alpha_instruction i, int showregs)
841{
842	const char	*opcode;
843	int		ireg;
844	long		signed_immediate;
845	int		fstore;
846	pal_instruction	p;
847	char		tmpfmt[28];
848
849	regcount = 0;
850	fstore = 0;
851	opcode = op_name[i.mem_format.opcode];
852
853	/*
854	 *	Dispatch directly on the opcode, save code
855	 *	duplication sometimes via "harmless gotos".
856	 */
857	switch (i.mem_format.opcode) {
858	case op_pal:
859		/* "call_pal" is a long string; just use a space. */
860		db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
861		break;
862	case op_lda:
863	case op_ldah:
864	case op_ldbu:
865	case op_ldq_u:
866	case op_ldwu:
867	case op_stw:
868	case op_stb:
869	case op_stq_u:
870		/*
871		 * These loadstores are here to make compiling the
872		 * switch a bit easier.  Could embellish the output
873		 * someday, too.
874		 */
875		goto loadstore;
876		break;
877	case op_arit:
878		/*
879		 * For this and the following three groups we
880		 * just need different opcode strings
881		 */
882		opcode = arit_name(i.operate_lit_format.function);
883		goto operate;
884		break;
885	case op_logical:
886		opcode = logical_name(i.operate_lit_format.function);
887		goto operate;
888		break;
889	case op_bit:
890		opcode = bitop_name(i.operate_lit_format.function);
891		goto operate;
892		break;
893	case op_mul:
894		opcode = mul_name(i.operate_lit_format.function);
895operate:
896		/*
897		 * Nice and uniform, just check for literals
898		 */
899		db_printf("%s\t%s,", opcode,
900		    register_name(i.operate_lit_format.ra));
901		if (i.operate_lit_format.one)
902			db_printf("#0x%x", i.operate_lit_format.literal);
903		else
904			db_printf("%s", register_name(i.operate_reg_format.rb));
905		db_printf(",%s", register_name(i.operate_lit_format.rc));
906		break;
907	case op_vax_float:
908		/*
909		 * The three floating point groups are even simpler
910		 */
911		opcode = vaxf_name(i.float_format.function);
912		goto foperate;
913		break;
914	case op_ieee_float:
915		opcode = ieeef_name(i.float_format.function);
916		goto foperate;
917		break;
918	case op_any_float:
919		opcode = anyf_name(i.float_format.function);
920foperate:
921		db_printf("%s\tf%d,f%d,f%d", opcode,
922			i.float_format.fa,
923			i.float_format.fb,
924			i.float_format.fc);
925		break;
926	case op_special:
927		/*
928		 * Miscellaneous.
929		 */
930		{
931			register unsigned int code;
932
933			code = (i.mem_format.displacement)&0xffff;
934			opcode = special_name(code);
935
936			switch (code) {
937			case op_ecb:
938				db_printf("%s\t(%s)", opcode,
939					register_name(i.mem_format.rb));
940				break;
941			case op_fetch:
942			case op_fetch_m:
943				db_printf("%s\t0(%s)", opcode,
944					register_name(i.mem_format.rb));
945				break;
946			case op_rpcc:
947			case op_rc:
948			case op_rs:
949				db_printf("%s\t%s", opcode,
950					register_name(i.mem_format.ra));
951				break;
952			default:
953				db_printf("%s", opcode);
954			break;
955			}
956		}
957		break;
958	case op_j:
959		/*
960		 * Jump instructions really are of two sorts,
961		 * depending on the use of the hint info.
962		 */
963		opcode = jump_name(i.jump_format.action);
964		switch (i.jump_format.action) {
965		case op_jmp:
966		case op_jsr:
967			db_printf("%s\t%s,(%s),", opcode,
968				register_name(i.jump_format.ra),
969				register_name(i.jump_format.rb));
970			signed_immediate = i.jump_format.hint;
971			goto branch_displacement;
972			break;
973		case op_ret:
974		case op_jcr:
975			db_printf("%s\t%s,(%s)", opcode,
976				register_name(i.jump_format.ra),
977				register_name(i.jump_format.rb));
978			break;
979		}
980		break;
981	case op_intmisc:
982		/*
983		 * These are just in "operate" format.
984		 */
985		opcode = intmisc_name(i.operate_lit_format.function);
986		goto operate;
987		break;
988			/* HW instructions, possibly chip-specific XXXX */
989	case op_pal19:	/* "hw_mfpr" */
990	case op_pal1d:	/* "hw_mtpr" */
991		p.bits = i.bits;
992		db_printf("\t%s%s\t%s, %d", opcode,
993			mXpr_name[p.mXpr_format.regset],
994			register_name(p.mXpr_format.rd),
995			p.mXpr_format.index);
996		break;
997	case op_pal1b:	/* "hw_ld" */
998	case op_pal1f:	/* "hw_st" */
999		p.bits = i.bits;
1000		db_printf("\t%s%c%s\t%s,", opcode,
1001			(p.mem_format.qw) ? 'q' : 'l',
1002			hwlds_name[p.mem_format.qualif],
1003			register_name(p.mem_format.rd));
1004		signed_immediate = (long)p.mem_format.displacement;
1005		goto loadstore_address;
1006
1007	case op_pal1e:	/* "hw_rei" */
1008		db_printf("\t%s", opcode);
1009		break;
1010
1011	case op_ldf:
1012	case op_ldg:
1013	case op_lds:
1014	case op_ldt:
1015	case op_stf:
1016	case op_stg:
1017	case op_sts:
1018	case op_stt:
1019		fstore = 1;
1020		/* FALLTHROUGH */
1021	case op_ldl:
1022	case op_ldq:
1023	case op_ldl_l:
1024	case op_ldq_l:
1025	case op_stl:
1026	case op_stq:
1027	case op_stl_c:
1028	case op_stq_c:
1029		/*
1030		 * Memory operations, including floats
1031		 */
1032loadstore:
1033		if (fstore)
1034		    db_printf("%s\tf%d,", opcode, i.mem_format.ra);
1035		else
1036		    db_printf("%s\t%s,", opcode,
1037		        register_name(i.mem_format.ra));
1038		signed_immediate = (long)i.mem_format.displacement;
1039loadstore_address:
1040		db_printf("%s(%s)", db_format(tmpfmt, sizeof tmpfmt,
1041		    signed_immediate, DB_FORMAT_Z, 0, 0),
1042		    register_name(i.mem_format.rb));
1043		/*
1044		 * For convenience, do the address computation
1045		 */
1046		if (showregs) {
1047			if (i.mem_format.opcode == op_ldah)
1048				signed_immediate <<= 16;
1049			db_printf(" <0x%lx>", signed_immediate +
1050			    db_register_value(&ddb_regs, i.mem_format.rb));
1051		}
1052		break;
1053	case op_br:
1054	case op_fbeq:
1055	case op_fblt:
1056	case op_fble:
1057	case op_bsr:
1058	case op_fbne:
1059	case op_fbge:
1060	case op_fbgt:
1061	case op_blbc:
1062	case op_beq:
1063	case op_blt:
1064	case op_ble:
1065	case op_blbs:
1066	case op_bne:
1067	case op_bge:
1068	case op_bgt:
1069		/*
1070		 * We want to know where we are branching to
1071		 */
1072		signed_immediate = (long)i.branch_format.displacement;
1073		db_printf("%s\t%s,", opcode,
1074			  register_name(i.branch_format.ra));
1075branch_displacement:
1076		db_printsym(iadr + sizeof(alpha_instruction) +
1077		    (signed_immediate << 2), DB_STGY_PROC, db_printf);
1078		break;
1079	default:
1080		/*
1081		 * Shouldn't happen
1082		 */
1083		db_printf("? 0x%x ?", i.bits);
1084	}
1085
1086	/*
1087	 *	Print out the registers used in this instruction
1088	 */
1089	if (showregs && regcount > 0) {
1090		db_printf("\t<");
1091		for (ireg = 0; ireg < regcount; ireg++) {
1092			if (ireg != 0)
1093				db_printf(",");
1094			db_printf("%s=0x%lx",
1095			    name_of_register[regnum[ireg]],
1096			    db_register_value(&ddb_regs, regnum[ireg]));
1097		}
1098		db_printf(">");
1099	}
1100	db_printf("\n");
1101	return (sizeof(alpha_instruction));
1102}
1103