]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/alpha/db_disasm.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / sys / alpha / alpha / db_disasm.c
1 /*-
2  * Mach Operating System
3  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
4  * All Rights Reserved.
5  * 
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.
11  * 
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.
15  * 
16  * Carnegie Mellon requests users of this software to return to
17  * 
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  * 
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  */
26
27 /*
28  *      File: db_disasm.c
29  *      Author: Alessandro Forin, Carnegie Mellon University
30  *      Date:   11/91
31  *
32  *      Disassembler for Alpha
33  *
34  *      Modified for NetBSD/alpha by:
35  *
36  *      Christopher G. Demetriou, Carnegie Mellon University
37  *
38  *      Jason R. Thorpe, Numerical Aerospace Simulation Facility,
39  *      NASA Ames Research Center
40  *
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
45  */
46
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$");
50
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/proc.h>
54 #include <machine/db_machdep.h>
55 #include <alpha/alpha/db_instruction.h>
56
57 #include <machine/pal.h>
58  
59 #include <ddb/ddb.h>
60 #include <ddb/db_access.h>
61 #include <ddb/db_sym.h>
62 #include <ddb/db_output.h>
63
64 /*
65  * This would belong in a header file, except noone else needs it
66  */
67 typedef union {
68         /*
69          *      All instructions are 32 bits wide, PAL included
70          */
71         unsigned int    bits;
72
73         /*
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)
78          */
79         struct {
80                 unsigned        index : 5,
81                                 regset : 3, /* a,i,p */
82                                 xxx : 8,
83                                 rs : 5,
84                                 rd : 5,
85                                 opcode : 6;
86         } mXpr_format;
87
88         /*
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)
96          *              qw:  quadword access
97          */
98         struct {
99                 signed int      displacement : 12;
100                 unsigned        qw : 1,
101                                 qualif : 3,
102                                 rs : 5,
103                                 rd : 5,
104                                 opcode : 6;
105         } mem_format;
106
107         /*
108          *      Return from exception or interrupt has
109          *      a branch-like encoding, but only one
110          *      instantiation is actually usable.
111          */
112         struct {
113                 unsigned        xxx : 14,
114                                 zero : 1,       /* branch prediction! */
115                                 one : 1,
116                                 rb : 5,         /* r31 or stall */
117                                 ra : 5,         /* r31 or stall */
118                                 opcode : 6;
119         } rei_format;
120
121 } pal_instruction;
122
123
124 /*
125  * Major opcodes
126  */
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"
136 };
137
138 /*
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.
142  */
143
144 struct tbl {
145         const char      *name;
146         int             code;
147 };
148
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 },
157         { "bpt",                PAL_bpt },
158         { "bugchk",             PAL_bugchk },
159         { "imb",                PAL_imb },
160         { "rdunique",           PAL_rdunique },
161         { "wrunique",           PAL_wrunique },
162         { "gentrap",            PAL_gentrap },
163
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 },
184
185         { NULL,                 -1 },
186 };
187
188 static const char *pal_opname(int);
189
190 static const char *
191 pal_opname(op)
192         int op;
193 {
194         static char unk[8];
195         int i;
196
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);
200         }
201
202         snprintf(unk, sizeof(unk), "0x%x", op);
203         return (unk);
204 }
205
206 /* HW (PAL) instruction qualifiers, stright tables */
207 static const char *mXpr_name[8] = {
208         "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
209 };
210 static const char *hwlds_name[8] = {
211         "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
212 };
213
214 /*
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
221  */
222 static const char *arit_c0[8] = {
223         "addl", 0, "addq", 0, "addl/v", 0, "addq/v",
224 };
225 static const char *arit_c2[8] = {
226         "s4addl", "s8addl", "s4addq", "s8addq", 
227 };
228 static const char *arit_c9[8] = {
229         "subl", 0, "subq", 0, "subl/v", 0, "subq/v", 
230 };
231 static const char *arit_cB[8] = {
232         "s4subl", "s8subl", "s4subq", "s8subq", 
233 };
234 static const char *arit_cD[8] = {
235         0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
236 };
237 static const char *arit_cF[1] = {
238         "cmpbge"
239 };
240 static const char **arit_opname[8] = {
241         arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
242 };
243
244 static __inline const char *arit_name(int);
245 static __inline const char *
246 arit_name(op)
247         int op;
248 {
249         static char unk[32];
250         const char *name = NULL;
251
252         if (arit_opname[((op)&0xe)>>1])
253                 name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
254
255         if (name != NULL)
256                 return (name);
257
258         snprintf(unk, sizeof(unk), "?arit 0x%x?", op);
259         return (unk);
260 }
261
262 /*
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)
268  *
269  * There are two functions that don't play by these simple rules,
270  * so we special-case them.
271  */
272 static const char *logical_c0[4] = {
273         "and", "or", "xor", 0
274 };
275 static const char *logical_c4[4] = {
276         "cmovlbs", "cmoveq", "cmovlt", "cmovle"
277 };
278 static const char *logical_c6[4] = {
279         "cmovlbc", "cmovne", "cmovge", "cmovgt"
280 };
281 static const char *logical_c8[4] = {
282         "andnot", "ornot", "xornot", 0
283 };
284
285 static __inline const char *logical_name(int);
286 static __inline const char *
287 logical_name(op)
288         int op;
289 {
290         static char unk[32];
291         const char *name = NULL;
292
293         if (op == op_amask)
294                 return ("amask");
295         else if (op == op_implver)
296                 return ("implver");
297
298         switch (op & 0xf) {
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;
303         }
304
305         if (name != NULL)
306                 return (name);
307
308         snprintf(unk, sizeof(unk), "?logical 0x%x?", op);
309         return (unk);
310 }
311
312 /*
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.
320  */
321 static const char *bitop_c3[8] = {
322         "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
323 };
324 static const char *bitop_c2[8] = {
325         "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
326 };
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" },
332 };
333
334 static __inline const char *bitop_name(int);
335 static __inline const char *
336 bitop_name(op)
337         int op;
338 {
339         static char unk[32];
340         const char *name = NULL;
341
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];
346         else
347                 name =
348                     bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
349
350         if (name != NULL)
351                 return (name);
352
353         snprintf(unk, sizeof(unk), "?bit 0x%x?", op);
354         return (unk);
355 }
356
357 /*
358  * Only 5 entries in this one
359  */
360 static const char *mul_opname[4] = {
361         "mull", "mulq", "mull/v", "mulq/v"
362 };
363
364 static __inline const char *mul_name(int);
365 static __inline const char *
366 mul_name(op)
367         int op;
368 {
369         static char unk[32];
370         const char *name = NULL;
371
372         name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
373
374         if (name != NULL)
375                 return (name);
376
377         snprintf(unk, sizeof(unk), "?mul 0x%x?", op);
378         return (unk);
379 }
380
381 /*
382  * These are few, the high nibble is enough to dispatch.
383  * We single out the "f" case to halve the table size.
384  */
385 static const char *special_opname[8] = {
386         "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
387 };
388
389 static __inline const char *special_name(int);
390 static __inline const char *
391 special_name(op)
392         int op;
393 {
394         static char unk[32];
395         const char *name;
396
397         name = (op == op_rs) ? "rs" : special_opname[(op)>>13];
398
399         if (name != NULL)
400                 return (name);
401
402         snprintf(unk, sizeof(unk), "?special 0x%x?", op);
403         return (unk);
404 }
405
406 /*
407  * This is trivial
408  */
409 static const char *jump_opname[4] = {
410         "jmp", "jsr", "ret", "jcr"
411 };
412 #define jump_name(ix)   jump_opname[ix]
413
414 /*
415  * For all but 4 of these, we can dispatch on the lower nibble of
416  * the "function".
417  */
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",
422 };
423
424 static __inline const char *intmisc_name(int);
425 static __inline const char *
426 intmisc_name(op)
427         int op;
428 {
429         static char unk[32];
430
431         if ((op & 0xf0) == 0x30)
432                 return (intmisc_opname_3x[op & 0x0f]);
433
434         switch (op) {
435         case op_sextb: return ("sextb");
436         case op_sextw: return ("sextw");
437         case op_ftoit: return ("ftoit");
438         case op_ftois: return ("ftois");
439         }
440
441         snprintf(unk, sizeof(unk), "?intmisc 0x%x?", op);
442         return (unk);
443 }
444
445 static const char *float_name(const struct tbl[], int, const char *type);
446
447 static const char *
448 float_name(tbl, op, type)
449         const struct tbl tbl[];
450         int op;
451         const char *type;
452 {
453         static char unk[32];
454         int i;
455
456         for (i = 0; tbl[i].name != NULL; i++) {
457                 if (tbl[i].code == op)
458                         return (tbl[i].name);
459         }
460
461         snprintf(unk, sizeof(unk), "?%s 0x%x?", type, op);
462         return (unk);
463 }
464
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")
468
469 static const struct tbl anyf_tbl[] = {
470         { "cvtlq",      0x010},
471         { "cpys",       0x020},
472         { "cpysn",      0x021},
473         { "cpyse",      0x022},
474         { "mt_fpcr",    0x024},
475         { "mf_fpcr",    0x025},
476         { "fcmoveq",    0x02a},
477         { "fcmovne",    0x02b},
478         { "fcmovlt",    0x02c},
479         { "fcmovge",    0x02d},
480         { "fcmovle",    0x02e},
481         { "fcmovgt",    0x02f},
482         { "cvtql",      0x030},
483         { "cvtql/v",    0x130},
484         { "cvtql/sv",   0x330},
485         { 0, 0},
486 };
487
488 static const struct tbl ieeef_tbl[] = {
489         { "adds/c",     0x000},
490         { "subs/c",     0x001},
491         { "muls/c",     0x002},
492         { "divs/c",     0x003},
493         { "addt/c",     0x020},
494         { "subt/c",     0x021},
495         { "mult/c",     0x022},
496         { "divt/c",     0x023},
497         { "cvtts/c",    0x02c},
498         { "cvttq/c",    0x02f},
499         { "cvtqs/c",    0x03c},
500         { "cvtqt/c",    0x03e},
501         { "adds/m",     0x040},
502         { "subs/m",     0x041},
503         { "muls/m",     0x042},
504         { "divs/m",     0x043},
505         { "addt/m",     0x060},
506         { "subt/m",     0x061},
507         { "mult/m",     0x062},
508         { "divt/m",     0x063},
509         { "cvtts/m",    0x06c},
510         { "cvtqs/m",    0x07c},
511         { "cvtqt/m",    0x07e},
512         { "adds",       0x080},
513         { "subs",       0x081},
514         { "muls",       0x082},
515         { "divs",       0x083},
516         { "addt",       0x0a0},
517         { "subt",       0x0a1},
518         { "mult",       0x0a2},
519         { "divt",       0x0a3},
520         { "cmptun",     0x0a4},
521         { "cmpteq",     0x0a5},
522         { "cmptlt",     0x0a6},
523         { "cmptle",     0x0a7},
524         { "cvtts",      0x0ac},
525         { "cvttq",      0x0af},
526         { "cvtqs",      0x0bc},
527         { "cvtqt",      0x0be},
528         { "adds/d",     0x0c0},
529         { "subs/d",     0x0c1},
530         { "muls/d",     0x0c2},
531         { "divs/d",     0x0c3},
532         { "addt/d",     0x0e0},
533         { "subt/d",     0x0e1},
534         { "mult/d",     0x0e2},
535         { "divt/d",     0x0e3},
536         { "cvtts/d",    0x0ec},
537         { "cvtqs/d",    0x0fc},
538         { "cvtqt/d",    0x0fe},
539         { "adds/uc",    0x100},
540         { "subs/uc",    0x101},
541         { "muls/uc",    0x102},
542         { "divs/uc",    0x103},
543         { "addt/uc",    0x120},
544         { "subt/uc",    0x121},
545         { "mult/uc",    0x122},
546         { "divt/uc",    0x123},
547         { "cvtts/uc",   0x12c},
548         { "cvttq/vc",   0x12f},
549         { "adds/um",    0x140},
550         { "subs/um",    0x141},
551         { "muls/um",    0x142},
552         { "divs/um",    0x143},
553         { "addt/um",    0x160},
554         { "subt/um",    0x161},
555         { "mult/um",    0x162},
556         { "divt/um",    0x163},
557         { "cvtts/um",   0x16c},
558         { "adds/u",     0x180},
559         { "subs/u",     0x181},
560         { "muls/u",     0x182},
561         { "divs/u",     0x183},
562         { "addt/u",     0x1a0},
563         { "subt/u",     0x1a1},
564         { "mult/u",     0x1a2},
565         { "divt/u",     0x1a3},
566         { "cvtts/u",    0x1ac},
567         { "cvttq/v",    0x1af},
568         { "adds/ud",    0x1c0},
569         { "subs/ud",    0x1c1},
570         { "muls/ud",    0x1c2},
571         { "divs/ud",    0x1c3},
572         { "addt/ud",    0x1e0},
573         { "subt/ud",    0x1e1},
574         { "mult/ud",    0x1e2},
575         { "divt/ud",    0x1e3},
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},
596         { "adds/su",    0x580},
597         { "subs/su",    0x581},
598         { "muls/su",    0x582},
599         { "divs/su",    0x583},
600         { "addt/su",    0x5a0},
601         { "subt/su",    0x5a1},
602         { "mult/su",    0x5a2},
603         { "divt/su",    0x5a3},
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},
665         { 0, 0}
666 };
667
668 static const struct tbl vaxf_tbl[] = {
669         { "addf/c",     0x000},
670         { "subf/c",     0x001},
671         { "mulf/c",     0x002},
672         { "divf/c",     0x003},
673         { "cvtdg/c",    0x01e},
674         { "addg/c",     0x020},
675         { "subg/c",     0x021},
676         { "mulg/c",     0x022},
677         { "divg/c",     0x023},
678         { "cvtgf/c",    0x02c},
679         { "cvtgd/c",    0x02d},
680         { "cvtgq/c",    0x02f},
681         { "cvtqf/c",    0x03c},
682         { "cvtqg/c",    0x03e},
683         { "addf",       0x080},
684         { "subf",       0x081},
685         { "mulf",       0x082},
686         { "divf",       0x083},
687         { "cvtdg",      0x09e},
688         { "addg",       0x0a0},
689         { "subg",       0x0a1},
690         { "mulg",       0x0a2},
691         { "divg",       0x0a3},
692         { "cmpgeq",     0x0a5},
693         { "cmpglt",     0x0a6},
694         { "cmpgle",     0x0a7},
695         { "cvtgf",      0x0ac},
696         { "cvtgd",      0x0ad},
697         { "cvtgq",      0x0af},
698         { "cvtqf",      0x0bc},
699         { "cvtqg",      0x0be},
700         { "addf/uc",    0x100},
701         { "subf/uc",    0x101},
702         { "mulf/uc",    0x102},
703         { "divf/uc",    0x103},
704         { "cvtdg/uc",   0x11e},
705         { "addg/uc",    0x120},
706         { "subg/uc",    0x121},
707         { "mulg/uc",    0x122},
708         { "divg/uc",    0x123},
709         { "cvtgf/uc",   0x12c},
710         { "cvtgd/uc",   0x12d},
711         { "cvtgq/vc",   0x12f},
712         { "addf/u",     0x180},
713         { "subf/u",     0x181},
714         { "mulf/u",     0x182},
715         { "divf/u",     0x183},
716         { "cvtdg/u",    0x19e},
717         { "addg/u",     0x1a0},
718         { "subg/u",     0x1a1},
719         { "mulg/u",     0x1a2},
720         { "divg/u",     0x1a3},
721         { "cvtgf/u",    0x1ac},
722         { "cvtgd/u",    0x1ad},
723         { "cvtgq/v",    0x1af},
724         { "addf/sc",    0x400},
725         { "subf/sc",    0x401},
726         { "mulf/sc",    0x402},
727         { "divf/sc",    0x403},
728         { "cvtdg/sc",   0x41e},
729         { "addg/sc",    0x420},
730         { "subg/sc",    0x421},
731         { "mulg/sc",    0x422},
732         { "divg/sc",    0x423},
733         { "cvtgf/sc",   0x42c},
734         { "cvtgd/sc",   0x42d},
735         { "cvtgq/sc",   0x42f},
736         { "cvtqf/sc",   0x43c},
737         { "cvtqg/sc",   0x43e},
738         { "addf/s",     0x480},
739         { "subf/s",     0x481},
740         { "mulf/s",     0x482},
741         { "divf/s",     0x483},
742         { "cvtdg/s",    0x49e},
743         { "addg/s",     0x4a0},
744         { "subg/s",     0x4a1},
745         { "mulg/s",     0x4a2},
746         { "divg/s",     0x4a3},
747         { "cmpgeq/s",   0x4a5},
748         { "cmpglt/s",   0x4a6},
749         { "cmpgle/s",   0x4a7},
750         { "cvtgf/s",    0x4ac},
751         { "cvtgd/s",    0x4ad},
752         { "cvtgq/s",    0x4af},
753         { "cvtqf/s",    0x4bc},
754         { "cvtqg/s",    0x4be},
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},
767         { "addf/su",    0x580},
768         { "subf/su",    0x581},
769         { "mulf/su",    0x582},
770         { "divf/su",    0x583},
771         { "cvtdg/su",   0x59e},
772         { "addg/su",    0x5a0},
773         { "subg/su",    0x5a1},
774         { "mulg/su",    0x5a2},
775         { "divg/su",    0x5a3},
776         { "cvtgf/su",   0x5ac},
777         { "cvtgd/su",   0x5ad},
778         { "cvtgq/sv",   0x5af},
779         { 0, 0}
780 };
781
782 /*
783  * General purpose registers
784  */
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"
790 };
791
792 static int regcount;            /* how many regs used in this inst */
793 static int regnum[3];           /* which regs used in this inst */
794
795 static const char *register_name(int);
796
797 static const char *
798 register_name (ireg)
799         int ireg;
800 {
801         int     i;
802
803         for (i = 0; i < regcount; i++)
804                 if (regnum[i] == ireg)
805                         break;
806         if (i >= regcount)
807                 regnum[regcount++] = ireg;
808         return (name_of_register[ireg]);
809 }
810
811 /*
812  * Disassemble instruction at 'loc'.  'altfmt' specifies an
813  * (optional) alternate format.  Return address of start of
814  * next instruction.
815  */
816
817 static int
818 alpha_print_instr(db_addr_t iadr, alpha_instruction i, boolean_t showregs)
819 {
820         const char      *opcode;
821         int             ireg;
822         long            signed_immediate;
823         boolean_t       fstore;
824         pal_instruction p;
825
826         regcount = 0;
827         fstore = FALSE;
828         opcode = op_name[i.mem_format.opcode];
829
830         /*
831          *      Dispatch directly on the opcode, save code
832          *      duplication sometimes via "harmless gotos".
833          */
834         switch (i.mem_format.opcode) {
835         case op_pal:
836                 /* "call_pal" is a long string; just use a space. */
837                 db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
838                 break;
839         case op_lda:
840         case op_ldah:
841         case op_ldbu:
842         case op_ldq_u:
843         case op_ldwu:
844         case op_stw:
845         case op_stb:
846         case op_stq_u:
847                 /*
848                  * These loadstores are here to make compiling the
849                  * switch a bit easier.  Could embellish the output
850                  * someday, too.
851                  */
852                 goto loadstore;
853                 break;
854         case op_arit:
855                 /*
856                  * For this and the following three groups we
857                  * just need different opcode strings
858                  */
859                 opcode = arit_name(i.operate_lit_format.function);
860                 goto operate;
861                 break;
862         case op_logical:
863                 opcode = logical_name(i.operate_lit_format.function);
864                 goto operate;
865                 break;
866         case op_bit:
867                 opcode = bitop_name(i.operate_lit_format.function);
868                 goto operate;
869                 break;
870         case op_mul:
871                 opcode = mul_name(i.operate_lit_format.function);
872 operate:
873                 /*
874                  * Nice and uniform, just check for literals
875                  */
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);
880                 else
881                         db_printf("%s", register_name(i.operate_reg_format.rt));
882                 db_printf(",%s", register_name(i.operate_lit_format.rd));
883                 break;
884         case op_vax_float:
885                 /*
886                  * The three floating point groups are even simpler
887                  */
888                 opcode = vaxf_name(i.float_format.function);
889                 goto foperate;
890                 break;
891         case op_ieee_float:
892                 opcode = ieeef_name(i.float_format.function);
893                 goto foperate;
894                 break;
895         case op_any_float:
896                 opcode = anyf_name(i.float_format.function);
897 foperate:
898                 db_printf("%s\tf%d,f%d,f%d", opcode,
899                         i.float_format.fs,
900                         i.float_format.ft,
901                         i.float_format.fd);
902                 break;
903         case op_special:
904                 /*
905                  * Miscellaneous.
906                  */
907                 {
908                         register unsigned int code;
909
910                         code = (i.mem_format.displacement)&0xffff;
911                         opcode = special_name(code);
912
913                         switch (code) {
914                         case op_fetch:
915                         case op_fetch_m:
916                                 db_printf("%s\t0(%s)", opcode,
917                                         register_name(i.mem_format.rs));
918                                 break;
919                         case op_rpcc:
920                         case op_rc:
921                         case op_rs:
922                                 db_printf("%s\t%s", opcode,
923                                         register_name(i.mem_format.rd));
924                                 break;
925                         case op_draint:
926                         case op_mb:
927                         default:
928                                 db_printf("%s", opcode);
929                         break;
930                         }
931                 }
932                 break;
933         case op_j:
934                 /*
935                  * Jump instructions really are of two sorts,
936                  * depending on the use of the hint info.
937                  */
938                 opcode = jump_name(i.jump_format.action);
939                 switch (i.jump_format.action) {
940                 case op_jmp:
941                 case op_jsr:
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;
947                         break;
948                 case op_ret:
949                 case op_jcr:
950                         db_printf("%s\t%s,(%s)", opcode,
951                                 register_name(i.jump_format.rd),
952                                 register_name(i.jump_format.rs));
953                         break;
954                 }
955                 break;
956         case op_intmisc:
957                 /*
958                  * These are just in "operate" format.
959                  */
960                 opcode = intmisc_name(i.operate_lit_format.function);
961                 goto operate;
962                 break;
963                         /* HW instructions, possibly chip-specific XXXX */
964         case op_pal19:  /* "hw_mfpr" */
965         case op_pal1d:  /* "hw_mtpr" */
966                 p.bits = i.bits;
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);
971                 break;
972         case op_pal1b:  /* "hw_ld" */
973         case op_pal1f:  /* "hw_st" */
974                 p.bits = i.bits;
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;
981
982         case op_pal1e:  /* "hw_rei" */
983                 db_printf("\t%s", opcode);
984                 break;
985
986         case op_ldf:
987         case op_ldg:
988         case op_lds:
989         case op_ldt:
990         case op_stf:
991         case op_stg:
992         case op_sts:
993         case op_stt:
994                 fstore = TRUE;
995                 /* FALLTHROUGH */
996         case op_ldl:
997         case op_ldq:
998         case op_ldl_l:
999         case op_ldq_l:
1000         case op_stl:
1001         case op_stq:
1002         case op_stl_c:
1003         case op_stq_c:
1004                 /*
1005                  * Memory operations, including floats
1006                  */
1007 loadstore:
1008                 if (fstore)
1009                     db_printf("%s\tf%d,", opcode, i.mem_format.rd);
1010                 else
1011                     db_printf("%s\t%s,", opcode,
1012                         register_name(i.mem_format.rd));
1013                 signed_immediate = (long)i.mem_format.displacement;
1014 loadstore_address:
1015                 db_printf("%#lx(%s)", signed_immediate,
1016                         register_name(i.mem_format.rs));
1017                 /*
1018                  * For convenience, do the address computation
1019                  */
1020                 if (showregs) {
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));
1025                 }
1026                 break;
1027         case op_br:
1028         case op_fbeq:
1029         case op_fblt:
1030         case op_fble:
1031         case op_bsr:
1032         case op_fbne:
1033         case op_fbge:
1034         case op_fbgt:
1035         case op_blbc:
1036         case op_beq:
1037         case op_blt:
1038         case op_ble:
1039         case op_blbs:
1040         case op_bne:
1041         case op_bge:
1042         case op_bgt:
1043                 /*
1044                  * We want to know where we are branching to
1045                  */
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);
1052                 break;
1053         default:
1054                 /*
1055                  * Shouldn't happen
1056                  */
1057                 db_printf("? 0x%x ?", i.bits);
1058         }
1059
1060         /*
1061          *      Print out the registers used in this instruction
1062          */
1063         if (showregs && regcount > 0) {
1064                 db_printf("\t<");
1065                 for (ireg = 0; ireg < regcount; ireg++) {
1066                         if (ireg != 0)
1067                                 db_printf(",");
1068                         db_printf("%s=0x%lx",
1069                             name_of_register[regnum[ireg]],
1070                             db_register_value(regnum[ireg]));
1071                 }
1072                 db_printf(">");
1073         }
1074         db_printf("\n");
1075         return (sizeof(alpha_instruction));
1076 }
1077
1078 db_addr_t
1079 db_disasm(loc, altfmt)
1080         db_addr_t       loc;
1081         boolean_t       altfmt;
1082 {
1083         alpha_instruction inst;
1084
1085         inst.bits = db_get_value(loc, 4, 0);
1086
1087         loc += alpha_print_instr(loc, inst, altfmt);
1088         return (loc);
1089 }