1 /* $NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $ */
4 * Mach Operating System
5 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
31 * Author: Alessandro Forin, Carnegie Mellon University
34 * Disassembler for Alpha
36 * Modified for NetBSD/alpha by:
38 * Christopher G. Demetriou, Carnegie Mellon University
40 * Jason R. Thorpe, Numerical Aerospace Simulation Facility,
41 * NASA Ames Research Center
43 * This code was derived exclusively from information available in
44 * "Alpha Architecture Reference Manual", Richard L. Sites ed.
45 * Digital Press, Burlington, MA 01803
46 * ISBN 1-55558-098-X, Order no. EY-L520E-DP
49 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
51 /* __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $"); */
53 #include <sys/param.h>
54 #include <sys/systm.h>
56 #include <machine/db_machdep.h>
57 #include <alpha/alpha/db_instruction.h>
59 #include <machine/pal.h>
62 #include <ddb/db_access.h>
63 #include <ddb/db_sym.h>
64 #include <ddb/db_output.h>
67 * This would belong in a header file, except noone else needs it
71 * All instructions are 32 bits wide, PAL included
76 * Internal processor register access instrs
77 * specify the IPR index, doubly specify the
78 * (same) GP register as src/dest, and qualifiers
79 * for the IPR set involved (abox/ibox/tmp)
83 regset : 3, /* a,i,p */
91 * Load/store instructions have a 12 bit displacement,
92 * and two register specifiers just as normal ld/st.
93 * Four bits have special meanings:
94 * phy: bypass the MMU (physical access)
95 * alt: use mode in ALT register for checks,
96 * or if PHY is also on locked/linked access
97 * rwc: read-with-write-check (probew)
101 signed int displacement : 12;
110 * Return from exception or interrupt has
111 * a branch-like encoding, but only one
112 * instantiation is actually usable.
116 zero : 1, /* branch prediction! */
118 rb : 5, /* r31 or stall */
119 ra : 5, /* r31 or stall */
129 static char *op_name[64] = {
130 /* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5", "op6", "op7",
131 /* 8 */ "lda", "ldah", "ldbu", "ldq_u","ldwu", "stw", "stb", "stq_u",
132 /*16 */ "arit", "logical","bit","mul", "op20", "vaxf", "ieeef","anyf",
133 /*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st",
134 /*32 */ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt",
135 /*40 */ "ldl", "ldq", "ldl_l","ldq_l","stl", "stq", "stl_c","stq_c",
136 /*48 */ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt",
137 /*56 */ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt"
141 * The function field is too big (7 or 11 bits), so the sub-tables
142 * are addressed in a somewhat complicated manner to save
143 * space. After all, alu operations is what RISCs are good at.
151 static const struct tbl pal_op_tbl[] = {
152 /* Common PAL function codes. */
153 { "halt", PAL_halt },
154 { "cflush", PAL_cflush },
155 { "draina", PAL_draina },
156 { "cserve", PAL_cserve, },
157 { "swppal", PAL_swppal },
158 { "ipir", PAL_ipir },
160 { "bugchk", PAL_bugchk },
162 { "rdunique", PAL_rdunique },
163 { "wrunique", PAL_wrunique },
164 { "gentrap", PAL_gentrap },
166 /* OSF/1 PAL function codes. */
167 { "osf1_rdmces", PAL_OSF1_rdmces },
168 { "osf1_wrmces", PAL_OSF1_wrmces },
169 { "osf1_wrfen", PAL_OSF1_wrfen },
170 { "osf1_wrvptptr", PAL_OSF1_wrvptptr },
171 { "osf1_swpctx", PAL_OSF1_swpctx },
172 { "osf1_wrval", PAL_OSF1_wrval },
173 { "osf1_rdval", PAL_OSF1_rdval },
174 { "osf1_tbi", PAL_OSF1_tbi },
175 { "osf1_wrent", PAL_OSF1_wrent },
176 { "osf1_swpipl", PAL_OSF1_swpipl },
177 { "osf1_rdps", PAL_OSF1_rdps },
178 { "osf1_wrkgp", PAL_OSF1_wrkgp },
179 { "osf1_wrusp", PAL_OSF1_wrusp },
180 { "osf1_wrperfmon", PAL_OSF1_wrperfmon },
181 { "osf1_rdusp", PAL_OSF1_rdusp },
182 { "osf1_whami", PAL_OSF1_whami },
183 { "osf1_retsys", PAL_OSF1_retsys },
184 { "osf1_rti", PAL_OSF1_rti },
185 { "osf1_callsys", PAL_OSF1_callsys },
190 static const char *pal_opname __P((int));
199 for (i = 0; pal_op_tbl[i].name != NULL; i++) {
200 if (pal_op_tbl[i].code == op)
201 return (pal_op_tbl[i].name);
204 snprintf(unk, sizeof(unk), "0x%x", op);
208 /* HW (PAL) instruction qualifiers, stright tables */
209 static const char *mXpr_name[8] = {
210 "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
212 static const char *hwlds_name[8] = {
213 "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
217 * For this one we take the low nibble (valid values 0/2/9/b/d)
218 * and shift it down one to get the row index. Within a row
219 * we can just take the high nibble deprived of the high bit
220 * (valid values 0/1/2/3/4/6). We could have used a flat 64
221 * entry array, but in this way we use just 48 pointers.
222 * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too
224 static const char *arit_c0[8] = {
225 "addl", 0, "addq", 0, "addl/v", 0, "addq/v",
227 static const char *arit_c2[8] = {
228 "s4addl", "s8addl", "s4addq", "s8addq",
230 static const char *arit_c9[8] = {
231 "subl", 0, "subq", 0, "subl/v", 0, "subq/v",
233 static const char *arit_cB[8] = {
234 "s4subl", "s8subl", "s4subq", "s8subq",
236 static const char *arit_cD[8] = {
237 0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
239 static const char *arit_cF[1] = {
242 static const char **arit_opname[8] = {
243 arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
246 static __inline const char *arit_name __P((int));
247 static __inline const char *
252 const char *name = NULL;
254 if (arit_opname[((op)&0xe)>>1])
255 name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
260 snprintf(unk, sizeof(unk), "?arit 0x%x?", op);
265 * Something similar for this one, except there are only
266 * 16 entries so the row indexing is done by enumeration
267 * of the low nibble (valid values 0/4/6/8). Then we can
268 * just shift the high nibble to index inside the row
269 * (valid values are 0/2/4 or 1/2/4/6)
271 * There are two functions that don't play by these simple rules,
272 * so we special-case them.
274 static const char *logical_c0[4] = {
275 "and", "or", "xor", 0
277 static const char *logical_c4[4] = {
278 "cmovlbs", "cmoveq", "cmovlt", "cmovle"
280 static const char *logical_c6[4] = {
281 "cmovlbc", "cmovne", "cmovge", "cmovgt"
283 static const char *logical_c8[4] = {
284 "andnot", "ornot", "xornot", 0
287 static __inline const char *logical_name __P((int));
288 static __inline const char *
293 const char *name = NULL;
297 else if (op == op_implver)
301 case 0: name = logical_c0[((op)>>5)&3]; break;
302 case 4: name = logical_c4[((op)>>5)&3]; break;
303 case 6: name = logical_c6[((op)>>5)&3]; break;
304 case 8: name = logical_c8[((op)>>5)&3]; break;
310 snprintf(unk, sizeof(unk), "?logical 0x%x?", op);
315 * This is the messy one. First, we single out the dense
316 * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c).
317 * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7).
318 * For the remaining codes (6/7/a/b) we do as above: high
319 * nibble has valid values 0/1/2 or 5/6/7. The low nibble
320 * can be used as row index picking bits 0 and 2, for the
321 * high one just the lower two bits.
323 static const char *bitop_c3[8] = {
324 "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
326 static const char *bitop_c2[8] = {
327 "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
329 static const char *bitop_c67ab[4][4] = {
330 /* a */ { 0, "extwh", "extlh", "extqh"},
331 /* b */ { "insbl", "inswl", "insll", 0 },
332 /* 6 */ { "extbl", "extwl", "extll", 0 },
333 /* 7 */ { 0, "inswh", "inslh", "insqh" },
336 static __inline const char *bitop_name __P((int));
337 static __inline const char *
342 const char *name = NULL;
344 if ((op & 0x70) == 0x30)
345 name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1];
346 else if ((op & 0xf) == 0x02)
347 name = bitop_c2[(op)>>4];
350 bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
355 snprintf(unk, sizeof(unk), "?bit 0x%x?", op);
360 * Only 5 entries in this one
362 static const char *mul_opname[4] = {
363 "mull", "mulq", "mull/v", "mulq/v"
366 static __inline const char *mul_name __P((int));
367 static __inline const char *
372 const char *name = NULL;
374 name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
379 snprintf(unk, sizeof(unk), "?mul 0x%x?", op);
384 * These are few, the high nibble is enough to dispatch.
385 * We single out the "f" case to halve the table size.
387 static const char *special_opname[8] = {
388 "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
391 static __inline const char *special_name __P((int));
392 static __inline const char *
399 name = (op == op_rs) ? "rs" : special_opname[(op)>>13];
404 snprintf(unk, sizeof(unk), "?special 0x%x?", op);
411 static const char *jump_opname[4] = {
412 "jmp", "jsr", "ret", "jcr"
414 #define jump_name(ix) jump_opname[ix]
417 * For all but 4 of these, we can dispatch on the lower nibble of
420 static const char *intmisc_opname_3x[16] = {
421 "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb",
422 "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8",
423 "maxuw4", "maxsb8", "maxsw4",
426 static __inline const char *intmisc_name __P((int));
427 static __inline const char *
433 if ((op & 0xf0) == 0x30)
434 return (intmisc_opname_3x[op & 0x0f]);
437 case op_sextb: return ("sextb");
438 case op_sextw: return ("sextw");
439 case op_ftoit: return ("ftoit");
440 case op_ftois: return ("ftois");
443 snprintf(unk, sizeof(unk), "?intmisc 0x%x?", op);
447 static const char *float_name __P((const struct tbl[], int, const char *type));
450 float_name(tbl, op, type)
451 const struct tbl tbl[];
458 for (i = 0; tbl[i].name != NULL; i++) {
459 if (tbl[i].code == op)
460 return (tbl[i].name);
463 snprintf(unk, sizeof(unk), "?%s 0x%x?", type, op);
467 #define vaxf_name(op) float_name(vaxf_tbl, op, "vaxfl")
468 #define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl")
469 #define anyf_name(op) float_name(anyf_tbl, op, "anyfl")
471 static const struct tbl anyf_tbl[] = {
486 { "cvtql/sv", 0x330},
490 static const struct tbl ieeef_tbl[] = {
549 { "cvtts/uc", 0x12c},
550 { "cvttq/vc", 0x12f},
559 { "cvtts/um", 0x16c},
578 { "cvtts/ud", 0x1ec},
579 { "adds/suc", 0x500},
580 { "subs/suc", 0x501},
581 { "muls/suc", 0x502},
582 { "divs/suc", 0x503},
583 { "addt/suc", 0x520},
584 { "subt/suc", 0x521},
585 { "mult/suc", 0x522},
586 { "divt/suc", 0x523},
587 { "cvtts/suc", 0x52c},
588 { "cvttq/svc", 0x52f},
589 { "adds/sum", 0x540},
590 { "subs/sum", 0x541},
591 { "muls/sum", 0x542},
592 { "divs/sum", 0x543},
593 { "addt/sum", 0x560},
594 { "subt/sum", 0x561},
595 { "mult/sum", 0x562},
596 { "divt/sum", 0x563},
597 { "cvtts/sum", 0x56c},
606 { "cmptun/su", 0x5a4},
607 { "cmpteq/su", 0x5a5},
608 { "cmptlt/su", 0x5a6},
609 { "cmptle/su", 0x5a7},
610 { "cvtts/su", 0x5ac},
611 { "cvttq/sv", 0x5af},
612 { "adds/sud", 0x5c0},
613 { "subs/sud", 0x5c1},
614 { "muls/sud", 0x5c2},
615 { "divs/sud", 0x5c3},
616 { "addt/sud", 0x5e0},
617 { "subt/sud", 0x5e1},
618 { "mult/sud", 0x5e2},
619 { "divt/sud", 0x5e3},
620 { "cvtts/sud", 0x5ec},
621 { "adds/suic", 0x700},
622 { "subs/suic", 0x701},
623 { "muls/suic", 0x702},
624 { "divs/suic", 0x703},
625 { "addt/suic", 0x720},
626 { "subt/suic", 0x721},
627 { "mult/suic", 0x722},
628 { "divt/suic", 0x723},
629 { "cvtts/suic", 0x72c},
630 { "cvttq/svic", 0x72f},
631 { "cvtqs/suic", 0x73c},
632 { "cvtqt/suic", 0x73e},
633 { "adds/suim", 0x740},
634 { "subs/suim", 0x741},
635 { "muls/suim", 0x742},
636 { "divs/suim", 0x743},
637 { "addt/suim", 0x760},
638 { "subt/suim", 0x761},
639 { "mult/suim", 0x762},
640 { "divt/suim", 0x763},
641 { "cvtts/suim", 0x76c},
642 { "cvtqs/suim", 0x77c},
643 { "cvtqt/suim", 0x77e},
644 { "adds/sui", 0x780},
645 { "subs/sui", 0x781},
646 { "muls/sui", 0x782},
647 { "divs/sui", 0x783},
648 { "addt/sui", 0x7a0},
649 { "subt/sui", 0x7a1},
650 { "mult/sui", 0x7a2},
651 { "divt/sui", 0x7a3},
652 { "cvtts/sui", 0x7ac},
653 { "cvttq/svi", 0x7af},
654 { "cvtqs/sui", 0x7bc},
655 { "cvtqt/sui", 0x7be},
656 { "adds/suid", 0x7c0},
657 { "subs/suid", 0x7c1},
658 { "muls/suid", 0x7c2},
659 { "divs/suid", 0x7c3},
660 { "addt/suid", 0x7e0},
661 { "subt/suid", 0x7e1},
662 { "mult/suid", 0x7e2},
663 { "divt/suid", 0x7e3},
664 { "cvtts/suid", 0x7ec},
665 { "cvtqs/suid", 0x7fc},
666 { "cvtqt/suid", 0x7fe},
670 static const struct tbl vaxf_tbl[] = {
706 { "cvtdg/uc", 0x11e},
711 { "cvtgf/uc", 0x12c},
712 { "cvtgd/uc", 0x12d},
713 { "cvtgq/vc", 0x12f},
730 { "cvtdg/sc", 0x41e},
735 { "cvtgf/sc", 0x42c},
736 { "cvtgd/sc", 0x42d},
737 { "cvtgq/sc", 0x42f},
738 { "cvtqf/sc", 0x43c},
739 { "cvtqg/sc", 0x43e},
749 { "cmpgeq/s", 0x4a5},
750 { "cmpglt/s", 0x4a6},
751 { "cmpgle/s", 0x4a7},
757 { "addf/suc", 0x500},
758 { "subf/suc", 0x501},
759 { "mulf/suc", 0x502},
760 { "divf/suc", 0x503},
761 { "cvtdg/suc", 0x51e},
762 { "addg/suc", 0x520},
763 { "subg/suc", 0x521},
764 { "mulg/suc", 0x522},
765 { "divg/suc", 0x523},
766 { "cvtgf/suc", 0x52c},
767 { "cvtgd/suc", 0x52d},
768 { "cvtgq/svc", 0x52f},
773 { "cvtdg/su", 0x59e},
778 { "cvtgf/su", 0x5ac},
779 { "cvtgd/su", 0x5ad},
780 { "cvtgq/sv", 0x5af},
785 * General purpose registers
787 static const char *name_of_register[32] = {
788 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
789 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
790 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
791 "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"
794 static int regcount; /* how many regs used in this inst */
795 static int regnum[3]; /* which regs used in this inst */
797 static const char *register_name __P((int));
805 for (i = 0; i < regcount; i++)
806 if (regnum[i] == ireg)
809 regnum[regcount++] = ireg;
810 return (name_of_register[ireg]);
814 * Disassemble instruction at 'loc'. 'altfmt' specifies an
815 * (optional) alternate format. Return address of start of
818 int alpha_print_instruction __P((db_addr_t, alpha_instruction, boolean_t));
821 db_disasm(loc, altfmt)
825 alpha_instruction inst;
827 inst.bits = db_get_value(loc, 4, 0);
829 loc += alpha_print_instruction(loc, inst, altfmt);
834 alpha_print_instruction(iadr, i, showregs)
841 long signed_immediate;
847 opcode = op_name[i.mem_format.opcode];
850 * Dispatch directly on the opcode, save code
851 * duplication sometimes via "harmless gotos".
853 switch (i.mem_format.opcode) {
855 /* "call_pal" is a long string; just use a space. */
856 db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
867 * These loadstores are here to make compiling the
868 * switch a bit easier. Could embellish the output
875 * For this and the following three groups we
876 * just need different opcode strings
878 opcode = arit_name(i.operate_lit_format.function);
882 opcode = logical_name(i.operate_lit_format.function);
886 opcode = bitop_name(i.operate_lit_format.function);
890 opcode = mul_name(i.operate_lit_format.function);
893 * Nice and uniform, just check for literals
895 db_printf("%s\t%s,", opcode,
896 register_name(i.operate_lit_format.rs));
897 if (i.operate_lit_format.one)
898 db_printf("#0x%x", i.operate_lit_format.literal);
900 db_printf("%s", register_name(i.operate_reg_format.rt));
901 db_printf(",%s", register_name(i.operate_lit_format.rd));
905 * The three floating point groups are even simpler
907 opcode = vaxf_name(i.float_format.function);
911 opcode = ieeef_name(i.float_format.function);
915 opcode = anyf_name(i.float_format.function);
917 db_printf("%s\tf%d,f%d,f%d", opcode,
927 register unsigned int code;
929 code = (i.mem_format.displacement)&0xffff;
930 opcode = special_name(code);
935 db_printf("%s\t0(%s)", opcode,
936 register_name(i.mem_format.rs));
941 db_printf("%s\t%s", opcode,
942 register_name(i.mem_format.rd));
947 db_printf("%s", opcode);
954 * Jump instructions really are of two sorts,
955 * depending on the use of the hint info.
957 opcode = jump_name(i.jump_format.action);
958 switch (i.jump_format.action) {
961 db_printf("%s\t%s,(%s),", opcode,
962 register_name(i.jump_format.rd),
963 register_name(i.jump_format.rs));
964 signed_immediate = i.jump_format.hint;
965 goto branch_displacement;
969 db_printf("%s\t%s,(%s)", opcode,
970 register_name(i.jump_format.rd),
971 register_name(i.jump_format.rs));
977 * These are just in "operate" format.
979 opcode = intmisc_name(i.operate_lit_format.function);
982 /* HW instructions, possibly chip-specific XXXX */
983 case op_pal19: /* "hw_mfpr" */
984 case op_pal1d: /* "hw_mtpr" */
986 db_printf("\t%s%s\t%s, %d", opcode,
987 mXpr_name[p.mXpr_format.regset],
988 register_name(p.mXpr_format.rd),
989 p.mXpr_format.index);
991 case op_pal1b: /* "hw_ld" */
992 case op_pal1f: /* "hw_st" */
994 db_printf("\t%s%c%s\t%s,", opcode,
995 (p.mem_format.qw) ? 'q' : 'l',
996 hwlds_name[p.mem_format.qualif],
997 register_name(p.mem_format.rd));
998 signed_immediate = (long)p.mem_format.displacement;
999 goto loadstore_address;
1001 case op_pal1e: /* "hw_rei" */
1002 db_printf("\t%s", opcode);
1024 * Memory operations, including floats
1028 db_printf("%s\tf%d,", opcode, i.mem_format.rd);
1030 db_printf("%s\t%s,", opcode,
1031 register_name(i.mem_format.rd));
1032 signed_immediate = (long)i.mem_format.displacement;
1034 db_printf("%+#lx(%s)", signed_immediate,
1035 register_name(i.mem_format.rs));
1037 * For convenience, do the address computation
1040 if (i.mem_format.opcode == op_ldah)
1041 signed_immediate <<= 16;
1042 db_printf(" <0x%lx>", signed_immediate +
1043 db_register_value(DDB_REGS, i.mem_format.rs));
1063 * We want to know where we are branching to
1065 signed_immediate = (long)i.branch_format.displacement;
1066 db_printf("%s\t%s,", opcode,
1067 register_name(i.branch_format.rd));
1068 branch_displacement:
1069 db_printsym(iadr + sizeof(alpha_instruction) +
1070 (signed_immediate << 2), DB_STGY_PROC);
1076 db_printf("? 0x%x ?", i.bits);
1080 * Print out the registers used in this instruction
1082 if (showregs && regcount > 0) {
1084 for (ireg = 0; ireg < regcount; ireg++) {
1087 db_printf("%s=0x%lx",
1088 name_of_register[regnum[ireg]],
1089 db_register_value(DDB_REGS, regnum[ireg]));
1094 return (sizeof(alpha_instruction));