]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/alpha/alpha/db_disasm.c
This commit was generated by cvs2svn to compensate for changes in r57093,
[FreeBSD/FreeBSD.git] / sys / alpha / alpha / db_disasm.c
1 /* $NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $ */
2
3 /* 
4  * Mach Operating System
5  * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
6  * All Rights Reserved.
7  * 
8  * Permission to use, copy, modify and distribute this software and its
9  * documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  * 
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  * 
18  * Carnegie Mellon requests users of this software to return to
19  * 
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  * 
25  * any improvements or extensions that they make and grant Carnegie Mellon
26  * the rights to redistribute these changes.
27  */
28
29 /*
30  *      File: db_disasm.c
31  *      Author: Alessandro Forin, Carnegie Mellon University
32  *      Date:   11/91
33  *
34  *      Disassembler for Alpha
35  *
36  *      Modified for NetBSD/alpha by:
37  *
38  *      Christopher G. Demetriou, Carnegie Mellon University
39  *
40  *      Jason R. Thorpe, Numerical Aerospace Simulation Facility,
41  *      NASA Ames Research Center
42  *
43  *      This code was derived exclusively from information available in
44  *      "Alpha Architecture Reference Manual", Richard L. Sites ed.
45  *      Digital Press, Burlington, MA 01803
46  *      ISBN 1-55558-098-X, Order no. EY-L520E-DP
47  */
48
49 #include <sys/cdefs.h>                  /* RCS ID & Copyright macro defns */
50
51 /* __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.4 1997/09/16 22:52:40 thorpej Exp $"); */
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/proc.h>
56 #include <machine/db_machdep.h>
57 #include <alpha/alpha/db_instruction.h>
58
59 #include <machine/pal.h>
60  
61 #include <ddb/ddb.h>
62 #include <ddb/db_access.h>
63 #include <ddb/db_sym.h>
64 #include <ddb/db_output.h>
65
66 /*
67  * This would belong in a header file, except noone else needs it
68  */
69 typedef union {
70         /*
71          *      All instructions are 32 bits wide, PAL included
72          */
73         unsigned int    bits;
74
75         /*
76          *      Internal processor register access instrs
77          *      specify the IPR index, doubly specify the
78          *      (same) GP register as src/dest, and qualifiers
79          *      for the IPR set involved (abox/ibox/tmp)
80          */
81         struct {
82                 unsigned        index : 5,
83                                 regset : 3, /* a,i,p */
84                                 xxx : 8,
85                                 rs : 5,
86                                 rd : 5,
87                                 opcode : 6;
88         } mXpr_format;
89
90         /*
91          *      Load/store instructions have a 12 bit displacement,
92          *      and two register specifiers just as normal ld/st.
93          *      Four bits have special meanings:
94          *              phy: bypass the MMU (physical access)
95          *              alt: use mode in ALT register for checks,
96          *                   or if PHY is also on locked/linked access
97          *              rwc: read-with-write-check (probew)
98          *              qw:  quadword access
99          */
100         struct {
101                 signed int      displacement : 12;
102                 unsigned        qw : 1,
103                                 qualif : 3,
104                                 rs : 5,
105                                 rd : 5,
106                                 opcode : 6;
107         } mem_format;
108
109         /*
110          *      Return from exception or interrupt has
111          *      a branch-like encoding, but only one
112          *      instantiation is actually usable.
113          */
114         struct {
115                 unsigned        xxx : 14,
116                                 zero : 1,       /* branch prediction! */
117                                 one : 1,
118                                 rb : 5,         /* r31 or stall */
119                                 ra : 5,         /* r31 or stall */
120                                 opcode : 6;
121         } rei_format;
122
123 } pal_instruction;
124
125
126 /*
127  * Major opcodes
128  */
129 static char *op_name[64] = {
130 /* 0 */ "call_pal", "op1", "op2", "op3", "op4", "op5",  "op6",  "op7",
131 /* 8 */ "lda",  "ldah", "ldbu", "ldq_u","ldwu", "stw",  "stb",  "stq_u",
132 /*16 */ "arit", "logical","bit","mul",  "op20", "vaxf", "ieeef","anyf",
133 /*24 */ "spec", "hw_mfpr","jump","hw_ld","intmisc","hw_mtpr","hw_rei","hw_st",
134 /*32 */ "ldf",  "ldg",  "lds",  "ldt",  "stf",  "stg",  "sts",  "stt",
135 /*40 */ "ldl",  "ldq",  "ldl_l","ldq_l","stl",  "stq",  "stl_c","stq_c",
136 /*48 */ "br",   "fbeq", "fblt", "fble", "bsr",  "fbne", "fbge", "fbgt",
137 /*56 */ "blbc", "beq",  "blt",  "ble",  "blbs", "bne",  "bge",  "bgt"
138 };
139
140 /*
141  * The function field is too big (7 or 11 bits), so the sub-tables
142  * are addressed in a somewhat complicated manner to save
143  * space.  After all, alu operations is what RISCs are good at.
144  */
145
146 struct tbl {
147         const char      *name;
148         int             code;
149 };
150
151 static const struct tbl pal_op_tbl[] = {
152         /* Common PAL function codes. */
153         { "halt",               PAL_halt },
154         { "cflush",             PAL_cflush },
155         { "draina",             PAL_draina },
156         { "cserve",             PAL_cserve, },
157         { "swppal",             PAL_swppal },
158         { "ipir",               PAL_ipir },
159         { "bpt",                PAL_bpt },
160         { "bugchk",             PAL_bugchk },
161         { "imb",                PAL_imb },
162         { "rdunique",           PAL_rdunique },
163         { "wrunique",           PAL_wrunique },
164         { "gentrap",            PAL_gentrap },
165
166         /* OSF/1 PAL function codes. */
167         { "osf1_rdmces",        PAL_OSF1_rdmces },
168         { "osf1_wrmces",        PAL_OSF1_wrmces },
169         { "osf1_wrfen",         PAL_OSF1_wrfen },
170         { "osf1_wrvptptr",      PAL_OSF1_wrvptptr },
171         { "osf1_swpctx",        PAL_OSF1_swpctx },
172         { "osf1_wrval",         PAL_OSF1_wrval },
173         { "osf1_rdval",         PAL_OSF1_rdval },
174         { "osf1_tbi",           PAL_OSF1_tbi },
175         { "osf1_wrent",         PAL_OSF1_wrent },
176         { "osf1_swpipl",        PAL_OSF1_swpipl },
177         { "osf1_rdps",          PAL_OSF1_rdps },
178         { "osf1_wrkgp",         PAL_OSF1_wrkgp },
179         { "osf1_wrusp",         PAL_OSF1_wrusp },
180         { "osf1_wrperfmon",     PAL_OSF1_wrperfmon },
181         { "osf1_rdusp",         PAL_OSF1_rdusp },
182         { "osf1_whami",         PAL_OSF1_whami },
183         { "osf1_retsys",        PAL_OSF1_retsys },
184         { "osf1_rti",           PAL_OSF1_rti },
185         { "osf1_callsys",       PAL_OSF1_callsys },
186
187         { NULL,                 -1 },
188 };
189
190 static const char *pal_opname __P((int));
191
192 static const char *
193 pal_opname(op)
194         int op;
195 {
196         static char unk[8];
197         int i;
198
199         for (i = 0; pal_op_tbl[i].name != NULL; i++) {
200                 if (pal_op_tbl[i].code == op)
201                         return (pal_op_tbl[i].name);
202         }
203
204         snprintf(unk, sizeof(unk), "0x%x", op);
205         return (unk);
206 }
207
208 /* HW (PAL) instruction qualifiers, stright tables */
209 static const char *mXpr_name[8] = {
210         "", "/i", "/a", "/ai", "/p", "/pi", "/pa", "/pai"
211 };
212 static const char *hwlds_name[8] = {
213         "", "/r", "/a", "/ar", "/p", "/p?r", "_l-c", "_l-c/?r"
214 };
215
216 /*
217  * For this one we take the low nibble (valid values 0/2/9/b/d)
218  * and shift it down one to get the row index.  Within a row
219  * we can just take the high nibble deprived of the high bit
220  * (valid values 0/1/2/3/4/6).  We could have used a flat 64
221  * entry array, but in this way we use just 48 pointers.
222  * BUGFIX: the 'cmpbge 0x0f' opcode fits in here too
223  */
224 static const char *arit_c0[8] = {
225         "addl", 0, "addq", 0, "addl/v", 0, "addq/v",
226 };
227 static const char *arit_c2[8] = {
228         "s4addl", "s8addl", "s4addq", "s8addq", 
229 };
230 static const char *arit_c9[8] = {
231         "subl", 0, "subq", 0, "subl/v", 0, "subq/v", 
232 };
233 static const char *arit_cB[8] = {
234         "s4subl", "s8subl", "s4subq", "s8subq", 
235 };
236 static const char *arit_cD[8] = {
237         0, "cmpult", "cmpeq", "cmpule", "cmplt", 0, "cmple",
238 };
239 static const char *arit_cF[1] = {
240         "cmpbge"
241 };
242 static const char **arit_opname[8] = {
243         arit_c0, arit_c2, 0, 0, arit_c9, arit_cB, arit_cD, arit_cF
244 };
245
246 static __inline const char *arit_name __P((int));
247 static __inline const char *
248 arit_name(op)
249         int op;
250 {
251         static char unk[32];
252         const char *name = NULL;
253
254         if (arit_opname[((op)&0xe)>>1])
255                 name = arit_opname[((op)&0xe)>>1][((op)&0x70)>>4];
256
257         if (name != NULL)
258                 return (name);
259
260         snprintf(unk, sizeof(unk), "?arit 0x%x?", op);
261         return (unk);
262 }
263
264 /*
265  * Something similar for this one, except there are only
266  * 16 entries so the row indexing is done by enumeration
267  * of the low nibble (valid values 0/4/6/8).  Then we can
268  * just shift the high nibble to index inside the row
269  * (valid values are 0/2/4 or 1/2/4/6)
270  *
271  * There are two functions that don't play by these simple rules,
272  * so we special-case them.
273  */
274 static const char *logical_c0[4] = {
275         "and", "or", "xor", 0
276 };
277 static const char *logical_c4[4] = {
278         "cmovlbs", "cmoveq", "cmovlt", "cmovle"
279 };
280 static const char *logical_c6[4] = {
281         "cmovlbc", "cmovne", "cmovge", "cmovgt"
282 };
283 static const char *logical_c8[4] = {
284         "andnot", "ornot", "xornot", 0
285 };
286
287 static __inline const char *logical_name __P((int));
288 static __inline const char *
289 logical_name(op)
290         int op;
291 {
292         static char unk[32];
293         const char *name = NULL;
294
295         if (op == op_amask)
296                 return ("amask");
297         else if (op == op_implver)
298                 return ("implver");
299
300         switch (op & 0xf) {
301         case 0: name = logical_c0[((op)>>5)&3]; break;
302         case 4: name = logical_c4[((op)>>5)&3]; break;
303         case 6: name = logical_c6[((op)>>5)&3]; break;
304         case 8: name = logical_c8[((op)>>5)&3]; break;
305         }
306
307         if (name != NULL)
308                 return (name);
309
310         snprintf(unk, sizeof(unk), "?logical 0x%x?", op);
311         return (unk);
312 }
313
314 /*
315  * This is the messy one. First, we single out the dense
316  * case of a 3 in the high nibble (valid values 0/1/2/4/6/9/b/c).
317  * Then the case of a 2 in the low nibble (valid values 0/1/2/5/6/7).
318  * For the remaining codes (6/7/a/b) we do as above: high
319  * nibble has valid values 0/1/2 or 5/6/7.  The low nibble
320  * can be used as row index picking bits 0 and 2, for the
321  * high one just the lower two bits.
322  */
323 static const char *bitop_c3[8] = {
324         "zapnot", "mskql", "srl", "extql", "sll", "insql", "sra", 0
325 };
326 static const char *bitop_c2[8] = {
327         "mskbl", "mskwl", "mskll", 0/*mskql*/, 0, "mskwh", "msklh", "mskqh"
328 };
329 static const char *bitop_c67ab[4][4] = {
330 /* a */ { 0, "extwh", "extlh", "extqh"},
331 /* b */ { "insbl", "inswl", "insll", 0 },
332 /* 6 */ { "extbl", "extwl", "extll", 0 },
333 /* 7 */ { 0, "inswh", "inslh", "insqh" },
334 };
335
336 static __inline const char *bitop_name __P((int));
337 static __inline const char *
338 bitop_name(op)
339         int op;
340 {
341         static char unk[32];
342         const char *name = NULL;
343
344         if ((op & 0x70) == 0x30)
345                 name = (op == op_zap) ? "zap" : bitop_c3[((op)&0xe)>>1];
346         else if ((op & 0xf) == 0x02)
347                 name = bitop_c2[(op)>>4];
348         else
349                 name =
350                     bitop_c67ab[(((op)&1)|(((op)&0x4)>>1))][(((op)&0x30)>>4)];
351
352         if (name != NULL)
353                 return (name);
354
355         snprintf(unk, sizeof(unk), "?bit 0x%x?", op);
356         return (unk);
357 }
358
359 /*
360  * Only 5 entries in this one
361  */
362 static const char *mul_opname[4] = {
363         "mull", "mulq", "mull/v", "mulq/v"
364 };
365
366 static __inline const char *mul_name __P((int));
367 static __inline const char *
368 mul_name(op)
369         int op;
370 {
371         static char unk[32];
372         const char *name = NULL;
373
374         name = (op == op_umulh) ? "umulh" : mul_opname[((op)>>5)&3];
375
376         if (name != NULL)
377                 return (name);
378
379         snprintf(unk, sizeof(unk), "?mul 0x%x?", op);
380         return (unk);
381 }
382
383 /*
384  * These are few, the high nibble is enough to dispatch.
385  * We single out the "f" case to halve the table size.
386  */
387 static const char *special_opname[8] = {
388         "drain_t", 0, "mb", 0, "fetch", "fetch_m", "rpcc", "rc"
389 };
390
391 static __inline const char *special_name __P((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         name = (op == op_rs) ? "rs" : special_opname[(op)>>13];
400
401         if (name != NULL)
402                 return (name);
403
404         snprintf(unk, sizeof(unk), "?special 0x%x?", op);
405         return (unk);
406 }
407
408 /*
409  * This is trivial
410  */
411 static const char *jump_opname[4] = {
412         "jmp", "jsr", "ret", "jcr"
413 };
414 #define jump_name(ix)   jump_opname[ix]
415
416 /*
417  * For all but 4 of these, we can dispatch on the lower nibble of
418  * the "function".
419  */
420 static const char *intmisc_opname_3x[16] = {
421         "ctpop", "perr", "ctlz", "cttz", "unpkbw", "unpkbl", "pkwb",
422         "pklb", "minsb8", "minsw4", "minub8", "minuw4", "maxub8",
423         "maxuw4", "maxsb8", "maxsw4",
424 };
425
426 static __inline const char *intmisc_name __P((int));
427 static __inline const char *
428 intmisc_name(op)
429         int op;
430 {
431         static char unk[32];
432
433         if ((op & 0xf0) == 0x30)
434                 return (intmisc_opname_3x[op & 0x0f]);
435
436         switch (op) {
437         case op_sextb: return ("sextb");
438         case op_sextw: return ("sextw");
439         case op_ftoit: return ("ftoit");
440         case op_ftois: return ("ftois");
441         }
442
443         snprintf(unk, sizeof(unk), "?intmisc 0x%x?", op);
444         return (unk);
445 }
446
447 static const char *float_name __P((const struct tbl[], int, const char *type));
448
449 static const char *
450 float_name(tbl, op, type)
451         const struct tbl tbl[];
452         int op;
453         const char *type;
454 {
455         static char unk[32];
456         int i;
457
458         for (i = 0; tbl[i].name != NULL; i++) {
459                 if (tbl[i].code == op)
460                         return (tbl[i].name);
461         }
462
463         snprintf(unk, sizeof(unk), "?%s 0x%x?", type, op);
464         return (unk);
465 }
466
467 #define vaxf_name(op)   float_name(vaxf_tbl, op, "vaxfl")
468 #define ieeef_name(op)  float_name(ieeef_tbl, op, "ieeefl")
469 #define anyf_name(op)   float_name(anyf_tbl, op, "anyfl")
470
471 static const struct tbl anyf_tbl[] = {
472         { "cvtlq",      0x010},
473         { "cpys",       0x020},
474         { "cpysn",      0x021},
475         { "cpyse",      0x022},
476         { "mt_fpcr",    0x024},
477         { "mf_fpcr",    0x025},
478         { "fcmoveq",    0x02a},
479         { "fcmovne",    0x02b},
480         { "fcmovlt",    0x02c},
481         { "fcmovge",    0x02d},
482         { "fcmovle",    0x02e},
483         { "fcmovgt",    0x02f},
484         { "cvtql",      0x030},
485         { "cvtql/v",    0x130},
486         { "cvtql/sv",   0x330},
487         { 0, 0},
488 };
489
490 static const struct tbl ieeef_tbl[] = {
491         { "adds/c",     0x000},
492         { "subs/c",     0x001},
493         { "muls/c",     0x002},
494         { "divs/c",     0x003},
495         { "addt/c",     0x020},
496         { "subt/c",     0x021},
497         { "mult/c",     0x022},
498         { "divt/c",     0x023},
499         { "cvtts/c",    0x02c},
500         { "cvttq/c",    0x02f},
501         { "cvtqs/c",    0x03c},
502         { "cvtqt/c",    0x03e},
503         { "adds/m",     0x040},
504         { "subs/m",     0x041},
505         { "muls/m",     0x042},
506         { "divs/m",     0x043},
507         { "addt/m",     0x060},
508         { "subt/m",     0x061},
509         { "mult/m",     0x062},
510         { "divt/m",     0x063},
511         { "cvtts/m",    0x06c},
512         { "cvtqs/m",    0x07c},
513         { "cvtqt/m",    0x07e},
514         { "adds",       0x080},
515         { "subs",       0x081},
516         { "muls",       0x082},
517         { "divs",       0x083},
518         { "addt",       0x0a0},
519         { "subt",       0x0a1},
520         { "mult",       0x0a2},
521         { "divt",       0x0a3},
522         { "cmptun",     0x0a4},
523         { "cmpteq",     0x0a5},
524         { "cmptlt",     0x0a6},
525         { "cmptle",     0x0a7},
526         { "cvtts",      0x0ac},
527         { "cvttq",      0x0af},
528         { "cvtqs",      0x0bc},
529         { "cvtqt",      0x0be},
530         { "adds/d",     0x0c0},
531         { "subs/d",     0x0c1},
532         { "muls/d",     0x0c2},
533         { "divs/d",     0x0c3},
534         { "addt/d",     0x0e0},
535         { "subt/d",     0x0e1},
536         { "mult/d",     0x0e2},
537         { "divt/d",     0x0e3},
538         { "cvtts/d",    0x0ec},
539         { "cvtqs/d",    0x0fc},
540         { "cvtqt/d",    0x0fe},
541         { "adds/uc",    0x100},
542         { "subs/uc",    0x101},
543         { "muls/uc",    0x102},
544         { "divs/uc",    0x103},
545         { "addt/uc",    0x120},
546         { "subt/uc",    0x121},
547         { "mult/uc",    0x122},
548         { "divt/uc",    0x123},
549         { "cvtts/uc",   0x12c},
550         { "cvttq/vc",   0x12f},
551         { "adds/um",    0x140},
552         { "subs/um",    0x141},
553         { "muls/um",    0x142},
554         { "divs/um",    0x143},
555         { "addt/um",    0x160},
556         { "subt/um",    0x161},
557         { "mult/um",    0x162},
558         { "divt/um",    0x163},
559         { "cvtts/um",   0x16c},
560         { "adds/u",     0x180},
561         { "subs/u",     0x181},
562         { "muls/u",     0x182},
563         { "divs/u",     0x183},
564         { "addt/u",     0x1a0},
565         { "subt/u",     0x1a1},
566         { "mult/u",     0x1a2},
567         { "divt/u",     0x1a3},
568         { "cvtts/u",    0x1ac},
569         { "cvttq/v",    0x1af},
570         { "adds/ud",    0x1c0},
571         { "subs/ud",    0x1c1},
572         { "muls/ud",    0x1c2},
573         { "divs/ud",    0x1c3},
574         { "addt/ud",    0x1e0},
575         { "subt/ud",    0x1e1},
576         { "mult/ud",    0x1e2},
577         { "divt/ud",    0x1e3},
578         { "cvtts/ud",   0x1ec},
579         { "adds/suc",   0x500},
580         { "subs/suc",   0x501},
581         { "muls/suc",   0x502},
582         { "divs/suc",   0x503},
583         { "addt/suc",   0x520},
584         { "subt/suc",   0x521},
585         { "mult/suc",   0x522},
586         { "divt/suc",   0x523},
587         { "cvtts/suc",  0x52c},
588         { "cvttq/svc",  0x52f},
589         { "adds/sum",   0x540},
590         { "subs/sum",   0x541},
591         { "muls/sum",   0x542},
592         { "divs/sum",   0x543},
593         { "addt/sum",   0x560},
594         { "subt/sum",   0x561},
595         { "mult/sum",   0x562},
596         { "divt/sum",   0x563},
597         { "cvtts/sum",  0x56c},
598         { "adds/su",    0x580},
599         { "subs/su",    0x581},
600         { "muls/su",    0x582},
601         { "divs/su",    0x583},
602         { "addt/su",    0x5a0},
603         { "subt/su",    0x5a1},
604         { "mult/su",    0x5a2},
605         { "divt/su",    0x5a3},
606         { "cmptun/su",  0x5a4},
607         { "cmpteq/su",  0x5a5},
608         { "cmptlt/su",  0x5a6},
609         { "cmptle/su",  0x5a7},
610         { "cvtts/su",   0x5ac},
611         { "cvttq/sv",   0x5af},
612         { "adds/sud",   0x5c0},
613         { "subs/sud",   0x5c1},
614         { "muls/sud",   0x5c2},
615         { "divs/sud",   0x5c3},
616         { "addt/sud",   0x5e0},
617         { "subt/sud",   0x5e1},
618         { "mult/sud",   0x5e2},
619         { "divt/sud",   0x5e3},
620         { "cvtts/sud",  0x5ec},
621         { "adds/suic",  0x700},
622         { "subs/suic",  0x701},
623         { "muls/suic",  0x702},
624         { "divs/suic",  0x703},
625         { "addt/suic",  0x720},
626         { "subt/suic",  0x721},
627         { "mult/suic",  0x722},
628         { "divt/suic",  0x723},
629         { "cvtts/suic", 0x72c},
630         { "cvttq/svic", 0x72f},
631         { "cvtqs/suic", 0x73c},
632         { "cvtqt/suic", 0x73e},
633         { "adds/suim",  0x740},
634         { "subs/suim",  0x741},
635         { "muls/suim",  0x742},
636         { "divs/suim",  0x743},
637         { "addt/suim",  0x760},
638         { "subt/suim",  0x761},
639         { "mult/suim",  0x762},
640         { "divt/suim",  0x763},
641         { "cvtts/suim", 0x76c},
642         { "cvtqs/suim", 0x77c},
643         { "cvtqt/suim", 0x77e},
644         { "adds/sui",   0x780},
645         { "subs/sui",   0x781},
646         { "muls/sui",   0x782},
647         { "divs/sui",   0x783},
648         { "addt/sui",   0x7a0},
649         { "subt/sui",   0x7a1},
650         { "mult/sui",   0x7a2},
651         { "divt/sui",   0x7a3},
652         { "cvtts/sui",  0x7ac},
653         { "cvttq/svi",  0x7af},
654         { "cvtqs/sui",  0x7bc},
655         { "cvtqt/sui",  0x7be},
656         { "adds/suid",  0x7c0},
657         { "subs/suid",  0x7c1},
658         { "muls/suid",  0x7c2},
659         { "divs/suid",  0x7c3},
660         { "addt/suid",  0x7e0},
661         { "subt/suid",  0x7e1},
662         { "mult/suid",  0x7e2},
663         { "divt/suid",  0x7e3},
664         { "cvtts/suid", 0x7ec},
665         { "cvtqs/suid", 0x7fc},
666         { "cvtqt/suid", 0x7fe},
667         { 0, 0}
668 };
669
670 static const struct tbl vaxf_tbl[] = {
671         { "addf/c",     0x000},
672         { "subf/c",     0x001},
673         { "mulf/c",     0x002},
674         { "divf/c",     0x003},
675         { "cvtdg/c",    0x01e},
676         { "addg/c",     0x020},
677         { "subg/c",     0x021},
678         { "mulg/c",     0x022},
679         { "divg/c",     0x023},
680         { "cvtgf/c",    0x02c},
681         { "cvtgd/c",    0x02d},
682         { "cvtgq/c",    0x02f},
683         { "cvtqf/c",    0x03c},
684         { "cvtqg/c",    0x03e},
685         { "addf",       0x080},
686         { "subf",       0x081},
687         { "mulf",       0x082},
688         { "divf",       0x083},
689         { "cvtdg",      0x09e},
690         { "addg",       0x0a0},
691         { "subg",       0x0a1},
692         { "mulg",       0x0a2},
693         { "divg",       0x0a3},
694         { "cmpgeq",     0x0a5},
695         { "cmpglt",     0x0a6},
696         { "cmpgle",     0x0a7},
697         { "cvtgf",      0x0ac},
698         { "cvtgd",      0x0ad},
699         { "cvtgq",      0x0af},
700         { "cvtqf",      0x0bc},
701         { "cvtqg",      0x0be},
702         { "addf/uc",    0x100},
703         { "subf/uc",    0x101},
704         { "mulf/uc",    0x102},
705         { "divf/uc",    0x103},
706         { "cvtdg/uc",   0x11e},
707         { "addg/uc",    0x120},
708         { "subg/uc",    0x121},
709         { "mulg/uc",    0x122},
710         { "divg/uc",    0x123},
711         { "cvtgf/uc",   0x12c},
712         { "cvtgd/uc",   0x12d},
713         { "cvtgq/vc",   0x12f},
714         { "addf/u",     0x180},
715         { "subf/u",     0x181},
716         { "mulf/u",     0x182},
717         { "divf/u",     0x183},
718         { "cvtdg/u",    0x19e},
719         { "addg/u",     0x1a0},
720         { "subg/u",     0x1a1},
721         { "mulg/u",     0x1a2},
722         { "divg/u",     0x1a3},
723         { "cvtgf/u",    0x1ac},
724         { "cvtgd/u",    0x1ad},
725         { "cvtgq/v",    0x1af},
726         { "addf/sc",    0x400},
727         { "subf/sc",    0x401},
728         { "mulf/sc",    0x402},
729         { "divf/sc",    0x403},
730         { "cvtdg/sc",   0x41e},
731         { "addg/sc",    0x420},
732         { "subg/sc",    0x421},
733         { "mulg/sc",    0x422},
734         { "divg/sc",    0x423},
735         { "cvtgf/sc",   0x42c},
736         { "cvtgd/sc",   0x42d},
737         { "cvtgq/sc",   0x42f},
738         { "cvtqf/sc",   0x43c},
739         { "cvtqg/sc",   0x43e},
740         { "addf/s",     0x480},
741         { "subf/s",     0x481},
742         { "mulf/s",     0x482},
743         { "divf/s",     0x483},
744         { "cvtdg/s",    0x49e},
745         { "addg/s",     0x4a0},
746         { "subg/s",     0x4a1},
747         { "mulg/s",     0x4a2},
748         { "divg/s",     0x4a3},
749         { "cmpgeq/s",   0x4a5},
750         { "cmpglt/s",   0x4a6},
751         { "cmpgle/s",   0x4a7},
752         { "cvtgf/s",    0x4ac},
753         { "cvtgd/s",    0x4ad},
754         { "cvtgq/s",    0x4af},
755         { "cvtqf/s",    0x4bc},
756         { "cvtqg/s",    0x4be},
757         { "addf/suc",   0x500},
758         { "subf/suc",   0x501},
759         { "mulf/suc",   0x502},
760         { "divf/suc",   0x503},
761         { "cvtdg/suc",  0x51e},
762         { "addg/suc",   0x520},
763         { "subg/suc",   0x521},
764         { "mulg/suc",   0x522},
765         { "divg/suc",   0x523},
766         { "cvtgf/suc",  0x52c},
767         { "cvtgd/suc",  0x52d},
768         { "cvtgq/svc",  0x52f},
769         { "addf/su",    0x580},
770         { "subf/su",    0x581},
771         { "mulf/su",    0x582},
772         { "divf/su",    0x583},
773         { "cvtdg/su",   0x59e},
774         { "addg/su",    0x5a0},
775         { "subg/su",    0x5a1},
776         { "mulg/su",    0x5a2},
777         { "divg/su",    0x5a3},
778         { "cvtgf/su",   0x5ac},
779         { "cvtgd/su",   0x5ad},
780         { "cvtgq/sv",   0x5af},
781         { 0, 0}
782 };
783
784 /*
785  * General purpose registers
786  */
787 static const char *name_of_register[32] = {
788         "v0",   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",
789         "t7",   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",
790         "a0",   "a1",   "a2",   "a3",   "a4",   "a5",   "t8",   "t9",
791         "t10",  "t11",  "ra",   "pv",   "at",   "gp",   "sp",   "zero"
792 };
793
794 static int regcount;            /* how many regs used in this inst */
795 static int regnum[3];           /* which regs used in this inst */
796
797 static const char *register_name __P((int));
798
799 static const char *
800 register_name (ireg)
801         int ireg;
802 {
803         int     i;
804
805         for (i = 0; i < regcount; i++)
806                 if (regnum[i] == ireg)
807                         break;
808         if (i >= regcount)
809                 regnum[regcount++] = ireg;
810         return (name_of_register[ireg]);
811 }
812
813 /*
814  * Disassemble instruction at 'loc'.  'altfmt' specifies an
815  * (optional) alternate format.  Return address of start of
816  * next instruction.
817  */
818 int     alpha_print_instruction __P((db_addr_t, alpha_instruction, boolean_t));
819
820 db_addr_t
821 db_disasm(loc, altfmt)
822         db_addr_t       loc;
823         boolean_t       altfmt;
824 {
825         alpha_instruction inst;
826
827         inst.bits = db_get_value(loc, 4, 0);
828
829         loc += alpha_print_instruction(loc, inst, altfmt);
830         return (loc);
831 }
832
833 int
834 alpha_print_instruction(iadr, i, showregs)
835         db_addr_t       iadr;
836         alpha_instruction i;
837         boolean_t       showregs;
838 {
839         const char      *opcode;
840         int             ireg;
841         long            signed_immediate;
842         boolean_t       fstore;
843         pal_instruction p;
844
845         regcount = 0;
846         fstore = FALSE;
847         opcode = op_name[i.mem_format.opcode];
848
849         /*
850          *      Dispatch directly on the opcode, save code
851          *      duplication sometimes via "harmless gotos".
852          */
853         switch (i.mem_format.opcode) {
854         case op_pal:
855                 /* "call_pal" is a long string; just use a space. */
856                 db_printf("%s %s", opcode, pal_opname(i.pal_format.function));
857                 break;
858         case op_lda:
859         case op_ldah:
860         case op_ldbu:
861         case op_ldq_u:
862         case op_ldwu:
863         case op_stw:
864         case op_stb:
865         case op_stq_u:
866                 /*
867                  * These loadstores are here to make compiling the
868                  * switch a bit easier.  Could embellish the output
869                  * someday, too.
870                  */
871                 goto loadstore;
872                 break;
873         case op_arit:
874                 /*
875                  * For this and the following three groups we
876                  * just need different opcode strings
877                  */
878                 opcode = arit_name(i.operate_lit_format.function);
879                 goto operate;
880                 break;
881         case op_logical:
882                 opcode = logical_name(i.operate_lit_format.function);
883                 goto operate;
884                 break;
885         case op_bit:
886                 opcode = bitop_name(i.operate_lit_format.function);
887                 goto operate;
888                 break;
889         case op_mul:
890                 opcode = mul_name(i.operate_lit_format.function);
891 operate:
892                 /*
893                  * Nice and uniform, just check for literals
894                  */
895                 db_printf("%s\t%s,", opcode,
896                     register_name(i.operate_lit_format.rs));
897                 if (i.operate_lit_format.one)
898                         db_printf("#0x%x", i.operate_lit_format.literal);
899                 else
900                         db_printf("%s", register_name(i.operate_reg_format.rt));
901                 db_printf(",%s", register_name(i.operate_lit_format.rd));
902                 break;
903         case op_vax_float:
904                 /*
905                  * The three floating point groups are even simpler
906                  */
907                 opcode = vaxf_name(i.float_format.function);
908                 goto foperate;
909                 break;
910         case op_ieee_float:
911                 opcode = ieeef_name(i.float_format.function);
912                 goto foperate;
913                 break;
914         case op_any_float:
915                 opcode = anyf_name(i.float_format.function);
916 foperate:
917                 db_printf("%s\tf%d,f%d,f%d", opcode,
918                         i.float_format.fs,
919                         i.float_format.ft,
920                         i.float_format.fd);
921                 break;
922         case op_special:
923                 /*
924                  * Miscellaneous.
925                  */
926                 {
927                         register unsigned int code;
928
929                         code = (i.mem_format.displacement)&0xffff;
930                         opcode = special_name(code);
931
932                         switch (code) {
933                         case op_fetch:
934                         case op_fetch_m:
935                                 db_printf("%s\t0(%s)", opcode,
936                                         register_name(i.mem_format.rs));
937                                 break;
938                         case op_rpcc:
939                         case op_rc:
940                         case op_rs:
941                                 db_printf("%s\t%s", opcode,
942                                         register_name(i.mem_format.rd));
943                                 break;
944                         case op_draint:
945                         case op_mb:
946                         default:
947                                 db_printf("%s", opcode);
948                         break;
949                         }
950                 }
951                 break;
952         case op_j:
953                 /*
954                  * Jump instructions really are of two sorts,
955                  * depending on the use of the hint info.
956                  */
957                 opcode = jump_name(i.jump_format.action);
958                 switch (i.jump_format.action) {
959                 case op_jmp:
960                 case op_jsr:
961                         db_printf("%s\t%s,(%s),", opcode,
962                                 register_name(i.jump_format.rd),
963                                 register_name(i.jump_format.rs));
964                         signed_immediate = i.jump_format.hint;
965                         goto branch_displacement;
966                         break;
967                 case op_ret:
968                 case op_jcr:
969                         db_printf("%s\t%s,(%s)", opcode,
970                                 register_name(i.jump_format.rd),
971                                 register_name(i.jump_format.rs));
972                         break;
973                 }
974                 break;
975         case op_intmisc:
976                 /*
977                  * These are just in "operate" format.
978                  */
979                 opcode = intmisc_name(i.operate_lit_format.function);
980                 goto operate;
981                 break;
982                         /* HW instructions, possibly chip-specific XXXX */
983         case op_pal19:  /* "hw_mfpr" */
984         case op_pal1d:  /* "hw_mtpr" */
985                 p.bits = i.bits;
986                 db_printf("\t%s%s\t%s, %d", opcode,
987                         mXpr_name[p.mXpr_format.regset],
988                         register_name(p.mXpr_format.rd),
989                         p.mXpr_format.index);
990                 break;
991         case op_pal1b:  /* "hw_ld" */
992         case op_pal1f:  /* "hw_st" */
993                 p.bits = i.bits;
994                 db_printf("\t%s%c%s\t%s,", opcode,
995                         (p.mem_format.qw) ? 'q' : 'l',
996                         hwlds_name[p.mem_format.qualif],
997                         register_name(p.mem_format.rd));
998                 signed_immediate = (long)p.mem_format.displacement;
999                 goto loadstore_address;
1000
1001         case op_pal1e:  /* "hw_rei" */
1002                 db_printf("\t%s", opcode);
1003                 break;
1004
1005         case op_ldf:
1006         case op_ldg:
1007         case op_lds:
1008         case op_ldt:
1009         case op_stf:
1010         case op_stg:
1011         case op_sts:
1012         case op_stt:
1013                 fstore = TRUE;
1014                 /* fall through */
1015         case op_ldl:
1016         case op_ldq:
1017         case op_ldl_l:
1018         case op_ldq_l:
1019         case op_stl:
1020         case op_stq:
1021         case op_stl_c:
1022         case op_stq_c:
1023                 /*
1024                  * Memory operations, including floats
1025                  */
1026 loadstore:
1027                 if (fstore)
1028                     db_printf("%s\tf%d,", opcode, i.mem_format.rd);
1029                 else
1030                     db_printf("%s\t%s,", opcode,
1031                         register_name(i.mem_format.rd));
1032                 signed_immediate = (long)i.mem_format.displacement;
1033 loadstore_address:
1034                 db_printf("%+#lx(%s)", signed_immediate,
1035                         register_name(i.mem_format.rs));
1036                 /*
1037                  * For convenience, do the address computation
1038                  */
1039                 if (showregs) {
1040                         if (i.mem_format.opcode == op_ldah)
1041                                 signed_immediate <<= 16;
1042                         db_printf(" <0x%lx>", signed_immediate +
1043                             db_register_value(DDB_REGS, i.mem_format.rs));
1044                 }
1045                 break;
1046         case op_br:
1047         case op_fbeq:
1048         case op_fblt:
1049         case op_fble:
1050         case op_bsr:
1051         case op_fbne:
1052         case op_fbge:
1053         case op_fbgt:
1054         case op_blbc:
1055         case op_beq:
1056         case op_blt:
1057         case op_ble:
1058         case op_blbs:
1059         case op_bne:
1060         case op_bge:
1061         case op_bgt:
1062                 /*
1063                  * We want to know where we are branching to
1064                  */
1065                 signed_immediate = (long)i.branch_format.displacement;
1066                 db_printf("%s\t%s,", opcode,
1067                           register_name(i.branch_format.rd));
1068 branch_displacement:
1069                 db_printsym(iadr + sizeof(alpha_instruction) +
1070                     (signed_immediate << 2), DB_STGY_PROC);
1071                 break;
1072         default:
1073                 /*
1074                  * Shouldn't happen
1075                  */
1076                 db_printf("? 0x%x ?", i.bits);
1077         }
1078
1079         /*
1080          *      Print out the registers used in this instruction
1081          */
1082         if (showregs && regcount > 0) {
1083                 db_printf("\t<");
1084                 for (ireg = 0; ireg < regcount; ireg++) {
1085                         if (ireg != 0)
1086                                 db_printf(",");
1087                         db_printf("%s=0x%lx",
1088                             name_of_register[regnum[ireg]],
1089                             db_register_value(DDB_REGS, regnum[ireg]));
1090                 }
1091                 db_printf(">");
1092         }
1093         db_printf("\n");
1094         return (sizeof(alpha_instruction));
1095 }