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