diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /libinterp/das-s800.c | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'libinterp/das-s800.c')
| -rw-r--r-- | libinterp/das-s800.c | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/libinterp/das-s800.c b/libinterp/das-s800.c new file mode 100644 index 00000000..a96cc23a --- /dev/null +++ b/libinterp/das-s800.c @@ -0,0 +1,457 @@ +#include "lib9.h" +#include "isa.h" +#include "interp.h" + +/* s800 disassembler. */ +/* does not handle stuff that won't be generated */ + +typedef struct instr Instr; + +struct instr +{ + ulong value; /* bits 31-00 */ + uchar op; /* bits 31-26 */ + uchar subop; /* bits 11-05 */ + uchar sysop; /* bits 12-05 */ + uchar reg0; /* bits 25-21 */ + uchar reg1; /* bits 20-16 */ + uchar reg2; /* bits 4-0 */ + uchar space; /* bits 15-14 */ + uchar indexed; /* bit 13 */ + uchar cond; /* bits 15-13 */ + uchar sr; /* bits 13,15,14 */ + uchar ftype; /* bits 12-9 */ + uchar simm; /* bit 12 */ + uchar store; /* bit 9 */ + uchar size; /* bits 8-6 */ + uchar mod; /* bit 5 */ + uchar shz; /* bit 9-5 */ + long imm21; /* bits 20-00 */ + short simm14; /* bits 13-01, sign 00 */ + short simm11; /* bits 10-01, sign 00 */ + short simm5; /* bits 4-1, sign 0 */ + short off; /* bits 13-02, sign 00 */ + char csimm5; /* bits 20-17, sign 16 */ + char *curr; /* current fill level in output buffer */ + char *end; /* end of buffer */ +}; + +typedef struct opdec Opdec; + +struct opdec +{ + char *mnem; + void (*func)(Instr *, char *); +}; + +static char ill[] = "ILL"; +static char sizes[] = "BHWXXXXX"; + +static char *conds[8] = +{ + "never", + "equal", + "less", + "leq", + "lessu", + "lequ", + "sv", + "odd", +}; + +static char *fconds[8] = +{ + "F", + "==", + "<", + "<=", + ">", + ">=", + "!=", + "T", +}; + +static void das_nil(Instr *, char *); +static void das_sys(Instr *, char *); +static void das_arith(Instr *, char *); +static void das_ldwx(Instr *, char *); +static void das_ld(Instr *, char *); +static void das_ldil(Instr *, char *); +static void das_ldo(Instr *, char *); +static void das_st(Instr *, char *); +static void das_fldst(Instr *, char *); +static void das_fltc(Instr *, char *); +static void das_combt(Instr *, char *); +static void das_ibt(Instr *, char *); +static void das_combf(Instr *, char *); +static void das_ibf(Instr *, char *); +static void das_extrs(Instr *, char *); +static void das_be(Instr *, char *); +static void das_bx(Instr *, char *); + +Opdec dastab[1 << 6] = +{ + {ill, das_sys}, /* 0x00 */ + {ill, das_nil}, /* 0x01 */ + {ill, das_arith}, /* 0x02 */ + {ill, das_ldwx}, /* 0x03 */ + {ill, das_nil}, /* 0x04 */ + {ill, das_nil}, /* 0x05 */ + {ill, das_nil}, /* 0x06 */ + {ill, das_nil}, /* 0x07 */ + {ill, das_ldil}, /* 0x08 */ + {ill, das_nil}, /* 0x09 */ + {ill, das_nil}, /* 0x0A */ + {ill, das_fldst}, /* 0x0B */ + {ill, das_fltc}, /* 0x0C */ + {ill, das_ldo}, /* 0x0D */ + {ill, das_nil}, /* 0x0E */ + {ill, das_nil}, /* 0x0F */ + + {"LDB", das_ld}, /* 0x10 */ + {"LDH", das_ld}, /* 0x11 */ + {"LDW", das_ld}, /* 0x12 */ + {ill, das_nil}, /* 0x13 */ + {ill, das_nil}, /* 0x14 */ + {ill, das_nil}, /* 0x15 */ + {ill, das_nil}, /* 0x16 */ + {ill, das_nil}, /* 0x17 */ + {"STB", das_st}, /* 0x18 */ + {"STH", das_st}, /* 0x19 */ + {"STW", das_st}, /* 0x1A */ + {ill, das_nil}, /* 0x1B */ + {ill, das_nil}, /* 0x1C */ + {ill, das_nil}, /* 0x1D */ + {ill, das_nil}, /* 0x1E */ + {ill, das_nil}, /* 0x1F */ + + {ill, das_combt}, /* 0x20 */ + {"COM", das_ibt}, /* 0x21 */ + {ill, das_combf}, /* 0x22 */ + {"COM", das_ibf}, /* 0x23 */ + {ill, das_nil}, /* 0x24 */ + {ill, das_nil}, /* 0x25 */ + {ill, das_nil}, /* 0x26 */ + {ill, das_nil}, /* 0x27 */ + {ill, das_nil}, /* 0x28 */ + {"ADD", das_ibt}, /* 0x29 */ + {ill, das_nil}, /* 0x2A */ + {"ADD", das_ibf}, /* 0x2B */ + {ill, das_nil}, /* 0x2C */ + {ill, das_nil}, /* 0x2D */ + {ill, das_nil}, /* 0x2E */ + {ill, das_nil}, /* 0x2F */ + + {ill, das_nil}, /* 0x30 */ + {ill, das_nil}, /* 0x31 */ + {ill, das_nil}, /* 0x32 */ + {ill, das_nil}, /* 0x33 */ + {ill, das_extrs}, /* 0x34 */ + {ill, das_nil}, /* 0x35 */ + {ill, das_nil}, /* 0x36 */ + {ill, das_nil}, /* 0x37 */ + {"BE", das_be}, /* 0x38 */ + {"BLE", das_be}, /* 0x39 */ + {ill, das_bx}, /* 0x3A */ + {ill, das_nil}, /* 0x3B */ + {ill, das_nil}, /* 0x3C */ + {ill, das_nil}, /* 0x3D */ + {ill, das_nil}, /* 0x3E */ + {ill, das_nil}, /* 0x3F */ +}; + +static void +bprint(Instr *i, char *fmt, ...) +{ + va_list arg; + + va_start(arg, fmt); + i->curr = vseprint(i->curr, i->end, fmt, arg); + va_end(arg); +} + +static void +decode(ulong *pc, Instr *i) +{ + ulong w; + int t; + + w = *pc; + + i->value = w; + i->op = (w >> 26) & 0x3F; + i->subop = (w >> 5) & 0x7F; + i->sysop = (w >> 5) & 0xFF; + i->reg0 = (w >> 21) & 0x1F; + i->reg1 = (w >> 16) & 0x1F; + i->reg2 = w & 0x1F; + i->space = (w >> 14) & 0x03; + i->indexed = (w >> 13) & 0x01; + i->cond = (w >> 13) & 0x07; + i->sr = (i->cond >> 1) | ((i->cond & 1) << 2); + i->ftype = (w >> 9) & 0xF; + i->simm = (w >> 12) & 0x01; + i->store = (w >> 9) & 0x01; + i->size = (w >> 6) & 0x07; + i->mod = (w >> 5) & 0x01; + i->shz = (w >> 5) & 0x1F; + i->imm21 = w & 0x01FFFFF; + i->simm14 = (w >> 1) & 0x1FFF; + i->simm11 = (w >> 1) & 0x03FF; + i->simm5 = (w >> 1) & 0x0F; + i->off = ((w >> 3) & 0x3FF) | ((w & (1 << 2)) << 8); + i->csimm5 = (w >> 17) & 0x0F; + if(w & 1) { + i->simm14 |= ~((1 << 13) - 1); + i->simm11 |= ~((1 << 10) - 1); + i->simm5 |= ~((1 << 4) - 1); + i->off |= ~((1 << 10) - 1); + } + if(w & (1 << 16)) + i->csimm5 |= ~((1 << 4) - 1); +} + +static void +das_ill(Instr *i) +{ + das_nil(i, ill); +} + +static void +das_nil(Instr *i, char *m) +{ + bprint(i, "%s\t%lx", m, i->value); +} + +static void +das_sys(Instr *i, char *m) +{ + switch(i->sysop) { + case 0x85: + bprint(i, "LDSID\t(sr%d,r%d),r%d", i->sr, i->reg0, i->reg2); + break; + case 0xC1: + bprint(i, "MTSP\tr%d,sr%d", i->reg1, i->sr); + break; + default: + das_ill(i); + } +} + +static void +das_arith(Instr *i, char *m) +{ + switch(i->subop) { + case 0x10: + m = "AND"; + break; + case 0x12: + if (i->reg1 + i->reg0 + i->reg2 == 0) { + bprint(i, "NOP"); + return; + } + m = "OR"; + break; + case 0x14: + m = "XOR"; + break; + case 0x20: + m = "SUB"; + break; + case 0x30: + m = "ADD"; + break; + case 0x32: + m = "SH1ADD"; + break; + case 0x34: + m = "SH2ADD"; + break; + default: + das_ill(i); + return; + } + + bprint(i, "%s\tr%d,r%d,r%d", m, i->reg1, i->reg0, i->reg2); +} + +static void +das_ldwx(Instr *i, char *m) +{ + bprint(i, "LD%cX\tr%d(r%d),r%d", sizes[i->size], i->reg0, i->reg1, i->reg2); +} + +static void +das_ld(Instr *i, char *m) +{ + bprint(i, "%s\t%d(r%d),r%d", m, i->simm14, i->reg0, i->reg1); +} + +static ulong +unfrig17(ulong v) +{ + ulong r; + + r = ((v >> 3) & 0x3FF) | + ((v & (1 << 2)) << 8) | + ((v & (0x1F << 16)) >> 5); + if (v & 1) + r |= ~((1 << 16) - 1); + return r << 2; +} + +static ulong +unfrig21(ulong v) +{ + return (((v & 1) << 20) | + ((v & (0x7FF << 1)) << 8) | + ((v >> 12) & 3) | + ((v & (3 << 14)) >> 7) | + ((v & (0x1F << 16)) >> 14)) << 11; +} + +static void +das_ldil(Instr *i, char *m) +{ + bprint(i, "LDIL\tL%%0x%lx,r%d", unfrig21(i->imm21), i->reg0); +} + +static void +das_ldo(Instr *i, char *m) +{ + bprint(i, "LDO\t%d(r%d),r%d", i->simm14, i->reg0, i->reg1); +} + +static void +das_st(Instr *i, char *m) +{ + bprint(i, "%s\tr%d,%d(r%d)", m, i->reg1, i->simm14, i->reg0); +} + +static void +das_fldst(Instr *i, char *m) +{ + if (i->simm) { + if (i->store) + bprint(i, "FSTDS\tfr%d,%d(r%d)", i->reg2, i->csimm5, i->reg0); + else + bprint(i, "FLDDS\t%d(r%d),fr%d", i->reg0, i->csimm5, i->reg2); + } + else { + if (i->store) + bprint(i, "FSTDX\tfr%d,r%d(r%d)", i->reg2, i->reg1, i->reg0); + else + bprint(i, "FLDDX\tr%d(r%d),fr%d", i->reg0, i->reg1, i->reg2); + } +} + +static void +das_fltc(Instr *i, char *m) +{ + char *o; + + switch (i->ftype) { + case 2: + bprint(i, "FTEST"); + break; + case 6: + bprint(i, "FCMP\tfr%d,%s,fr%d", i->reg0, fconds[i->reg2 >> 2], i->reg1); + break; + case 7: + switch (i->cond) { + case 0: + o = "ADD"; + break; + case 1: + o = "SUB"; + break; + case 2: + o = "MUL"; + break; + case 3: + o = "DIV"; + break; + default: + das_ill(i); + return; + } + bprint(i, "F%s\tfr%d,fr%d,fr%d", o, i->reg0, i->reg1, i->reg2); + break; + default: + das_ill(i); + } +} + +static void +das_combt(Instr *i, char *m) +{ + bprint(i, "COMBT,%s\tr%d,r%d,%d", conds[i->cond], i->reg1, i->reg0, i->off); +} + +static void +das_ibt(Instr *i, char *m) +{ + bprint(i, "%sIBT,%s\t%d,r%d,%d", m, conds[i->cond], i->csimm5, i->reg0, i->off); +} + +static void +das_combf(Instr *i, char *m) +{ + bprint(i, "COMBF,%s\tr%d,r%d,%d", conds[i->cond], i->reg1, i->reg0, i->off); +} + +static void +das_ibf(Instr *i, char *m) +{ + bprint(i, "%sIBF,%s\t%d,r%d,%d", m, conds[i->cond], i->csimm5, i->reg0, i->off); +} + +static void +das_extrs(Instr *i, char *m) +{ + bprint(i, "EXTRS\tr%d,%d,%d,r%d", i->reg0, i->shz, 32 - i->reg2, i->reg1); +} + +static void +das_be(Instr *i, char *m) +{ + bprint(i, "%s\t%d(sr%d,r%d)", m, unfrig17(i->value), i->sr, i->reg0); +} + +static void +das_bx(Instr *i, char *m) +{ + switch(i->cond) { + case 0: + bprint(i, "BL\t%d,r%d", unfrig17(i->value), i->reg0); + break; + case 6: + bprint(i, "BV\tr%d(r%d)", i->reg1, i->reg0); + break; + default: + das_ill(i); + } +} + +static int +inst(ulong *pc) +{ + Instr instr; + static char buf[128]; + + decode(pc, &instr); + instr.curr = buf; + instr.end = buf + sizeof(buf) - 1; + (*dastab[instr.op].func)(&instr, dastab[instr.op].mnem); + if (cflag > 5) + print("\t%.8lux %.8lux %s\n", pc, *pc, buf); + else + print("\t%.8lux %s\n", pc, buf); +} + +void +das(ulong *x, int n) +{ + while (--n >= 0) + inst(x++); +} |
