xref: /openbsd/sys/arch/alpha/alpha/db_disasm.c (revision e7c2d835)
1 /* $OpenBSD: db_disasm.c,v 1.26 2024/06/22 10:22:29 jsg 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  */
68 typedef 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  */
128 static 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 
145 struct tbl {
146 	const char	*name;
147 	int		code;
148 };
149 
150 static 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 
189 static const char *pal_opname(int);
190 
191 static const char *
pal_opname(op)192 pal_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 */
208 static const char *mXpr_name[8] = {
209 	"", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
210 };
211 static 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  */
223 static const char *arit_c0[8] = {
224 	"addl", 0, "addq", 0, "addl/v", 0, "addq/v",
225 };
226 static const char *arit_c2[8] = {
227 	"s4addl", "s8addl", "s4addq", "s8addq",
228 };
229 static const char *arit_c9[8] = {
230 	"subl", 0, "subq", 0, "subl/v", 0, "subq/v",
231 };
232 static const char *arit_cB[8] = {
233 	"s4subl", "s8subl", "s4subq", "s8subq",
234 };
235 static const char *arit_cD[8] = {
236 	0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
237 };
238 static const char *arit_cF[1] = {
239 	"cmpbge"
240 };
241 static const char **arit_opname[8] = {
242 	arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
243 };
244 
245 static __inline const char *arit_name(int);
246 static __inline const char *
arit_name(op)247 arit_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  */
273 static const char *logical_c0[4] = {
274 	"and", "or", "xor", 0
275 };
276 static const char *logical_c4[4] = {
277 	"cmovlbs", "cmoveq", "cmovlt", "cmovle"
278 };
279 static const char *logical_c6[4] = {
280 	"cmovlbc", "cmovne", "cmovge", "cmovgt"
281 };
282 static const char *logical_c8[4] = {
283 	"andnot", "ornot", "xornot", 0
284 };
285 
286 static __inline const char *logical_name(int);
287 static __inline const char *
logical_name(op)288 logical_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  */
322 static const char *bitop_c3[8] = {
323 	"zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
324 };
325 static const char *bitop_c2[8] = {
326 	"mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
327 };
328 static 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 
335 static __inline const char *bitop_name(int);
336 static __inline const char *
bitop_name(op)337 bitop_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  */
361 static const char *mul_opname[4] = {
362 	"mull", "mulq", "mull/v", "mulq/v"
363 };
364 
365 static __inline const char *mul_name(int);
366 static __inline const char *
mul_name(op)367 mul_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  */
387 static const char *special_opname[8] = {
388 	"trapb", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
389 };
390 
391 static __inline const char *special_name(int);
392 static __inline const char *
special_name(op)393 special_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  */
419 static 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  */
428 static 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 
434 static __inline const char *intmisc_name(int);
435 static __inline const char *
intmisc_name(op)436 intmisc_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 
455 static const char *float_name(const struct tbl[], int, const char *type);
456 
457 static const char *
float_name(tbl,op,type)458 float_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 
479 static 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 
498 static 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 
678 static 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  */
795 static 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 
802 static int regcount;		/* how many regs used in this inst */
803 static int regnum[3];		/* which regs used in this inst */
804 
805 static const char *register_name(int);
806 
807 static const char *
register_name(ireg)808 register_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  */
826 int	alpha_print_instruction(vaddr_t, alpha_instruction, int);
827 
828 vaddr_t
db_disasm(vaddr_t loc,int altfmt)829 db_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 
839 int
alpha_print_instruction(vaddr_t iadr,alpha_instruction i,int showregs)840 alpha_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);
895 operate:
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);
920 foperate:
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 		 */
1032 loadstore:
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;
1039 loadstore_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));
1075 branch_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