Annotation of sys/arch/alpha/alpha/db_disasm.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: db_disasm.c,v 1.19 2007/02/14 00:53:47 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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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", 0x330},
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 *
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(db_addr_t, alpha_instruction, boolean_t);
827:
828: db_addr_t
829: db_disasm(loc, altfmt)
830: db_addr_t loc;
831: boolean_t altfmt;
832: {
833: alpha_instruction inst;
834:
835: inst.bits = db_get_value(loc, 4, 0);
836:
837: loc += alpha_print_instruction(loc, inst, altfmt);
838: return (loc);
839: }
840:
841: int
842: alpha_print_instruction(iadr, i, showregs)
843: db_addr_t iadr;
844: alpha_instruction i;
845: boolean_t showregs;
846: {
847: const char *opcode;
848: int ireg;
849: long signed_immediate;
850: boolean_t fstore;
851: pal_instruction p;
852:
853: regcount = 0;
854: fstore = FALSE;
855: opcode = op_name[i.mem_format.opcode];
856:
857: /*
858: * Dispatch directly on the opcode, save code
859: * duplication sometimes via "harmless gotos".
860: */
861: switch (i.mem_format.opcode) {
862: case op_pal:
863: /* "call_pal" is a long string; just use a space. */
864: db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
865: break;
866: case op_lda:
867: case op_ldah:
868: case op_ldbu:
869: case op_ldq_u:
870: case op_ldwu:
871: case op_stw:
872: case op_stb:
873: case op_stq_u:
874: /*
875: * These loadstores are here to make compiling the
876: * switch a bit easier. Could embellish the output
877: * someday, too.
878: */
879: goto loadstore;
880: break;
881: case op_arit:
882: /*
883: * For this and the following three groups we
884: * just need different opcode strings
885: */
886: opcode = arit_name(i.operate_lit_format.function);
887: goto operate;
888: break;
889: case op_logical:
890: opcode = logical_name(i.operate_lit_format.function);
891: goto operate;
892: break;
893: case op_bit:
894: opcode = bitop_name(i.operate_lit_format.function);
895: goto operate;
896: break;
897: case op_mul:
898: opcode = mul_name(i.operate_lit_format.function);
899: operate:
900: /*
901: * Nice and uniform, just check for literals
902: */
903: db_printf("%s\t%s,", opcode,
904: register_name(i.operate_lit_format.ra));
905: if (i.operate_lit_format.one)
906: db_printf("#0x%x", i.operate_lit_format.literal);
907: else
908: db_printf("%s", register_name(i.operate_reg_format.rb));
909: db_printf(",%s", register_name(i.operate_lit_format.rc));
910: break;
911: case op_vax_float:
912: /*
913: * The three floating point groups are even simpler
914: */
915: opcode = vaxf_name(i.float_format.function);
916: goto foperate;
917: break;
918: case op_ieee_float:
919: opcode = ieeef_name(i.float_format.function);
920: goto foperate;
921: break;
922: case op_any_float:
923: opcode = anyf_name(i.float_format.function);
924: foperate:
925: db_printf("%s\tf%d,f%d,f%d", opcode,
926: i.float_format.fa,
927: i.float_format.fb,
928: i.float_format.fc);
929: break;
930: case op_special:
931: /*
932: * Miscellaneous.
933: */
934: {
935: register unsigned int code;
936:
937: code = (i.mem_format.displacement)&0xffff;
938: opcode = special_name(code);
939:
940: switch (code) {
941: case op_ecb:
942: db_printf("%s\t(%s)", opcode,
943: register_name(i.mem_format.rb));
944: break;
945: case op_fetch:
946: case op_fetch_m:
947: db_printf("%s\t0(%s)", opcode,
948: register_name(i.mem_format.rb));
949: break;
950: case op_rpcc:
951: case op_rc:
952: case op_rs:
953: db_printf("%s\t%s", opcode,
954: register_name(i.mem_format.ra));
955: break;
956: default:
957: db_printf("%s", opcode);
958: break;
959: }
960: }
961: break;
962: case op_j:
963: /*
964: * Jump instructions really are of two sorts,
965: * depending on the use of the hint info.
966: */
967: opcode = jump_name(i.jump_format.action);
968: switch (i.jump_format.action) {
969: case op_jmp:
970: case op_jsr:
971: db_printf("%s\t%s,(%s),", opcode,
972: register_name(i.jump_format.ra),
973: register_name(i.jump_format.rb));
974: signed_immediate = i.jump_format.hint;
975: goto branch_displacement;
976: break;
977: case op_ret:
978: case op_jcr:
979: db_printf("%s\t%s,(%s)", opcode,
980: register_name(i.jump_format.ra),
981: register_name(i.jump_format.rb));
982: break;
983: }
984: break;
985: case op_intmisc:
986: /*
987: * These are just in "operate" format.
988: */
989: opcode = intmisc_name(i.operate_lit_format.function);
990: goto operate;
991: break;
992: /* HW instructions, possibly chip-specific XXXX */
993: case op_pal19: /* "hw_mfpr" */
994: case op_pal1d: /* "hw_mtpr" */
995: p.bits = i.bits;
996: db_printf("\t%s%s\t%s, %d", opcode,
997: mXpr_name[p.mXpr_format.regset],
998: register_name(p.mXpr_format.rd),
999: p.mXpr_format.index);
1000: break;
1001: case op_pal1b: /* "hw_ld" */
1002: case op_pal1f: /* "hw_st" */
1003: p.bits = i.bits;
1004: db_printf("\t%s%c%s\t%s,", opcode,
1005: (p.mem_format.qw) ? 'q' : 'l',
1006: hwlds_name[p.mem_format.qualif],
1007: register_name(p.mem_format.rd));
1008: signed_immediate = (long)p.mem_format.displacement;
1009: goto loadstore_address;
1010:
1011: case op_pal1e: /* "hw_rei" */
1012: db_printf("\t%s", opcode);
1013: break;
1014:
1015: case op_ldf:
1016: case op_ldg:
1017: case op_lds:
1018: case op_ldt:
1019: case op_stf:
1020: case op_stg:
1021: case op_sts:
1022: case op_stt:
1023: fstore = TRUE;
1024: /* FALLTHROUGH */
1025: case op_ldl:
1026: case op_ldq:
1027: case op_ldl_l:
1028: case op_ldq_l:
1029: case op_stl:
1030: case op_stq:
1031: case op_stl_c:
1032: case op_stq_c:
1033: /*
1034: * Memory operations, including floats
1035: */
1036: loadstore:
1037: if (fstore)
1038: db_printf("%s\tf%d,", opcode, i.mem_format.ra);
1039: else
1040: db_printf("%s\t%s,", opcode,
1041: register_name(i.mem_format.ra));
1042: signed_immediate = (long)i.mem_format.displacement;
1043: loadstore_address:
1044: db_printf("%lz(%s)", signed_immediate,
1045: register_name(i.mem_format.rb));
1046: /*
1047: * For convenience, do the address computation
1048: */
1049: if (showregs) {
1050: if (i.mem_format.opcode == op_ldah)
1051: signed_immediate <<= 16;
1052: db_printf(" <0x%lx>", signed_immediate +
1053: db_register_value(DDB_REGS, i.mem_format.rb));
1054: }
1055: break;
1056: case op_br:
1057: case op_fbeq:
1058: case op_fblt:
1059: case op_fble:
1060: case op_bsr:
1061: case op_fbne:
1062: case op_fbge:
1063: case op_fbgt:
1064: case op_blbc:
1065: case op_beq:
1066: case op_blt:
1067: case op_ble:
1068: case op_blbs:
1069: case op_bne:
1070: case op_bge:
1071: case op_bgt:
1072: /*
1073: * We want to know where we are branching to
1074: */
1075: signed_immediate = (long)i.branch_format.displacement;
1076: db_printf("%s\t%s,", opcode,
1077: register_name(i.branch_format.ra));
1078: branch_displacement:
1079: db_printsym(iadr + sizeof(alpha_instruction) +
1080: (signed_immediate << 2), DB_STGY_PROC, db_printf);
1081: break;
1082: default:
1083: /*
1084: * Shouldn't happen
1085: */
1086: db_printf("? 0x%x ?", i.bits);
1087: }
1088:
1089: /*
1090: * Print out the registers used in this instruction
1091: */
1092: if (showregs && regcount > 0) {
1093: db_printf("\t<");
1094: for (ireg = 0; ireg < regcount; ireg++) {
1095: if (ireg != 0)
1096: db_printf(",");
1097: db_printf("%s=0x%lx",
1098: name_of_register[regnum[ireg]],
1099: db_register_value(DDB_REGS, regnum[ireg]));
1100: }
1101: db_printf(">");
1102: }
1103: db_printf("\n");
1104: return (sizeof(alpha_instruction));
1105: }
CVSweb