mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-02-03 15:23:35 +00:00
441 lines
10 KiB
C
441 lines
10 KiB
C
/* This code borrowed from 2.11BSD adb */
|
|
|
|
#include "aout.h"
|
|
|
|
extern void add_symbol(int addr, int type, int size);
|
|
extern struct symbol *get_isym(int addr);
|
|
extern struct symbol *get_dsym(int addr);
|
|
|
|
extern u_int8_t *ispace, *dspace; /* Instruction and Data spaces */
|
|
extern struct syscallinfo *systab;
|
|
extern int numsyscalls;
|
|
|
|
int doprint = 0; /* Only print out if 1 */
|
|
int itype; /* Global equal to p->itype */
|
|
|
|
#define NSP 0
|
|
#define ISYM 2
|
|
#define DSYM 7
|
|
|
|
/* instruction printing */
|
|
|
|
#define DOUBLE 0
|
|
#define DOUBLW 1
|
|
#define SINGLE 2
|
|
#define SINGLW 3
|
|
#define REVERS 4
|
|
#define BRANCH 5
|
|
#define NOADDR 6
|
|
#define DFAULT 7
|
|
#define TRAP 8
|
|
#define SYS 9
|
|
#define SOB 10
|
|
#define JMP 11
|
|
#define JSR 12
|
|
|
|
struct optab {
|
|
int mask;
|
|
int val;
|
|
int itype;
|
|
char *iname;
|
|
} optab[] = {
|
|
{ 0107777, 0010000, DOUBLE, "mov" },
|
|
{ 0107777, 0020000, DOUBLE, "cmp" },
|
|
{ 0107777, 0030000, DOUBLE, "bit" },
|
|
{ 0107777, 0040000, DOUBLE, "bic" },
|
|
{ 0107777, 0050000, DOUBLE, "bis" },
|
|
{ 0007777, 0060000, DOUBLW, "add" },
|
|
{ 0007777, 0160000, DOUBLW, "sub" },
|
|
{ 0100077, 0005000, SINGLE, "clr" },
|
|
{ 0100077, 0005100, SINGLE, "com" },
|
|
{ 0100077, 0005200, SINGLE, "inc" },
|
|
{ 0100077, 0005300, SINGLE, "dec" },
|
|
{ 0100077, 0005400, SINGLE, "neg" },
|
|
{ 0100077, 0005500, SINGLE, "adc" },
|
|
{ 0100077, 0005600, SINGLE, "sbc" },
|
|
{ 0100077, 0005700, SINGLE, "tst" },
|
|
{ 0100077, 0006000, SINGLE, "ror" },
|
|
{ 0100077, 0006100, SINGLE, "rol" },
|
|
{ 0100077, 0006200, SINGLE, "asr" },
|
|
{ 0100077, 0006300, SINGLE, "asl" },
|
|
{ 0000077, 0000100, JMP, "jmp" },
|
|
{ 0000077, 0000300, SINGLE, "swab" },
|
|
{ 0000077, 0170100, SINGLW, "ldfps" },
|
|
{ 0000077, 0170200, SINGLW, "stfps" },
|
|
{ 0000077, 0170300, SINGLW, "stst" },
|
|
{ 0000077, 0170400, SINGLW, "clrf" },
|
|
{ 0000077, 0170500, SINGLW, "tstf" },
|
|
{ 0000077, 0170600, SINGLW, "absf" },
|
|
{ 0000077, 0170700, SINGLW, "negf" },
|
|
{ 0000077, 0006700, SINGLW, "sxt" },
|
|
{ 0000077, 0006600, SINGLW, "mtpi" },
|
|
{ 0000077, 0106600, SINGLW, "mtpd" },
|
|
{ 0000077, 0006500, SINGLW, "mfpi" },
|
|
{ 0000077, 0106500, SINGLW, "mfpd" },
|
|
{ 0000077, 0106700, SINGLW, "mfps" },
|
|
{ 0000077, 0106400, SINGLW, "mtps" },
|
|
{ 0000777, 0070000, REVERS, "mul" },
|
|
{ 0000777, 0071000, REVERS, "div" },
|
|
{ 0000777, 0072000, REVERS, "ash" },
|
|
{ 0000777, 0073000, REVERS, "ashc" },
|
|
{ 0377, 0000400, BRANCH, "br" },
|
|
{ 0377, 0001000, BRANCH, "bne" },
|
|
{ 0377, 0001400, BRANCH, "beq" },
|
|
{ 0377, 0002000, BRANCH, "bge" },
|
|
{ 0377, 0002400, BRANCH, "blt" },
|
|
{ 0377, 0003000, BRANCH, "bgt" },
|
|
{ 0377, 0003400, BRANCH, "ble" },
|
|
{ 0377, 0100000, BRANCH, "bpl" },
|
|
{ 0377, 0100400, BRANCH, "bmi" },
|
|
{ 0377, 0101000, BRANCH, "bhi" },
|
|
{ 0377, 0101400, BRANCH, "blos" },
|
|
{ 0377, 0102000, BRANCH, "bvc" },
|
|
{ 0377, 0102400, BRANCH, "bvs" },
|
|
{ 0377, 0103000, BRANCH, "bcc" },
|
|
{ 0377, 0103400, BRANCH, "bcs" },
|
|
{ 0000000, 0000000, NOADDR, "halt" },
|
|
{ 0000000, 0000001, NOADDR, "wait" },
|
|
{ 0000000, 0000002, NOADDR, "rti" },
|
|
{ 0000000, 0000003, NOADDR, "bpt" },
|
|
{ 0000000, 0000004, NOADDR, "iot" },
|
|
{ 0000000, 0000005, NOADDR, "reset" },
|
|
{ 0000000, 0000006, NOADDR, "rtt" },
|
|
{ 0377, 0171000, REVERS, "mulf" },
|
|
{ 0377, 0171400, REVERS, "modf" },
|
|
{ 0377, 0172000, REVERS, "addf" },
|
|
{ 0377, 0172400, REVERS, "movf" },
|
|
{ 0377, 0173000, REVERS, "subf" },
|
|
{ 0377, 0173400, REVERS, "cmpf" },
|
|
{ 0377, 0174000, DOUBLW, "movf" },
|
|
{ 0377, 0174400, REVERS, "divf" },
|
|
{ 0377, 0175000, DOUBLW, "movei" },
|
|
{ 0377, 0175400, DOUBLW, "movfi" },
|
|
{ 0377, 0176000, DOUBLW, "movfo" },
|
|
{ 0377, 0176400, REVERS, "movie" },
|
|
{ 0377, 0177000, REVERS, "movif" },
|
|
{ 0377, 0177400, REVERS, "movof" },
|
|
{ 0000000, 0170000, NOADDR, "cfcc" },
|
|
{ 0000000, 0170001, NOADDR, "setf" },
|
|
{ 0000000, 0170002, NOADDR, "seti" },
|
|
{ 0000000, 0170011, NOADDR, "setd" },
|
|
{ 0000000, 0170012, NOADDR, "setl" },
|
|
{ 0000000, 0000007, NOADDR, "mfpt" },
|
|
{ 0000077, 0007000, JMP, "csm" },
|
|
{ 0000077, 0007300, SINGLW, "wrtlck" },
|
|
{ 0000077, 0007200, SINGLW, "tstset" },
|
|
{ 0000777, 0004000, JSR, "jsr" },
|
|
{ 0000777, 0074000, DOUBLE, "xor" },
|
|
{ 0000007, 0000200, SINGLE, "rts" },
|
|
{ 0000017, 0000240, DFAULT, "cflg" },
|
|
{ 0000017, 0000260, DFAULT, "sflg" },
|
|
{ 0377, 0104000, TRAP, "emt" },
|
|
{ 0377, 0104400, SYS, "sys" },
|
|
{ 0000077, 0006400, TRAP, "mark" },
|
|
{ 0000777, 0077000, SOB, "sob" },
|
|
{ 0000007, 0000230, DFAULT, "spl" },
|
|
{ 0177777, 0000000, DFAULT, "<illegal op>" }
|
|
};
|
|
|
|
|
|
/* Heuristically determine what follows after a jsr r5,xxx.
|
|
* Create a symbol for it, including the estimated size.
|
|
* Return the length of the data in bytes.
|
|
*/
|
|
int guess_jsr_r5(int addr)
|
|
{
|
|
int a,len;
|
|
int istext=1;
|
|
|
|
/* Try an ASCII string first. Give up if we find a
|
|
* non-printable and non-NUL character.
|
|
*/
|
|
for (a=addr,len=0;; a++,len++) {
|
|
/* Found end of string which isn't zero length, stop now */
|
|
if (len && (ispace[a]=='\0')) {
|
|
len++; break;
|
|
}
|
|
|
|
/* If char is not ASCII and not tab/newline, it's not a string */
|
|
if (!isprint(ispace[a]) && (ispace[a] != '\t') && (ispace[a] != '\n')) {
|
|
istext=0; break;
|
|
}
|
|
}
|
|
|
|
/* If not a string, guess a single word as argument */
|
|
if (!istext) {
|
|
add_symbol(addr, SYM_JSRDATA, 2);
|
|
return(2);
|
|
} else {
|
|
add_symbol(addr, SYM_JSRTEXT, len);
|
|
return(len);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Print out an operand. Return any increment to skip to reach the next
|
|
* instruction.
|
|
*/
|
|
int paddr(char *str, int addr, int a, int lastr)
|
|
{
|
|
char *regname[] = {"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc"};
|
|
u_int16_t var;
|
|
int r;
|
|
char *rptr;
|
|
|
|
r = a & 07;
|
|
a &= 070;
|
|
|
|
if (doprint)
|
|
printf(str);
|
|
if (r == 7 && a & 020) {
|
|
int jsrr5_skip=0; /* Amount to skip on a jsr r5,xxx */
|
|
if (a & 010) {
|
|
if (doprint)
|
|
putchar('*');
|
|
}
|
|
if (a & 040) {
|
|
|
|
var = (addr + 4) + ispace[addr + 2] + (ispace[addr + 3] << 8);
|
|
if (doprint) {
|
|
/* See if there is a label for that */
|
|
struct symbol *s;
|
|
if (itype==JSR) s= get_isym(var);
|
|
else s= get_dsym(var);
|
|
if (s == NULL)
|
|
printf("0%o", var);
|
|
else
|
|
printf("%s", s->name);
|
|
|
|
/* We've hit a jsr r5,... */
|
|
if ((itype==JSR) && (lastr==5)) {
|
|
s= get_isym(addr+4);
|
|
if (s==NULL) {
|
|
printf("Weird, no SYM_JSR\n");
|
|
} else {
|
|
jsrr5_skip= s->size;
|
|
if (s->type==SYM_JSRTEXT) {
|
|
char *str= (char *)&ispace[addr+4];
|
|
printf("; <%s>; .even", str);
|
|
} else {
|
|
u_int16_t var2= ispace[addr + 4] + (ispace[addr + 5] << 8);
|
|
printf("; 0%o", var2);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* Register a function if this is a JSR, else data */
|
|
if (itype==JSR) {
|
|
add_symbol(var, SYM_FUNCTION, 0);
|
|
if (lastr==5) {
|
|
jsrr5_skip= guess_jsr_r5(addr+4);
|
|
}
|
|
}
|
|
else add_symbol(var, SYM_DATA, 0);
|
|
}
|
|
} else {
|
|
var = ispace[addr + 2] + (ispace[addr + 3] << 8);
|
|
if (doprint)
|
|
printf("$0%o", var);
|
|
}
|
|
return (2+jsrr5_skip);
|
|
}
|
|
|
|
rptr = regname[r];
|
|
switch (a) {
|
|
/* r */
|
|
case 000:
|
|
if (doprint)
|
|
printf(rptr);
|
|
return (0);
|
|
|
|
/* (r) */
|
|
case 010:
|
|
if (doprint)
|
|
printf("(%s)", rptr);
|
|
return (0);
|
|
|
|
/* *(r)+ */
|
|
case 030:
|
|
if (doprint)
|
|
putchar('*');
|
|
|
|
/* (r)+ */
|
|
case 020:
|
|
if (doprint)
|
|
printf("(%s)+", rptr);
|
|
return (0);
|
|
|
|
/* *-(r) */
|
|
case 050:
|
|
if (doprint)
|
|
putchar('*');
|
|
|
|
/* -(r) */
|
|
case 040:
|
|
if (doprint)
|
|
printf("-(%s)", rptr);
|
|
return (0);
|
|
|
|
/* *x(r) */
|
|
case 070:
|
|
if (doprint)
|
|
putchar('*');
|
|
|
|
/* x(r) */
|
|
case 060:
|
|
var = ispace[addr + 2] + (ispace[addr + 3] << 8);
|
|
if (doprint)
|
|
printf("0%o(%s)", var, rptr);
|
|
return (2);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Deal with double operands. Return any increment to skip to reach the next
|
|
* instruction.
|
|
*/
|
|
int doubl(int addr, int a, int b)
|
|
{
|
|
int i = 0;
|
|
int r= a & 07; /* Get the register from the 1st operand */
|
|
i += paddr(" ", addr, a, 0);
|
|
i += paddr(",", addr + i, b, r);
|
|
return (i);
|
|
}
|
|
|
|
void branch(char *str, int addr, int ins)
|
|
{
|
|
if (doprint) printf(str);
|
|
if (ins & 0200) {
|
|
ins |= 0177400;
|
|
}
|
|
|
|
/* Determine the branch address */
|
|
ins = (addr + (ins << 1) + 2) & 0177777;
|
|
|
|
if (!doprint) {
|
|
add_symbol(ins, SYM_BRANCH, 0); /* Add a branch symbol for it */
|
|
return;
|
|
}
|
|
|
|
/* Printing it, see if there is a label for that */
|
|
struct symbol *s = get_isym(ins);
|
|
if (s == NULL) {
|
|
printf("0%o", ins);
|
|
return;
|
|
}
|
|
|
|
/* Yes there is, print it out */
|
|
printf("%s", s->name);
|
|
if (s->type == SYM_BRANCH) {
|
|
if (ins > addr) printf("f");
|
|
else printf("b");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Given an address, disassemble and print out the instruction at that
|
|
* address. Return any increment to skip to reach the next instruction.
|
|
*/
|
|
int printins(int addr)
|
|
{
|
|
unsigned int type;
|
|
int byte;
|
|
int incr = 2;
|
|
int syscall;
|
|
struct optab *p;
|
|
struct symbol *s;
|
|
|
|
/* Print out any instruction symbol */
|
|
if (doprint) {
|
|
s = get_isym(addr);
|
|
if (s)
|
|
printf("%s:\n", s->name);
|
|
}
|
|
/* Get the instruction from the ispace array */
|
|
int ins = ispace[addr] + (ispace[addr + 1] << 8);
|
|
|
|
type = DSYM;
|
|
for (p = optab;; p++) {
|
|
if ((ins & ~p->mask) == p->val) {
|
|
break;
|
|
}
|
|
}
|
|
if (doprint)
|
|
printf("\t%s", p->iname);
|
|
byte = ins & 0100000;
|
|
ins &= p->mask;
|
|
|
|
itype= p->itype;
|
|
switch (p->itype) {
|
|
|
|
case JMP:
|
|
type = ISYM;
|
|
|
|
case SINGLE:
|
|
if (byte) {
|
|
if (doprint)
|
|
putchar('b');
|
|
}
|
|
case SINGLW:
|
|
incr += paddr(" ", addr, ins, 0);
|
|
break;
|
|
|
|
case REVERS:
|
|
incr += doubl(addr, ins & 077, (ins >> 6) & 07);
|
|
break;
|
|
|
|
case JSR:
|
|
type = ISYM;
|
|
|
|
case DOUBLE:
|
|
if (byte) {
|
|
if (doprint)
|
|
putchar('b');
|
|
}
|
|
case DOUBLW:
|
|
incr += doubl(addr, ins >> 6, ins);
|
|
|
|
case NOADDR:
|
|
break;
|
|
|
|
case SOB:
|
|
incr += paddr(" ", addr, (ins >> 6) & 07, 0);
|
|
branch(",", addr, -(ins & 077));
|
|
break;
|
|
|
|
case BRANCH:
|
|
branch(" ", addr, ins);
|
|
break;
|
|
|
|
case SYS:
|
|
if (ins < numsyscalls && systab[ins].name) {
|
|
if (doprint)
|
|
printf(" %s", systab[ins].name);
|
|
/* Print any argument words following the syscall */
|
|
int n;
|
|
for (n = 1; n <= systab[ins].numwords; n++) {
|
|
int b = 2 * n;
|
|
syscall = ispace[addr + b] + (ispace[addr + b + 1] << 8);
|
|
if (doprint)
|
|
printf("; 0%o", syscall);
|
|
}
|
|
/* Skip some number of words following the syscall */
|
|
incr += 2 * systab[ins].numwords;
|
|
} else if (doprint)
|
|
printf(" %d", ins);
|
|
break;
|
|
|
|
case TRAP:
|
|
case DFAULT:
|
|
default:
|
|
if (doprint)
|
|
printf(" 0%o", ins);
|
|
}
|
|
if (doprint)
|
|
printf("\n");
|
|
return (incr);
|
|
}
|