summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-31 05:05:23 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-31 05:05:23 +0000
commit68260964edf75ea99d1255e23659b8756091dbe2 (patch)
treeada7f885a497552b35a26aa7f5efde53a3237eb2
parent93d044bac66e1a946f00b1fd8e58ac67c54e087c (diff)
from ragge;
DDB disassembly is fixed and now works good. Code written and contributed to Ludd by Bertram Barth.
-rw-r--r--sys/arch/vax/vax/db_disasm.c803
-rw-r--r--sys/arch/vax/vax/db_disasm.h361
2 files changed, 849 insertions, 315 deletions
diff --git a/sys/arch/vax/vax/db_disasm.c b/sys/arch/vax/vax/db_disasm.c
index 06728df5f79..429d357aaa3 100644
--- a/sys/arch/vax/vax/db_disasm.c
+++ b/sys/arch/vax/vax/db_disasm.c
@@ -1,8 +1,11 @@
-/* $NetBSD: db_disasm.c,v 1.2 1995/11/30 00:59:34 jtc Exp $ */
+/* $NetBSD: db_disasm.c,v 1.3 1996/01/28 11:31:25 ragge Exp $ */
/*
- * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
*
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -36,345 +39,515 @@
#include <sys/reboot.h>
#include <ddb/db_variables.h>
-
#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include "vax/vax/db_disasm.h"
+#ifdef VMS_MODE
+#define DEFERRED '@'
+#define LITERAL '#'
+#else
+#define DEFERRED '*'
+#define LITERAL '$'
+#endif
+/*
+ * disassembling vax instructions works as follows:
+ *
+ * - get first byte as opcode (check for two-byte opcodes!)
+ * - evaluate (variable length) argument list
+ * - for each argument get type (byte, long, address etc.)
+ * - evaluate addressing mode for this argument
+ * - db_printf the opcode and the (value of the) arguments
+ * - return the start of the next instruction
+ *
+ * - if jump/branch calculate (and display) the target-address
+ */
-struct vax_insn {
- char *insn;
- int nargs;
-} instr[] = {
- "halt", 0,
- "nop", 0,
- "rei", 0,
- "bpt", 0,
- "ret", 0,
- "rsb", 0,
- "ldpctx", 0,
- "svpctx", 0,
- "cvtps", 4,
- "cvtsp", 4,
- "index", 6,
- "crc", 4,
- "prober", 3,
- "probew", 3,
- "insque", 2,
- "remque", 2,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
- "", -1,
+/*
+#define BROKEN_DB_REGS
+*/
+#ifdef BROKEN_DB_REGS
+struct { /* Due to order and contents of db_regs[], we can't */
+ char *name; /* use this array to extract register-names. */
+ void *valuep; /* eg. "psl" vs "pc", "pc" vs "sp" */
+} my_db_regs[16] = {
+ { "r0", NULL },
+ { "r1", NULL },
+ { "r2", NULL },
+ { "r3", NULL },
+ { "r4", NULL },
+ { "r5", NULL },
+ { "r6", NULL },
+ { "r7", NULL },
+ { "r8", NULL },
+ { "r9", NULL },
+ { "r10", NULL },
+ { "r11", NULL },
+ { "ap", NULL }, /* aka "r12" */
+ { "fp", NULL }, /* aka "r13" */
+ { "sp", NULL }, /* aka "r14" */
+ { "pc", NULL }, /* aka "r15" */
};
+#else
+#define my_db_regs db_regs
+#endif
+typedef struct {
+ char dasm[256]; /* disassebled instruction as text */
+ char *curp; /* pointer into result */
+ char *ppc; /* pseudo PC */
+ int opc; /* op-code */
+ char *argp; /* pointer into argument-list */
+ int itype; /* instruction-type, eg. branch, call, unspec */
+ int atype; /* argument-type, eg. byte, long, address */
+ int off; /* offset specified by last argument */
+ int addr; /* address specified by last argument */
+} inst_buffer;
+
+#define ITYPE_INVALID -1
+#define ITYPE_UNSPEC 0
+#define ITYPE_BRANCH 1
+#define ITYPE_CALL 2
+
+int get_byte __P((inst_buffer * ib));
+int get_word __P((inst_buffer * ib));
+int get_long __P((inst_buffer * ib));
+
+int get_opcode __P((inst_buffer * ib));
+int get_operands __P((inst_buffer * ib));
+int get_operand __P((inst_buffer * ib, int size));
+
+void add_char __P((inst_buffer * ib, int c));
+void add_str __P((inst_buffer * ib, char *s));
+void add_int __P((inst_buffer * ib, int i));
+void add_xint __P((inst_buffer * ib, int i));
+void add_sym __P((inst_buffer * ib, int i));
+void add_off __P((inst_buffer * ib, int i));
+
+#define err_print printf
/*
* Disassemble instruction at 'loc'. 'altfmt' specifies an
- * (optional) alternate format. Return address of start of
- * next instruction.
+ * (optional) alternate format (altfmt for vax: don't assume
+ * that each external label is a procedure entry mask).
+ * Return address of start of next instruction.
+ * Since this function is used by 'examine' and by 'step'
+ * "next instruction" does NOT mean the next instruction to
+ * be executed but the 'linear' next instruction.
*/
db_addr_t
db_disasm(loc, altfmt)
- db_addr_t loc;
- boolean_t altfmt;
+ db_addr_t loc;
+ boolean_t altfmt;
{
- char *i_pl;
- int inr, i;
+ db_expr_t diff;
+ db_sym_t sym;
+ char *symname;
- i_pl = (char *)loc;
- inr = *i_pl;
+ inst_buffer ib;
- if (instr[*i_pl].nargs < 0) {
- printf("Ok{nd instruktion: %2x",*i_pl&0xff);
- i_pl++;
- } else {
- printf("\t%s\t",instr[inr].insn);
- i_pl++;
- for (i=0;i<instr[inr].nargs;i++) {
- i_pl = (char *)argprint(i_pl);
- if (i<instr[inr].nargs-1)
- printf(",");
+ bzero(&ib, sizeof(ib));
+ ib.ppc = (void *) loc;
+ ib.curp = ib.dasm;
+
+ if (!altfmt) { /* ignore potential entry masks in altfmt */
+ diff = INT_MAX;
+ symname = NULL;
+ sym = db_search_symbol(loc, DB_STGY_PROC, &diff);
+ db_symbol_values(sym, &symname, 0);
+
+ if (symname && !diff) { /* symbol at loc */
+ db_printf("function \"%s()\", entry-mask 0x%x\n\t\t",
+ symname, (unsigned short) get_word(&ib));
+ ib.ppc += 2;
}
}
+ get_opcode(&ib);
+ get_operands(&ib);
+ db_printf("%s\n", ib.dasm);
+
+ return ((u_int) ib.ppc);
+}
+
+int
+get_opcode(ib)
+ inst_buffer *ib;
+{
+ ib->opc = get_byte(ib);
+ if (ib->opc >> 2 == 0x3F) { /* two byte op-code */
+ ib->opc = ib->opc << 8;
+ ib->opc += get_byte(ib);
+ }
+ switch (ib->opc) {
+ case 0xFA: /* CALLG */
+ case 0xFB: /* CALLS */
+ case 0xFC: /* XFC */
+ ib->itype = ITYPE_CALL;
+ break;
+ case 0x16: /* JSB */
+ case 0x17: /* JMP */
+ ib->itype = ITYPE_BRANCH;
+ break;
+ default:
+ ib->itype = ITYPE_UNSPEC;
+ }
+ if (ib->opc < 0 || ib->opc > 0xFF) {
+ add_str(ib, "invalid or two-byte opcode ");
+ add_xint(ib, ib->opc);
+ ib->itype = ITYPE_INVALID;
+ } else {
+ add_str(ib, vax_inst[ib->opc].mnemonic);
+ add_char(ib, '\t');
+ }
+ return (ib->opc);
+}
+
+int
+get_operands(ib)
+ inst_buffer *ib;
+{
+ int aa = 0; /* absolute address mode ? */
+ int size;
+
+ if (ib->opc < 0 || ib->opc > 0xFF) {
+ /* invalid or two-byte opcode */
+ ib->argp = NULL;
+ return (-1);
+ }
+ ib->argp = vax_inst[ib->opc].argdesc;
+ while (*ib->argp) {
+ switch (*ib->argp) {
+ case 'b': /* branch displacement */
+ switch (*(++ib->argp)) {
+ case 'b':
+ ib->off = (signed char) get_byte(ib);
+ break;
+ case 'w':
+ ib->off = (short) get_word(ib);
+ break;
+ case 'l':
+ ib->off = get_long(ib);
+ break;
+ default:
+ err_print("XXX eror\n");
+ }
+ /* add_int(ib, ib->off); */
+ ib->addr = (u_int) ib->ppc + ib->off;
+ add_off(ib, ib->addr);
+ break;
+
+ case 'a': /* absolute adressing mode */
+ aa = 1; /* do not break here ! */
+
+ default:
+ switch (*(++ib->argp)) {
+ case 'b': /* Byte */
+ size = SIZE_BYTE;
+ break;
+ case 'w': /* Word */
+ size = SIZE_WORD;
+ break;
+ case 'l': /* Long-Word */
+ case 'f': /* F_Floating */
+ size = SIZE_LONG;
+ break;
+ case 'q': /* Quad-Word */
+ case 'd': /* D_Floating */
+ case 'g': /* G_Floating */
+ size = SIZE_QWORD;
+ break;
+ case 'o': /* Octa-Word */
+ case 'h': /* H_Floating */
+ size = SIZE_OWORD;
+ break;
+ default:
+ err_print("invalid op-type %X (%c) found.\n",
+ *ib->argp, *ib->argp);
+ size = 0;
+ }
+ if (aa) {
+ /* get the address */
+ ib->addr = get_operand(ib, size);
+ add_sym(ib, ib->addr);
+ } else {
+ /* get the operand */
+ ib->addr = get_operand(ib, size);
+ add_off(ib, ib->addr);
+ }
+ }
+
+ if (!*ib->argp || !*++ib->argp)
+ break;
+ if (*ib->argp++ == ',') {
+ add_char(ib, ',');
+ add_char(ib, ' ');
+ } else {
+ err_print("XXX error\n");
+ add_char(ib, '\0');
+ return (-1);
+ }
+ }
- return (int)i_pl;
+ add_char(ib, '\0');
+ return (0);
}
-argprint(plats)
- char *plats;
+int
+get_operand(ib, size)
+ inst_buffer *ib;
+ int size;
{
- switch (*plats&0xf0) {
- case 0x00:
- case 0x10:
- case 0x20:
- case 0x30:
- printf("$%x",*plats++);
+ int c = get_byte(ib);
+ int mode = c >> 4;
+ int reg = c & 0x0F;
+ int lit = c & 0x3F;
+ int tmp = 0;
+ char buf[16];
+
+ switch (mode) {
+ case 0: /* literal */
+ case 1: /* literal */
+ case 2: /* literal */
+ case 3: /* literal */
+ add_char(ib, LITERAL);
+ add_int(ib, lit);
+ tmp = lit;
break;
-
- case 0xe0:
- if (*plats++&15 == 15) {
- printf("%8x",*(unsigned *)plats + plats);
- plats += 4;
- } else {
- printf("Oinpl. s{tt.");
+
+ case 4: /* indexed */
+ sprintf(buf, "[%s]", my_db_regs[reg].name);
+ get_operand(ib, 0);
+ add_str(ib, buf);
+ break;
+
+ case 5: /* register */
+ add_str(ib, my_db_regs[reg].name);
+ break;
+
+ case 6: /* register deferred */
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
+ break;
+
+ case 7: /* autodecrement */
+ add_char(ib, '-');
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
+ if (reg == 0x0F) { /* pc is not allowed in this mode */
+ err_print("autodecrement not allowd for PC.\n");
+ }
+ break;
+
+ case 9: /* autoincrement deferred */
+ add_char(ib, DEFERRED);
+ case 8: /* autoincrement */
+ if (reg == 0x0F) { /* pc: immediate ==> special syntax */
+ switch (size) {
+ case SIZE_BYTE:
+ tmp = (signed char) get_byte(ib);
+ break;
+ case SIZE_WORD:
+ tmp = (signed short) get_word(ib);
+ break;
+ case SIZE_LONG:
+ tmp = get_long(ib);
+ break;
+ default:
+ err_print("illegal op-type %d\n", size);
+ tmp = -1;
+ }
+ if (mode == 8)
+ add_char(ib, LITERAL);
+ add_int(ib, tmp);
+ break;
+ }
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
+ add_char(ib, '+');
+ break;
+
+ case 11: /* byte displacement deferred/ relative deferred */
+ add_char(ib, DEFERRED);
+ case 10: /* byte displacement / relative mode */
+ tmp = (signed char) get_byte(ib);
+ if (reg == 0x0F) {
+ add_off(ib, (u_int) ib->ppc + tmp);
+ break;
+ }
+ /* add_str (ib, "b^"); */
+ add_int(ib, tmp);
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
+ break;
+
+ case 13: /* word displacement deferred */
+ add_char(ib, DEFERRED);
+ case 12: /* word displacement */
+ tmp = (signed short) get_word(ib);
+ if (reg == 0x0F) {
+ add_off(ib, (u_int) ib->ppc + tmp);
+ break;
+ }
+ /* add_str (ib, "w^"); */
+ add_int(ib, tmp);
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
+ break;
+
+ case 15: /* long displacement referred */
+ add_char(ib, DEFERRED);
+ case 14: /* long displacement */
+ tmp = get_long(ib);
+ if (reg == 0x0F) {
+ add_off(ib, (u_int) ib->ppc + tmp);
+ break;
}
+ /* add_str (ib, "l^"); */
+ add_int(ib, tmp);
+ add_char(ib, '(');
+ add_str(ib, my_db_regs[reg].name);
+ add_char(ib, ')');
break;
+
default:
- printf("Oinpl. s{tt.");
+ err_print("can\'t evaluate operand (%02X).\n", lit);
+ break;
+ }
+
+ return (0);
+}
+
+int
+get_byte(ib)
+ inst_buffer *ib;
+{
+ return ((unsigned char) *(ib->ppc++));
+}
+
+int
+get_word(ib)
+ inst_buffer *ib;
+{
+ int tmp;
+ char *p = (void *) &tmp;
+ *p++ = get_byte(ib);
+ *p++ = get_byte(ib);
+ return (tmp);
+}
+
+int
+get_long(ib)
+ inst_buffer *ib;
+{
+ int tmp;
+ char *p = (void *) &tmp;
+ *p++ = get_byte(ib);
+ *p++ = get_byte(ib);
+ *p++ = get_byte(ib);
+ *p++ = get_byte(ib);
+ return (tmp);
+}
+
+void
+add_char(ib, c)
+ inst_buffer *ib;
+ int c;
+{
+ *ib->curp++ = c;
+}
+
+void
+add_str(ib, s)
+ inst_buffer *ib;
+ char *s;
+{
+ while (*ib->curp++ = *s++);
+ *--ib->curp = '\0';
+}
+
+void
+add_int(ib, i)
+ inst_buffer *ib;
+ int i;
+{
+ char buf[32];
+ if (i < 100 && i > -100)
+ sprintf(buf, "%d", i);
+ else
+ sprintf(buf, "0x%x", i);
+ add_str(ib, buf);
+}
+
+void
+add_xint(ib, val)
+ inst_buffer *ib;
+ int val;
+{
+ char buf[32];
+ sprintf(buf, "0x%x", val);
+ add_str(ib, buf);
+}
+
+void
+add_sym(ib, loc)
+ inst_buffer *ib;
+ int loc;
+{
+ db_expr_t diff;
+ db_sym_t sym;
+ char *symname;
+
+ if (! loc)
+ return;
+
+ diff = INT_MAX;
+ symname = NULL;
+ sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
+ db_symbol_values(sym, &symname, 0);
+
+ if (symname && !diff) {
+ /* add_char(ib, '<'); */
+ add_str(ib, symname);
+ /* add_char(ib, '>'); */
+ }
+ else
+ add_xint(ib, loc);
+}
+
+void
+add_off(ib, loc)
+ inst_buffer *ib;
+ int loc;
+{
+ db_expr_t diff;
+ db_sym_t sym;
+ char *symname;
+
+ if (!loc)
+ return;
+
+ diff = INT_MAX;
+ symname = NULL;
+ sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
+ db_symbol_values(sym, &symname, 0);
+
+ if (symname) {
+ /* add_char(ib, '<'); */
+ add_str(ib, symname);
+ if (diff) {
+ add_char(ib, '+');
+ add_xint(ib, diff);
+ }
+ /* add_char(ib, '>'); */
}
- return (int)plats;
+ else
+ add_xint(ib, loc);
}
diff --git a/sys/arch/vax/vax/db_disasm.h b/sys/arch/vax/vax/db_disasm.h
new file mode 100644
index 00000000000..99efd972b1c
--- /dev/null
+++ b/sys/arch/vax/vax/db_disasm.h
@@ -0,0 +1,361 @@
+/* $NetBSD: db_disasm.h,v 1.1 1996/01/28 11:31:27 ragge Exp $ */
+/*
+ * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Ludd by
+ * Bertram Barth.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed at Ludd, University of
+ * Lule}, Sweden and its contributors.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#define SIZE_BYTE 1 /* Byte */
+#define SIZE_WORD 2 /* Word */
+#define SIZE_LONG 4 /* Longword */
+#define SIZE_QWORD 8 /* Quadword */
+#define SIZE_OWORD 16 /* Octaword */
+
+/*
+ * The VAX instruction set has a variable length instruction format which
+ * may be as short as one byte and as long as needed depending on the type
+ * of instruction. [...] Each instruction consists of an opcode followed
+ * by zero to six operand specifiers whose number and type depend on the
+ * opcode. All operand specidiers are, themselves, of the same format --
+ * i.e. an address mode plus additional information.
+ *
+ * [VAX Architecture Handbook, p.52: Instruction Format]
+ */
+
+struct {
+ char *mnemonic;
+ char *argdesc;
+} vax_inst[256] = {
+
+/*
+ * argdesc describes each arguments by two characters denoting
+ * the access-type and the data-type.
+ *
+ * Arguments (Access-Types):
+ * r: operand is read only
+ * w: operand is written only
+ * m: operand is modified (both R and W)
+ * b: no operand reference. Branch displacement is specified.
+ * a: calculate the adress of the specified operand
+ * v: if not "Rn", same as a. If "RN," R[n+1]R[n]
+ * Arguments (Data-Types):
+ * b: Byte
+ * w: Word
+ * l: Longword
+ * q: Quadword
+ * o: Octaword
+ * d: D_floating
+ * f: F_floating
+ * g: G_floating
+ * h: H_floating
+ * r: Register
+ * x: first data type specified by instruction
+ * y: second data type spcified by instructin
+ * -: no-args
+ * ?: unknown (variable?)
+ */
+
+/* 0x00 */ { "halt", "" },
+/* 0x01 */ { "nop", "" },
+/* 0x02 */ { "rei", "" },
+/* 0x03 */ { "bpt", "" },
+/* 0x04 */ { "ret", "" },
+/* 0x05 */ { "rsb", "" },
+/* 0x06 */ { "ldpctx", "" },
+/* 0x07 */ { "svpctx", "" },
+/* 0x08 */ { "cvtps", "rw,ab,rw,ab" },
+/* 0x09 */ { "cvtsp", "rw,ab,rw,ab" },
+/* 0x0a */ { "index", "rl,rl,rl,rl,rl,wl" },
+/* 0x0b */ { "crc", "ab,rl,rw,ab" },
+/* 0x0c */ { "prober", "rb,rw,ab" },
+/* 0x0d */ { "probew", "rb,rw,ab" },
+/* 0x0e */ { "insque", "ab,wl" },
+/* 0x0f */ { "remque", "ab,wl" },
+
+/* 0x10 */ { "bsbb", "bb" },
+/* 0x11 */ { "brb", "bb" },
+/* 0x12 */ { "*bneq", "bb" },
+/* 0x13 */ { "*beql", "bb" },
+/* 0x14 */ { "bgtr", "bb" },
+/* 0x15 */ { "bleq", "bb" },
+/* 0x16 */ { "jsb", "ab" },
+/* 0x17 */ { "jmp", "ab" },
+/* 0x18 */ { "bgeq", "bb" },
+/* 0x19 */ { "blss", "bb" },
+/* 0x1a */ { "bgtru", "bb" },
+/* 0x1b */ { "blequ", "bb" },
+/* 0x1c */ { "bvc", "bb" },
+/* 0x1d */ { "bvs", "bb" },
+/* 0x1e */ { "*bcc", "bb" },
+/* 0x1f */ { "*bcs", "bb" },
+
+/* 0x20 */ { "addp4", "rw,ab,rw,ab" },
+/* 0x21 */ { "addp6", "rw,ab,rw,ab,rw,ab" },
+/* 0x22 */ { "subp4", "rw,ab,rw,ab" },
+/* 0x23 */ { "subp6", "rw,ab,rw,ab,rw,ab" },
+/* 0x24 */ { "cvtpt", "rw,ab,ab,rw,ab" },
+/* 0x25 */ { "mulp", "rw,ab,rw,ab,rw,ab" },
+/* 0x26 */ { "cvttp", "rw,ab,ab,rw,ab" },
+/* 0x27 */ { "divp", "rw,ab,rw,ab,rw,ab" },
+/* 0x28 */ { "movc3", "rw,ab,ab" },
+/* 0x29 */ { "cmpc3", "rw,ab,ab" },
+/* 0x2a */ { "scanc", "rw,ab,ab,rb" },
+/* 0x2b */ { "spanc", "rw,ab,ab,rb" },
+/* 0x2c */ { "movc5", "rw,ab,rb,rw,ab" },
+/* 0x2d */ { "cmpc5", "rw,ab,rb,rw,ab" },
+/* 0x2e */ { "movtc", "rw,ab,rb,ab,rw,ab" },
+/* 0x2f */ { "movtuc", "rw,ab,rb,ab,rw,ab" },
+
+/* 0x30 */ { "bsbw", "bw" },
+/* 0x31 */ { "brw", "bw" },
+/* 0x32 */ { "cvtwl", "rw,wl" },
+/* 0x33 */ { "cvtwb", "rw,wb" },
+/* 0x34 */ { "movp", "rw,ab,ab" },
+/* 0x35 */ { "cmpp3", "rw,ab,ab" },
+/* 0x36 */ { "cvtpl", "rw,ab,wl" },
+/* 0x37 */ { "cmpp4", "rw,ab,rw,ab" },
+/* 0x38 */ { "editpc", "rw,ab,ab,ab" },
+/* 0x39 */ { "matchc", "rw,ab,rw,ab" },
+/* 0x3a */ { "locc", "rb,rw,ab" },
+/* 0x3b */ { "skpc", "rb,rw,ab" },
+/* 0x3c */ { "movzwl", "rw,wl" },
+/* 0x3d */ { "acbw", "rw,rw,mw,bw" },
+/* 0x3e */ { "movaw", "aw,wl" },
+/* 0x3f */ { "pushaw", "aw" },
+
+/* 0x40 */ { "addf2", "rf,mf" },
+/* 0x41 */ { "addf3", "rf,rf,wf" },
+/* 0x42 */ { "subf2", "rf,mf" },
+/* 0x43 */ { "subf3", "rf,rf,wf" },
+/* 0x44 */ { "mulf2", "rf,mf" },
+/* 0x45 */ { "mulf3", "rf,rf,wf" },
+/* 0x46 */ { "divf2", "rf,mf" },
+/* 0x47 */ { "divf3", "rf,rf,wf" },
+/* 0x48 */ { "cvtfb", "rf,wb" },
+/* 0x49 */ { "cvtfw", "rf,ww" },
+/* 0x4a */ { "cvtfl", "rf,wl" },
+/* 0x4b */ { "cvtrfl", "rf,wl" },
+/* 0x4c */ { "cvtbf", "rb,wf" },
+/* 0x4d */ { "cvtwf", "rw,wf" },
+/* 0x4e */ { "cvtlf", "rl,wf" },
+/* 0x4f */ { "acbf", "rf,rf,rf,bw" },
+
+/* 0x50 */ { "movf", "rf,wf" },
+/* 0x51 */ { "cmpf", "rf,rf" },
+/* 0x52 */ { "mnegf", "rf,wf" },
+/* 0x53 */ { "tstf", "rf" },
+/* 0x54 */ { "emodf", "rf,rb,rf,wl,wf" },
+/* 0x55 */ { "polyf", "rf,rw,ab" },
+/* 0x56 */ { "cvtfd", "rf,wd" },
+/* 0x57 */ { "-reserved-", "" },
+/* 0x58 */ { "adawi", "rw,mw" },
+/* 0x59 */ { "-reserved-", "" },
+/* 0x5a */ { "-reserved-", "" },
+/* 0x5b */ { "-reserved-", "" },
+/* 0x5c */ { "insqhi", "ab,aq" },
+/* 0x5d */ { "insqti", "ab,aq" },
+/* 0x5e */ { "remqhi", "aq,wl" },
+/* 0x5f */ { "remqti", "aq,wl" },
+
+/* 0x60 */ { "addd2", "rd,md" },
+/* 0x61 */ { "addd3", "rd,rd,wd" },
+/* 0x62 */ { "subd2", "rd,md" },
+/* 0x63 */ { "subd3", "rd,rd,wd" },
+/* 0x64 */ { "muld2", "rd,md" },
+/* 0x65 */ { "muld3", "rd,rd,wd" },
+/* 0x66 */ { "divd2", "rd,md" },
+/* 0x67 */ { "divd3", "rd,rd,wd" },
+/* 0x68 */ { "cvtdb", "rd,wb" },
+/* 0x69 */ { "cvtdw", "rd,ww" },
+/* 0x6a */ { "cvtdl", "rd,wl" },
+/* 0x6b */ { "cvtrdl", "rd,wl" },
+/* 0x6c */ { "cvtbd", "rb,wd" },
+/* 0x6d */ { "cvtwd", "rw,wd" },
+/* 0x6e */ { "cvtld", "rl,wd" },
+/* 0x6f */ { "acbd", "rd,rd,md,bw" },
+
+/* 0x70 */ { "movd", "rd,wd" },
+/* 0x71 */ { "cmpd", "rd,rd" },
+/* 0x72 */ { "mnegd", "rd,wd" },
+/* 0x73 */ { "tstd", "rd" },
+/* 0x74 */ { "emodd", "rd,rb,rd,wl,wd" },
+/* 0x75 */ { "polyd", "rd,rw,ab" },
+/* 0x76 */ { "cvtdf", "rd,wf" },
+/* 0x77 */ { "-reserved-", "" },
+/* 0x78 */ { "ashl", "rb,rl,wl" },
+/* 0x79 */ { "ashq", "rb,rq,wq" },
+/* 0x7a */ { "emul", "rl,rl,rl,wq" },
+/* 0x7b */ { "ediv", "rl,rq,wl,wl" },
+/* 0x7c */ { "*clrq", "wq" },
+/* 0x7d */ { "movq", "rq,wq" },
+/* 0x7e */ { "*movaq", "aq,wl" },
+/* 0x7f */ { "*pushaq", "aq" },
+
+/* 0x80 */ { "addb2", "rb,mb" },
+/* 0x81 */ { "addb3", "rb,rb,wb" },
+/* 0x82 */ { "subb2", "rb,mb" },
+/* 0x83 */ { "subb3", "rb,rb,wb" },
+/* 0x84 */ { "mulb2", "rb,mb" },
+/* 0x85 */ { "mulb3", "rb,rb,wb" },
+/* 0x86 */ { "divb2", "rb,mb" },
+/* 0x87 */ { "divb3", "rb,rb,wb" },
+/* 0x88 */ { "bisb2", "rb,mb" },
+/* 0x89 */ { "bisb3", "rb,rb,wb" },
+/* 0x8a */ { "bicb2", "rb,mb" },
+/* 0x8b */ { "bicb3", "rb,rb,wb" },
+/* 0x8c */ { "xorb2", "rb,mb" },
+/* 0x8d */ { "xorb3", "rb,rb,wb" },
+/* 0x8e */ { "mnegb", "rb,wb" },
+/* 0x8f */ { "caseb", "rb,rb,rb,bw-list" },
+
+/* 0x90 */ { "movb", "rb,wb" },
+/* 0x91 */ { "cmpb", "rb,rb" },
+/* 0x92 */ { "mcomb", "rb,wb" },
+/* 0x93 */ { "bitb", "rb,rb" },
+/* 0x94 */ { "clrb", "wb" },
+/* 0x95 */ { "tstb", "rb" },
+/* 0x96 */ { "incb", "mb" },
+/* 0x97 */ { "decb", "mb" },
+/* 0x98 */ { "cvtbl", "rb,wl" },
+/* 0x99 */ { "cvtbw", "rb,ww" },
+/* 0x9a */ { "movzbl", "rb,wl" },
+/* 0x9b */ { "movzbw", "wb,ww" },
+/* 0x9c */ { "rotl", "rb,rl,wl" },
+/* 0x9d */ { "acbb", "rb,rb,mb,bw" },
+/* 0x9e */ { "movab", "ab,wl" },
+/* 0x9f */ { "pushab", "ab" },
+
+/* 0xa0 */ { "addw2", "rw,mw" },
+/* 0xa1 */ { "addw3", "rw,rw,ww" },
+/* 0xa2 */ { "subw2", "rw,mw" },
+/* 0xa3 */ { "subw3", "rw,rw,ww" },
+/* 0xa4 */ { "mulw2", "rw,mw" },
+/* 0xa5 */ { "mulw3", "rw,rw,ww" },
+/* 0xa6 */ { "divw2", "rw,mw" },
+/* 0xa7 */ { "divw3", "rw,rw,ww" },
+/* 0xa8 */ { "bisw2", "rw,mw" },
+/* 0xa9 */ { "bisw3", "rw,rw,ww" },
+/* 0xaa */ { "bicw2", "rw,mw" },
+/* 0xab */ { "bicw3", "rw,rw,ww" },
+/* 0xac */ { "xorw2", "rw,mw" },
+/* 0xad */ { "xorw3", "rw,rw,ww" },
+/* 0xae */ { "mnegw", "rw,ww" },
+/* 0xaf */ { "casew", "rw,rw,rw,bw-list" },
+
+/* 0xb0 */ { "movw", "rw,ww" },
+/* 0xb1 */ { "cmpw", "rw,rw" },
+/* 0xb2 */ { "mcomw", "rw,ww" },
+/* 0xb3 */ { "bitw", "rw,rw" },
+/* 0xb4 */ { "clrw", "mw" },
+/* 0xb5 */ { "tstw", "rw" },
+/* 0xb6 */ { "incw", "mw" },
+/* 0xb7 */ { "decw", "mw" },
+/* 0xb8 */ { "bispsw", "rw" },
+/* 0xb9 */ { "bicpsw", "rw" },
+/* 0xba */ { "popr", "rw" },
+/* 0xbb */ { "pushr", "rw" },
+/* 0xbc */ { "chmk", "rw" },
+/* 0xbd */ { "chme", "rw" },
+/* 0xbe */ { "chms", "rw" },
+/* 0xbf */ { "chmu", "rw" },
+
+/* 0xc0 */ { "addl2", "rl,ml" },
+/* 0xc1 */ { "addl3", "rl,rl,wl" },
+/* 0xc2 */ { "subl2", "rl,ml" },
+/* 0xc3 */ { "subl3", "rl,rl,wl" },
+/* 0xc4 */ { "mull2", "rl,ml" },
+/* 0xc5 */ { "mull3", "rl,rl,wl" },
+/* 0xc6 */ { "divl2", "rl,ml" },
+/* 0xc7 */ { "divl3", "rl,rl,wl" },
+/* 0xc8 */ { "bisl2", "rl,ml" },
+/* 0xc9 */ { "bisl3", "rl,rl,wl" },
+/* 0xca */ { "bicl2", "rl,ml" },
+/* 0xcb */ { "bicl3", "rl,rl,wl" },
+/* 0xcc */ { "xorl2", "rl,ml" },
+/* 0xcd */ { "xorl3", "rl,rl,wl" },
+/* 0xce */ { "mnegl", "rl,wl" },
+/* 0xcf */ { "casel", "rl,rl,rl,bw-list" },
+
+/* 0xd0 */ { "movl", "rl,wl" },
+/* 0xd1 */ { "cmpl", "rl,rl" },
+/* 0xd2 */ { "mcoml", "rl,wl" },
+/* 0xd3 */ { "bitl", "rl,rl" },
+/* 0xd4 */ { "*clrl", "wl" },
+/* 0xd5 */ { "tstl", "rl" },
+/* 0xd6 */ { "incl", "ml" },
+/* 0xd7 */ { "decl", "ml" },
+/* 0xd8 */ { "adwc", "rl,ml" },
+/* 0xd9 */ { "sbwc", "rl,ml" },
+/* 0xda */ { "mtpr", "rl,rl" },
+/* 0xdb */ { "mfpr", "rl,wl" },
+/* 0xdc */ { "movpsl", "wl" },
+/* 0xdd */ { "pushl", "rl" },
+/* 0xde */ { "*moval", "al,wl" },
+/* 0xdf */ { "*pushal", "al" },
+
+/* 0xe0 */ { "bbs", "rl,vb,bb" },
+/* 0xe1 */ { "bbc", "rl,vb,bb" },
+/* 0xe2 */ { "bbss", "rl,vb,bb" },
+/* 0xe3 */ { "bbcs", "rl,vb,bb" },
+/* 0xe4 */ { "bbsc", "rl,vb,bb" },
+/* 0xe5 */ { "bbcc", "rl,vb,bb" },
+/* 0xe6 */ { "bbssi", "rl,vb,bb" },
+/* 0xe7 */ { "bbcci", "rl,vb,bb" },
+/* 0xe8 */ { "blbs", "rl,bb" },
+/* 0xe9 */ { "blbc", "rl,bb" },
+/* 0xea */ { "ffs", "rl,rb,vb" },
+/* 0xeb */ { "ffc", "rl,rb,vb" },
+/* 0xec */ { "cmpv", "rl,rb,vb,rl" },
+/* 0xed */ { "cmpzv", "rl,rb,vb,rl" },
+/* 0xee */ { "extv", "rl,rb,vb,wl" },
+/* 0xef */ { "extzv", "rl,rb,vb,wl" },
+
+/* 0xf0 */ { "insv", "rl,rl,rb,vb" },
+/* 0xf1 */ { "acbl", "rl,rl,ml,bw" },
+/* 0xf2 */ { "aoblss", "rl,ml,bb" },
+/* 0xf3 */ { "aobleq", "rl,ml,bb" },
+/* 0xf4 */ { "sobgeq", "ml,bb" },
+/* 0xf5 */ { "sobgtr", "ml,bb" },
+/* 0xf6 */ { "cvtlb", "rl,wb" },
+/* 0xf7 */ { "cvtlw", "rl,ww" },
+/* 0xf8 */ { "ashp", "rb,rw,ab,rb,rw,ab" },
+/* 0xf9 */ { "cvtlp", "rl,rw,ab" },
+/* 0xfa */ { "callg", "ab,ab" },
+/* 0xfb */ { "calls", "rl,ab" },
+/* 0xfc */ { "xfc", "?" },
+/* 0xfd */ { "-reserved-", "" },
+/* 0xfe */ { "-reserved-", "" },
+/* 0xff */ { "-reserved-", "" },
+
+};
+