]> git.wh0rd.org - ICEs.git/blobdiff - 555418/mips.c
more
[ICEs.git] / 555418 / mips.c
diff --git a/555418/mips.c b/555418/mips.c
new file mode 100644 (file)
index 0000000..714373a
--- /dev/null
@@ -0,0 +1,137 @@
+#include <stdint.h>
+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;
+}