2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
29 * Author: Alessandro Forin, Carnegie Mellon University
32 * Disassembler for Alpha
34 * Modified for NetBSD/alpha by:
36 * Christopher G. Demetriou, Carnegie Mellon University
38 * Jason R. Thorpe, Numerical Aerospace Simulation Facility,
39 * NASA Ames Research Center
41 * This code was derived exclusively from information available in
42 * "Alpha Architecture Reference Manual", Richard L. Sites ed.
43 * Digital Press, Burlington, MA 01803
44 * ISBN 1-55558-098-X, Order no. EY-L520E-DP
47 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
48 /* __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $"); */
49 __FBSDID("$FreeBSD$");
51 #include <sys/param.h>
52 #include <sys/systm.h>
54 #include <machine/db_machdep.h>
55 #include <alpha/alpha/db_instruction.h>
57 #include <machine/pal.h>
60 #include <ddb/db_access.h>
61 #include <ddb/db_sym.h>
62 #include <ddb/db_output.h>
65 * This would belong in a header file, except noone else needs it
69 * All instructions are 32 bits wide, PAL included
74 * Internal processor register access instrs
75 * specify the IPR index, doubly specify the
76 * (same) GP register as src/dest, and qualifiers
77 * for the IPR set involved (abox/ibox/tmp)
81 regset : 3, /* a,i,p */
89 * Load/store instructions have a 12 bit displacement,
90 * and two register specifiers just as normal ld/st.
91 * Four bits have special meanings:
92 * phy: bypass the MMU (physical access)
93 * alt: use mode in ALT register for checks,
94 * or if PHY is also on locked/linked access
95 * rwc: read-with-write-check (probew)
99 signed int displacement : 12;
108 * Return from exception or interrupt has
109 * a branch-like encoding, but only one
110 * instantiation is actually usable.
114 zero : 1, /* branch prediction! */
116 rb : 5, /* r31 or stall */
117 ra : 5, /* r31 or stall */
127 static char *op_name[64] = {
128 /* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5", "op6", "op7",
129 /* 8 */ "lda", "ldah", "ldbu", "ldq_u","ldwu", "stw", "stb", "stq_u",
130 /*16 */ "arit", "logical","bit","mul", "op20", "vaxf", "ieeef","anyf",
131 /*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st",
132 /*32 */ "ldf", "ldg", "lds", "ldt", "stf", "stg", "sts", "stt",
133 /*40 */ "ldl", "ldq", "ldl_l","ldq_l","stl", "stq", "stl_c","stq_c",
134 /*48 */ "br", "fbeq", "fblt", "fble", "bsr", "fbne", "fbge", "fbgt",
135 /*56 */ "blbc", "beq", "blt", "ble", "blbs", "bne", "bge", "bgt"
139 * The function field is too big (7 or 11 bits), so the sub-tables
140 * are addressed in a somewhat complicated manner to save
141 * space. After all, alu operations is what RISCs are good at.
149 static const struct tbl pal_op_tbl[] = {
150 /* Common PAL function codes. */
151 { "halt", PAL_halt },
152 { "cflush", PAL_cflush },
153 { "draina", PAL_draina },
154 { "cserve", PAL_cserve, },
155 { "swppal", PAL_swppal },
156 { "ipir", PAL_ipir },
158 { "bugchk", PAL_bugchk },
160 { "rdunique", PAL_rdunique },
161 { "wrunique", PAL_wrunique },
162 { "gentrap", PAL_gentrap },
164 /* OSF/1 PAL function codes. */
165 { "osf1_rdmces", PAL_OSF1_rdmces },
166 { "osf1_wrmces", PAL_OSF1_wrmces },
167 { "osf1_wrfen", PAL_OSF1_wrfen },
168 { "osf1_wrvptptr", PAL_OSF1_wrvptptr },
169 { "osf1_swpctx", PAL_OSF1_swpctx },
170 { "osf1_wrval", PAL_OSF1_wrval },
171 { "osf1_rdval", PAL_OSF1_rdval },
172 { "osf1_tbi", PAL_OSF1_tbi },
173 { "osf1_wrent", PAL_OSF1_wrent },
174 { "osf1_swpipl", PAL_OSF1_swpipl },
175 { "osf1_rdps", PAL_OSF1_rdps },
176 { "osf1_wrkgp", PAL_OSF1_wrkgp },
177 { "osf1_wrusp", PAL_OSF1_wrusp },
178 { "osf1_wrperfmon", PAL_OSF1_wrperfmon },
179 { "osf1_rdusp", PAL_OSF1_rdusp },
180 { "osf1_whami", PAL_OSF1_whami },
181 { "osf1_retsys", PAL_OSF1_retsys },
182 { "osf1_rti", PAL_OSF1_rti },
183 { "osf1_callsys", PAL_OSF1_callsys },
188 static const char *pal_opname(int);
197 for (i = 0; pal_op_tbl[i].name != NULL; i++) {
198 if (pal_op_tbl[i].code == op)
199 return (pal_op_tbl[i].name);
202 snprintf(unk, sizeof(unk), "0x%x", op);
206 /* HW (PAL) instruction qualifiers, stright tables */
207 static const char *mXpr_name[8] = {
208 "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
210 static const char *hwlds_name[8] = {
211 "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
215 * For this one we take the low nibble (valid values 0/2/9/b/d)
216 * and shift it down one to get the row index. Within a row
217 * we can just take the high nibble deprived of the high bit
218 * (valid values 0/1/2/3/4/6). We could have used a flat 64
219 * entry array, but in this way we use just 48 pointers.
220 * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too
222 static const char *arit_c0[8] = {
223 "addl", 0, "addq", 0, "addl/v", 0, "addq/v",
225 static const char *arit_c2[8] = {
226 "s4addl", "s8addl", "s4addq", "s8addq",
228 static const char *arit_c9[8] = {
229 "subl", 0, "subq", 0, "subl/v", 0, "subq/v",
231 static const char *arit_cB[8] = {
232 "s4subl", "s8subl", "s4subq", "s8subq",
234 static const char *arit_cD[8] = {
235 0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
237 static const char *arit_cF[1] = {
240 static const char **arit_opname[8] = {
241 arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
244 static __inline const char *arit_name(int);
245 static __inline const char *
250 const char *name = NULL;
252 if (arit_opname[((op)&0xe)>>1])
253 name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
258 snprintf(unk, sizeof(unk), "?arit 0x%x?", op);
263 * Something similar for this one, except there are only
264 * 16 entries so the row indexing is done by enumeration
265 * of the low nibble (valid values 0/4/6/8). Then we can
266 * just shift the high nibble to index inside the row
267 * (valid values are 0/2/4 or 1/2/4/6)
269 * There are two functions that don't play by these simple rules,
270 * so we special-case them.
272 static const char *logical_c0[4] = {
273 "and", "or", "xor", 0
275 static const char *logical_c4[4] = {
276 "cmovlbs", "cmoveq", "cmovlt", "cmovle"
278 static const char *logical_c6[4] = {
279 "cmovlbc", "cmovne", "cmovge", "cmovgt"
281 static const char *logical_c8[4] = {
282 "andnot", "ornot", "xornot", 0
285 static __inline const char *logical_name(int);
286 static __inline const char *
291 const char *name = NULL;
295 else if (op == op_implver)
299 case 0: name = logical_c0[((op)>>5)&3]; break;
300 case 4: name = logical_c4[((op)>>5)&3]; break;
301 case 6: name = logical_c6[((op)>>5)&3]; break;
302 case 8: name = logical_c8[((op)>>5)&3]; break;
308 snprintf(unk, sizeof(unk), "?logical 0x%x?", op);
313 * This is the messy one. First, we single out the dense
314 * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c).
315 * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7).
316 * For the remaining codes (6/7/a/b) we do as above: high
317 * nibble has valid values 0/1/2 or 5/6/7. The low nibble
318 * can be used as row index picking bits 0 and 2, for the
319 * high one just the lower two bits.
321 static const char *bitop_c3[8] = {
322 "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
324 static const char *bitop_c2[8] = {
325 "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
327 static const char *bitop_c67ab[4][4] = {
328 /* a */ { 0, "extwh", "extlh", "extqh"},
329 /* b */ { "insbl", "inswl", "insll", 0 },
330 /* 6 */ { "extbl", "extwl", "extll", 0 },
331 /* 7 */ { 0, "inswh", "inslh", "insqh" },
334 static __inline const char *bitop_name(int);
335 static __inline const char *
340 const char *name = NULL;
342 if ((op & 0x70) == 0x30)
343 name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1];
344 else if ((op & 0xf) == 0x02)
345 name = bitop_c2[(op)>>4];
348 bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
353 snprintf(unk, sizeof(unk), "?bit 0x%x?", op);
358 * Only 5 entries in this one
360 static const char *mul_opname[4] = {
361 "mull", "mulq", "mull/v", "mulq/v"
364 static __inline const char *mul_name(int);
365 static __inline const char *
370 const char *name = NULL;
372 name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
377 snprintf(unk, sizeof(unk), "?mul 0x%x?", op);
382 * These are few, the high nibble is enough to dispatch.
383 * We single out the "f" case to halve the table size.
385 static const char *special_opname[8] = {
386 "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
389 static __inline const char *special_name(int);
390 static __inline const char *
397 name = (op == op_rs) ? "rs" : special_opname[(op)>>13];
402 snprintf(unk, sizeof(unk), "?special 0x%x?", op);
409 static const char *jump_opname[4] = {
410 "jmp", "jsr", "ret", "jcr"
412 #define jump_name(ix) jump_opname[ix]
415 * For all but 4 of these, we can dispatch on the lower nibble of
418 static const char *intmisc_opname_3x[16] = {
419 "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb",
420 "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8",
421 "maxuw4", "maxsb8", "maxsw4",
424 static __inline const char *intmisc_name(int);
425 static __inline const char *
431 if ((op & 0xf0) == 0x30)
432 return (intmisc_opname_3x[op & 0x0f]);
435 case op_sextb: return ("sextb");
436 case op_sextw: return ("sextw");
437 case op_ftoit: return ("ftoit");
438 case op_ftois: return ("ftois");
441 snprintf(unk, sizeof(unk), "?intmisc 0x%x?", op);
445 static const char *float_name(const struct tbl[], int, const char *type);
448 float_name(tbl, op, type)
449 const struct tbl tbl[];
456 for (i = 0; tbl[i].name != NULL; i++) {
457 if (tbl[i].code == op)
458 return (tbl[i].name);
461 snprintf(unk, sizeof(unk), "?%s 0x%x?", type, op);
465 #define vaxf_name(op) float_name(vaxf_tbl, op, "vaxfl")
466 #define ieeef_name(op) float_name(ieeef_tbl, op, "ieeefl")
467 #define anyf_name(op) float_name(anyf_tbl, op, "anyfl")
469 static const struct tbl anyf_tbl[] = {
484 { "cvtql/sv", 0x330},
488 static const struct tbl ieeef_tbl[] = {
547 { "cvtts/uc", 0x12c},
548 { "cvttq/vc", 0x12f},
557 { "cvtts/um", 0x16c},
576 { "cvtts/ud", 0x1ec},
577 { "adds/suc", 0x500},
578 { "subs/suc", 0x501},
579 { "muls/suc", 0x502},
580 { "divs/suc", 0x503},
581 { "addt/suc", 0x520},
582 { "subt/suc", 0x521},
583 { "mult/suc", 0x522},
584 { "divt/suc", 0x523},
585 { "cvtts/suc", 0x52c},
586 { "cvttq/svc", 0x52f},
587 { "adds/sum", 0x540},
588 { "subs/sum", 0x541},
589 { "muls/sum", 0x542},
590 { "divs/sum", 0x543},
591 { "addt/sum", 0x560},
592 { "subt/sum", 0x561},
593 { "mult/sum", 0x562},
594 { "divt/sum", 0x563},
595 { "cvtts/sum", 0x56c},
604 { "cmptun/su", 0x5a4},
605 { "cmpteq/su", 0x5a5},
606 { "cmptlt/su", 0x5a6},
607 { "cmptle/su", 0x5a7},
608 { "cvtts/su", 0x5ac},
609 { "cvttq/sv", 0x5af},
610 { "adds/sud", 0x5c0},
611 { "subs/sud", 0x5c1},
612 { "muls/sud", 0x5c2},
613 { "divs/sud", 0x5c3},
614 { "addt/sud", 0x5e0},
615 { "subt/sud", 0x5e1},
616 { "mult/sud", 0x5e2},
617 { "divt/sud", 0x5e3},
618 { "cvtts/sud", 0x5ec},
619 { "adds/suic", 0x700},
620 { "subs/suic", 0x701},
621 { "muls/suic", 0x702},
622 { "divs/suic", 0x703},
623 { "addt/suic", 0x720},
624 { "subt/suic", 0x721},
625 { "mult/suic", 0x722},
626 { "divt/suic", 0x723},
627 { "cvtts/suic", 0x72c},
628 { "cvttq/svic", 0x72f},
629 { "cvtqs/suic", 0x73c},
630 { "cvtqt/suic", 0x73e},
631 { "adds/suim", 0x740},
632 { "subs/suim", 0x741},
633 { "muls/suim", 0x742},
634 { "divs/suim", 0x743},
635 { "addt/suim", 0x760},
636 { "subt/suim", 0x761},
637 { "mult/suim", 0x762},
638 { "divt/suim", 0x763},
639 { "cvtts/suim", 0x76c},
640 { "cvtqs/suim", 0x77c},
641 { "cvtqt/suim", 0x77e},
642 { "adds/sui", 0x780},
643 { "subs/sui", 0x781},
644 { "muls/sui", 0x782},
645 { "divs/sui", 0x783},
646 { "addt/sui", 0x7a0},
647 { "subt/sui", 0x7a1},
648 { "mult/sui", 0x7a2},
649 { "divt/sui", 0x7a3},
650 { "cvtts/sui", 0x7ac},
651 { "cvttq/svi", 0x7af},
652 { "cvtqs/sui", 0x7bc},
653 { "cvtqt/sui", 0x7be},
654 { "adds/suid", 0x7c0},
655 { "subs/suid", 0x7c1},
656 { "muls/suid", 0x7c2},
657 { "divs/suid", 0x7c3},
658 { "addt/suid", 0x7e0},
659 { "subt/suid", 0x7e1},
660 { "mult/suid", 0x7e2},
661 { "divt/suid", 0x7e3},
662 { "cvtts/suid", 0x7ec},
663 { "cvtqs/suid", 0x7fc},
664 { "cvtqt/suid", 0x7fe},
668 static const struct tbl vaxf_tbl[] = {
704 { "cvtdg/uc", 0x11e},
709 { "cvtgf/uc", 0x12c},
710 { "cvtgd/uc", 0x12d},
711 { "cvtgq/vc", 0x12f},
728 { "cvtdg/sc", 0x41e},
733 { "cvtgf/sc", 0x42c},
734 { "cvtgd/sc", 0x42d},
735 { "cvtgq/sc", 0x42f},
736 { "cvtqf/sc", 0x43c},
737 { "cvtqg/sc", 0x43e},
747 { "cmpgeq/s", 0x4a5},
748 { "cmpglt/s", 0x4a6},
749 { "cmpgle/s", 0x4a7},
755 { "addf/suc", 0x500},
756 { "subf/suc", 0x501},
757 { "mulf/suc", 0x502},
758 { "divf/suc", 0x503},
759 { "cvtdg/suc", 0x51e},
760 { "addg/suc", 0x520},
761 { "subg/suc", 0x521},
762 { "mulg/suc", 0x522},
763 { "divg/suc", 0x523},
764 { "cvtgf/suc", 0x52c},
765 { "cvtgd/suc", 0x52d},
766 { "cvtgq/svc", 0x52f},
771 { "cvtdg/su", 0x59e},
776 { "cvtgf/su", 0x5ac},
777 { "cvtgd/su", 0x5ad},
778 { "cvtgq/sv", 0x5af},
783 * General purpose registers
785 static const char *name_of_register[32] = {
786 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
787 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
788 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
789 "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"
792 static int regcount; /* how many regs used in this inst */
793 static int regnum[3]; /* which regs used in this inst */
795 static const char *register_name(int);
803 for (i = 0; i < regcount; i++)
804 if (regnum[i] == ireg)
807 regnum[regcount++] = ireg;
808 return (name_of_register[ireg]);
812 * Disassemble instruction at 'loc'. 'altfmt' specifies an
813 * (optional) alternate format. Return address of start of
818 alpha_print_instr(db_addr_t iadr, alpha_instruction i, boolean_t showregs)
822 long signed_immediate;
828 opcode = op_name[i.mem_format.opcode];
831 * Dispatch directly on the opcode, save code
832 * duplication sometimes via "harmless gotos".
834 switch (i.mem_format.opcode) {
836 /* "call_pal" is a long string; just use a space. */
837 db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
848 * These loadstores are here to make compiling the
849 * switch a bit easier. Could embellish the output
856 * For this and the following three groups we
857 * just need different opcode strings
859 opcode = arit_name(i.operate_lit_format.function);
863 opcode = logical_name(i.operate_lit_format.function);
867 opcode = bitop_name(i.operate_lit_format.function);
871 opcode = mul_name(i.operate_lit_format.function);
874 * Nice and uniform, just check for literals
876 db_printf("%s\t%s,", opcode,
877 register_name(i.operate_lit_format.rs));
878 if (i.operate_lit_format.one)
879 db_printf("#0x%x", i.operate_lit_format.literal);
881 db_printf("%s", register_name(i.operate_reg_format.rt));
882 db_printf(",%s", register_name(i.operate_lit_format.rd));
886 * The three floating point groups are even simpler
888 opcode = vaxf_name(i.float_format.function);
892 opcode = ieeef_name(i.float_format.function);
896 opcode = anyf_name(i.float_format.function);
898 db_printf("%s\tf%d,f%d,f%d", opcode,
908 register unsigned int code;
910 code = (i.mem_format.displacement)&0xffff;
911 opcode = special_name(code);
916 db_printf("%s\t0(%s)", opcode,
917 register_name(i.mem_format.rs));
922 db_printf("%s\t%s", opcode,
923 register_name(i.mem_format.rd));
928 db_printf("%s", opcode);
935 * Jump instructions really are of two sorts,
936 * depending on the use of the hint info.
938 opcode = jump_name(i.jump_format.action);
939 switch (i.jump_format.action) {
942 db_printf("%s\t%s,(%s),", opcode,
943 register_name(i.jump_format.rd),
944 register_name(i.jump_format.rs));
945 signed_immediate = i.jump_format.hint;
946 goto branch_displacement;
950 db_printf("%s\t%s,(%s)", opcode,
951 register_name(i.jump_format.rd),
952 register_name(i.jump_format.rs));
958 * These are just in "operate" format.
960 opcode = intmisc_name(i.operate_lit_format.function);
963 /* HW instructions, possibly chip-specific XXXX */
964 case op_pal19: /* "hw_mfpr" */
965 case op_pal1d: /* "hw_mtpr" */
967 db_printf("\t%s%s\t%s, %d", opcode,
968 mXpr_name[p.mXpr_format.regset],
969 register_name(p.mXpr_format.rd),
970 p.mXpr_format.index);
972 case op_pal1b: /* "hw_ld" */
973 case op_pal1f: /* "hw_st" */
975 db_printf("\t%s%c%s\t%s,", opcode,
976 (p.mem_format.qw) ? 'q' : 'l',
977 hwlds_name[p.mem_format.qualif],
978 register_name(p.mem_format.rd));
979 signed_immediate = (long)p.mem_format.displacement;
980 goto loadstore_address;
982 case op_pal1e: /* "hw_rei" */
983 db_printf("\t%s", opcode);
1005 * Memory operations, including floats
1009 db_printf("%s\tf%d,", opcode, i.mem_format.rd);
1011 db_printf("%s\t%s,", opcode,
1012 register_name(i.mem_format.rd));
1013 signed_immediate = (long)i.mem_format.displacement;
1015 db_printf("%#lx(%s)", signed_immediate,
1016 register_name(i.mem_format.rs));
1018 * For convenience, do the address computation
1021 if (i.mem_format.opcode == op_ldah)
1022 signed_immediate <<= 16;
1023 db_printf(" <0x%lx>", signed_immediate +
1024 db_register_value(i.mem_format.rs));
1044 * We want to know where we are branching to
1046 signed_immediate = (long)i.branch_format.displacement;
1047 db_printf("%s\t%s,", opcode,
1048 register_name(i.branch_format.rd));
1049 branch_displacement:
1050 db_printsym(iadr + sizeof(alpha_instruction) +
1051 (signed_immediate << 2), DB_STGY_PROC);
1057 db_printf("? 0x%x ?", i.bits);
1061 * Print out the registers used in this instruction
1063 if (showregs && regcount > 0) {
1065 for (ireg = 0; ireg < regcount; ireg++) {
1068 db_printf("%s=0x%lx",
1069 name_of_register[regnum[ireg]],
1070 db_register_value(regnum[ireg]));
1075 return (sizeof(alpha_instruction));
1079 db_disasm(loc, altfmt)
1083 alpha_instruction inst;
1085 inst.bits = db_get_value(loc, 4, 0);
1087 loc += alpha_print_instr(loc, inst, altfmt);