|
|
researchv10 Norman
/*
* disassemble 68020 opcodes
*/
#include "defs.h"
#include "optab.h"
#define SZ_MASK 00300
#define SZ_SHIFT 6 /* bits (7-6) */
static struct opmask {
long mask;
int shift;
} opmask[] = {
0, 0, /* DIG 0 ignore this address */
0x0000003f, 0, /* DEA 1 E.A. to low order 6 bits */
0x00000007, 0, /* DRG 2 register to low order 3 bits */
0x00000e00, 9, /* DRGL 3 register to bits 11-9 */
0x000000ff, 0, /* DBR 4 branch offset (short) */
0x000000ff, 0, /* DMQ 5 move-quick 8-bit value */
0x00000e00, 9, /* DAQ 6 add-quick 3-bit value in 11-9 */
0, 0, /* DIM 7 Immediate value, according to size */
0x00000fc0, 6, /* DEAM 8 E.A. to bits 11-6 as in move */
0, 0, /* DBCC 9 branch address as in "dbcc" */
0x0000000f, 0, /* DTRAP 10 immediate in low 4 bits */
0x00070000, 16, /* D2L 11 register to bits 0-2 of next word */
0x70000000, 16+12, /* D2H 12 register to bits 12-14 of next word */
0x001f0000, 16, /* DBL 13 qty in bits 0-5 of next word */
0x07c00000, 16+6, /* DBH 14 qty in bits 6-11 of next word */
0x0fff0000, 16, /* DCR 15 control reg a bit combination in 0-11 */
};
static int dsp;
extern struct optab optab[];
printins(isp)
int isp;
{
register struct optab *op;
register int i;
register WORD w, w1;
int w1f = 0;
dsp = isp;
w = stow(sget(dot, isp));
chkerr();
for (op = optab; op->opname; op++) {
if ((w & op->mask) != op->opcode)
continue;
if ((op->flags & I2W) == 0)
break; /* 1-word match */
if (w1f == 0) {
w1 = stow(sget(dot+2, isp));
w1f++;
}
if ((w1 & op->mk2) == op->op2)
break; /* 2-word match */
}
if (op->opname == NULL) {
printf("\tnumber\t%R", w);
dotinc = 2;
return;
}
w &= 0xffff;
if ((op->flags & I2W) == 0)
dotinc = 2;
else {
w |= w1 << 16;
dotinc = 4;
}
printf("\t%s", op->opname);
for (i = 0; i < op->nrand; i++) {
if (i == 0)
printf("\t");
else
printf(",");
dorand(w, op->rand[i], op->flags & SZ);
}
}
#define ENSIGN(x) ((WORD)(short)(x))
static
dorand(w, rand, size)
register WORD w;
register short rand;
int size;
{
struct opmask *om;
WORD lval;
register int val;
om = &opmask[rand & DMASK];
if (om->mask)
val = (w & om->mask) >> om->shift;
switch(rand & DMASK) {
case DEA: /* effective address spec */
ea(val >> 3, val & 07, size);
return;
case DRG: /* abs register */
case DRGL:
case D2H:
case D2L:
if (rand & ADEC)
printf("-(%%a%d)", val);
else if (rand & AINC)
printf("(%%a%d)+", val);
else if (rand & AAREG)
printf("%%a%d", val);
else if (rand & ADREG)
printf("%%d%d", val);
else
printf("DRGgok");
return;
case DBR: /* branch displacement */
lval = val;
if (val == 0) {
lval = stow(sget(dot+dotinc, dsp));
if (lval & 0x8000)
lval |= ~0xffff;
dotinc += 2;
}
else if (val == 0xff) {
lval = ltow(lget(dot+dotinc, dsp));
dotinc += 4;
}
else if (val & 0x80)
lval |= ~0xff;
lval += dot + 2;
psymoff(lval, dsp, "");
return;
case DBH: /* 6-bit strange quick */
case DBL: /* other 6-bit strange quick */
if (val & 040) {
printf("%%d%d", val & 07);
return;
}
/* fall through */
case DMQ: /* 8-bit quick */
case DTRAP: /* 4-bit quick */
printf("&");
psymoff((WORD)val, dsp, "");
return;
case DAQ: /* silly 3-bit immediate */
if (val == 0)
val = 8;
printf("&");
psymoff((WORD)val, dsp, "");
return;
case DIM: /* immediate */
if (rand & AONE) {
printf("&1");
return;
}
if (rand & AWORD)
size = W;
switch ((int)size) {
case B:
lval = stow(sget(dot+dotinc, dsp)) & 0377;
if (val & 0200)
val |= ~0377; /* sign extend */
dotinc += 2; /* sic */
break;
case W:
lval = ENSIGN(stow(sget(dot+dotinc, dsp)));
dotinc += 2;
break;
case L:
lval = ltow(lget(dot+dotinc, dsp));
dotinc += 4;
break;
default:
lval = 0;
}
printf("&");
psymoff(lval, dsp, "");
return;
case DEAM: /* assinine backwards ea */
ea(val & 07, val >> 3, size);
return;
case DBCC: /* branch displacement a la dbcc */
lval = stow(sget(dot+dotinc, dsp));
dotinc += 2;
lval += dot + 2;
psymoff(lval, dsp, "");
return;
case DCR:
dcr(val);
return;
case DSREG:
if (rand & C)
printf("%%ccr");
else if (rand & SR)
printf("%%sr");
else if (rand & U)
printf("%%usp");
else
printf("%%GOKdsreg");
return;
}
printf("GOK");
}
static
ea(mode, reg, size)
int mode, reg;
{
WORD disp;
switch((int)mode){
case 0: /* data reg */
printf("%%d%d", reg);
return;
case 1: /* addr reg */
printf("%%a%d", reg);
return;
case 2: /* addr reg indir */
printf("(%%a%d)", reg);
return;
case 3: /* addr reg indir incr */
printf("(%%a%d)+", reg);
return;
case 4: /* addr reg indir decr */
printf("-(%%a%d)", reg);
return;
case 5: /* addr reg indir with displ */
disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
dotinc += 2;
psymoff(disp, dsp, "");
printf("(%%a%d)", reg);
return;
case 6: /* wretched indexing */
doindex(reg); /* ugh */
return;
case 7: /* non-register stuff: */
switch ((int)reg) {
case 0: /* absolute short */
disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
dotinc += 2;
psymoff(disp, dsp, "");
return;
case 1: /* absolute long */
disp = ltow(lget(dot+dotinc, dsp));
dotinc += 4;
psymoff(disp, dsp, "");
return;
case 4: /* immediate */
switch((int)size) {
case B:
disp = ENSIGN(ctow(cget(dot+dotinc, dsp)));
dotinc += 2; /* sic */
printf("&");
psymoff(disp, dsp, "");
return;
case W:
disp = ENSIGN(stow(sget(dot+dotinc, dsp)));
dotinc += 2;
printf("&");
psymoff(disp, dsp, "");
return;
case L:
disp = ltow(lget(dot+dotinc, dsp));
dotinc += 4;
printf("&");
psymoff(disp, dsp, "");
return;
}
}
}
printf("gok%d:%d", mode, reg);
}
static
doindex(reg)
int reg;
{
register WORD w;
register WORD base, outer;
base = outer = 0;
w = stow(sget(dot+dotinc, dsp));
dotinc += 2;
if ((w & 0x80) == 0) { /* brief format */
base = w & 0x7f;
if (base & 0x40)
base |= ~0x7f;
}
else { /* full format */
switch ((int)(w & 0x30)) {
case 0: /* ugh */
case 0x10: /* null displacement */
break;
case 0x20:
base = stow(sget(dot+dotinc, dsp));
outer = stow(sget(dot+dotinc+2, dsp));
dotinc += 4;
break;
case 0x30:
base = ltow(lget(dot+dotinc, dsp));
outer = ltow(lget(dot+dotinc+4, dsp));
dotinc += 8;
break;
}
}
psymoff(base, dsp, "");
printf("(%%a%d,", reg);
printf("%%%c%d.%c", w&0100000 ? 'a' : 'd', (int)(w>>12)&07,
w&04000 ? 'l' : 'w');
printf("*%D)", (WORD)1<<((w>>9)&03));
if (w & 0x80)
psymoff(outer, dsp, "");
}
static
dcr(reg)
int reg;
{
switch (reg) {
case 0x000:
printf("%%sfc");
return;
case 0x001:
printf("%%dfc");
return;
case 0x002:
printf("%%cacr");
return;
case 0x800:
printf("%%usp");
return;
case 0x801:
printf("%%vbr");
return;
case 0x802:
printf("%%caar");
return;
case 0x803:
printf("%%msp");
return;
case 0x804:
printf("%%isp");
return;
default:
printf("%%cr%x", reg);
return;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.