X-Git-Url: https://git.wh0rd.org/?p=ICEs.git;a=blobdiff_plain;f=555418%2Fmips.c;fp=555418%2Fmips.c;h=714373a6d18141c927c83e2fe3858c2b5f5a87af;hp=0000000000000000000000000000000000000000;hb=bd3239d2bbe0de3a200b266503e3330b1e391489;hpb=dbff64cb4b7530861c2309c794efdd4e0cf47a23 diff --git a/555418/mips.c b/555418/mips.c new file mode 100644 index 0000000..714373a --- /dev/null +++ b/555418/mips.c @@ -0,0 +1,137 @@ +#include +typedef struct { + uint32_t pc_exec, pc, r[32]; +} engine_state; +static uint32_t engine_getbits(uint32_t fetched, int base, int width) +{ + return (fetched >> base) & ((((uint32_t) 0x1) << width) - 1); +} +static void *engine_decode(void **ijops, void **rops, uint32_t fetched) +{ + int ijcode = engine_getbits(fetched, 26, 6); + void *ij = ijops[ijcode], *r = rops[engine_getbits(fetched, 0, 6)]; + if (0 == ijcode) + return r; + else + return ij; +} +static int32_t engine_sign(uint32_t u, int width) +{ + uint32_t msb = ((uint32_t) 0x1) << (width - 1); + return (u ^ msb) - msb; +} +static void engine_monitor(uint32_t pc_done, uint32_t pc_exec, uint32_t pc, + uint32_t inst) +{ + int i; + return; + //printf("%08x:%x-%x-%x\n", inst, pc_done * 4, pc_exec * 4, pc * 4); +} +/* +http://www.d.umn.edu/~gshute/mips/instruction-types.xhtml +https://www.student.cs.uwaterloo.ca/~isg/res/mips/opcodes +http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html +*/ +int engine(engine_state * statep, uint32_t * memory) +{ + int i; + int rtn = 0; + void *ijops[64], *rops[64]; + register uint32_t inst asm("edx"); + register uint32_t pc_exec asm("ebx") = statep->pc_exec; + register uint32_t pc asm("ecx") = statep->pc; + uint32_t *r = statep->r; +/* */ +#define COME(name) op_##name: { uint32_t ninst = memory[pc], pc_done = pc_exec; void *nlabel = engine_decode(ijops, rops, ninst); pc_exec = pc++ +#define JUMP(name) engine_monitor(pc_done, pc_exec, pc, inst); r[0] = 0; inst = ninst; asm volatile ("#" #name); goto *nlabel; } while (0) +/* */ +#define REG_S (r[engine_getbits(inst, 21, 5)]) +#define REG_T (r[engine_getbits(inst, 16, 5)]) +#define REG_D (r[engine_getbits(inst, 11, 5)]) +#define IMM_A (engine_getbits(inst, 6, 5)) +#define IMM_I ((uint16_t) inst) +#define IMM_SI ((int16_t) inst) +#define IMM_J (engine_getbits(inst, 0, 26)) +/* */ + for (i = 0; i < 64; i++) + ijops[i] = rops[i] = &&op_undef; +#define OP(code,mnemonic) ijops[code] = &&op_##mnemonic + OP(0x02, j); + OP(0x03, jal); + OP(0x04, beq); + OP(0x05, bne); + OP(0x09, addiu); + OP(0x0c, andi); + OP(0x0d, ori); + OP(0x0f, lui); +#undef OP +#define OP(code,mnemonic) rops[code] = &&op_##mnemonic + OP(0x00, sll); + OP(0x02, srl); + OP(0x08, jr); + OP(0x0c, syscall); + OP(0x21, addu); + OP(0x26, xor); +#undef OP + inst = memory[pc_exec]; + r[0] = 0; + goto *engine_decode(ijops, rops, inst); +/* interrupt */ + COME(syscall); + pc = pc_exec; + pc_exec = pc_done; + goto end; + JUMP(syscall); + COME(undef); + pc = pc_exec; + pc_exec = pc_done; + rtn = 1; + goto end; + JUMP(undef); +/* jump */ + COME(j); + pc = (pc_exec & 0xfc000000) | IMM_J; + JUMP(j); + COME(jal); + r[31] = pc * 4; + pc = (pc_exec & 0xfc000000) | IMM_J; + JUMP(jal); + COME(jr); + pc = REG_S / 4; + JUMP(jr); +/* branch */ +#define STEM_BRANCH(op,name) \ +COME(name); { uint32_t leap = pc_exec + IMM_SI; if (REG_S op REG_T) pc = leap; } JUMP(name) + STEM_BRANCH( ==, beq); + STEM_BRANCH(!=, bne); +/* register to register */ + COME(addiu); + REG_T = REG_S + IMM_SI; + JUMP(addiu); + COME(addu); + REG_D = REG_S + REG_T; + JUMP(addu); + COME(andi); + REG_T = REG_S & IMM_I; + JUMP(andi); + COME(lui); + REG_T = IMM_I << 16; + JUMP(lui); + COME(ori); + REG_T = REG_S | IMM_I; + JUMP(ori); + COME(sll); + REG_D = REG_T << IMM_A; + JUMP(sll); + COME(srl); + REG_D = REG_T >> IMM_A; + JUMP(srl); + COME(xor); + REG_D = REG_S ^ REG_T; + JUMP(xor); +/* */ + end: + statep->pc_exec = pc_exec; + statep->pc = pc; + return rtn; +}