]> git.wh0rd.org - ICEs.git/blame - 555418/mips.c
more
[ICEs.git] / 555418 / mips.c
CommitLineData
bd3239d2
MF
1#include <stdint.h>
2typedef struct {
3 uint32_t pc_exec, pc, r[32];
4} engine_state;
5static uint32_t engine_getbits(uint32_t fetched, int base, int width)
6{
7 return (fetched >> base) & ((((uint32_t) 0x1) << width) - 1);
8}
9static void *engine_decode(void **ijops, void **rops, uint32_t fetched)
10{
11 int ijcode = engine_getbits(fetched, 26, 6);
12 void *ij = ijops[ijcode], *r = rops[engine_getbits(fetched, 0, 6)];
13 if (0 == ijcode)
14 return r;
15 else
16 return ij;
17}
18static int32_t engine_sign(uint32_t u, int width)
19{
20 uint32_t msb = ((uint32_t) 0x1) << (width - 1);
21 return (u ^ msb) - msb;
22}
23static void engine_monitor(uint32_t pc_done, uint32_t pc_exec, uint32_t pc,
24 uint32_t inst)
25{
26 int i;
27 return;
28 //printf("%08x:%x-%x-%x\n", inst, pc_done * 4, pc_exec * 4, pc * 4);
29}
30/*
31http://www.d.umn.edu/~gshute/mips/instruction-types.xhtml
32https://www.student.cs.uwaterloo.ca/~isg/res/mips/opcodes
33http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
34*/
35int engine(engine_state * statep, uint32_t * memory)
36{
37 int i;
38 int rtn = 0;
39 void *ijops[64], *rops[64];
40 register uint32_t inst asm("edx");
41 register uint32_t pc_exec asm("ebx") = statep->pc_exec;
42 register uint32_t pc asm("ecx") = statep->pc;
43 uint32_t *r = statep->r;
44/* */
45#define COME(name) op_##name: { uint32_t ninst = memory[pc], pc_done = pc_exec; void *nlabel = engine_decode(ijops, rops, ninst); pc_exec = pc++
46#define JUMP(name) engine_monitor(pc_done, pc_exec, pc, inst); r[0] = 0; inst = ninst; asm volatile ("#" #name); goto *nlabel; } while (0)
47/* */
48#define REG_S (r[engine_getbits(inst, 21, 5)])
49#define REG_T (r[engine_getbits(inst, 16, 5)])
50#define REG_D (r[engine_getbits(inst, 11, 5)])
51#define IMM_A (engine_getbits(inst, 6, 5))
52#define IMM_I ((uint16_t) inst)
53#define IMM_SI ((int16_t) inst)
54#define IMM_J (engine_getbits(inst, 0, 26))
55/* */
56 for (i = 0; i < 64; i++)
57 ijops[i] = rops[i] = &&op_undef;
58#define OP(code,mnemonic) ijops[code] = &&op_##mnemonic
59 OP(0x02, j);
60 OP(0x03, jal);
61 OP(0x04, beq);
62 OP(0x05, bne);
63 OP(0x09, addiu);
64 OP(0x0c, andi);
65 OP(0x0d, ori);
66 OP(0x0f, lui);
67#undef OP
68#define OP(code,mnemonic) rops[code] = &&op_##mnemonic
69 OP(0x00, sll);
70 OP(0x02, srl);
71 OP(0x08, jr);
72 OP(0x0c, syscall);
73 OP(0x21, addu);
74 OP(0x26, xor);
75#undef OP
76 inst = memory[pc_exec];
77 r[0] = 0;
78 goto *engine_decode(ijops, rops, inst);
79/* interrupt */
80 COME(syscall);
81 pc = pc_exec;
82 pc_exec = pc_done;
83 goto end;
84 JUMP(syscall);
85 COME(undef);
86 pc = pc_exec;
87 pc_exec = pc_done;
88 rtn = 1;
89 goto end;
90 JUMP(undef);
91/* jump */
92 COME(j);
93 pc = (pc_exec & 0xfc000000) | IMM_J;
94 JUMP(j);
95 COME(jal);
96 r[31] = pc * 4;
97 pc = (pc_exec & 0xfc000000) | IMM_J;
98 JUMP(jal);
99 COME(jr);
100 pc = REG_S / 4;
101 JUMP(jr);
102/* branch */
103#define STEM_BRANCH(op,name) \
104COME(name); { uint32_t leap = pc_exec + IMM_SI; if (REG_S op REG_T) pc = leap; } JUMP(name)
105 STEM_BRANCH( ==, beq);
106 STEM_BRANCH(!=, bne);
107/* register to register */
108 COME(addiu);
109 REG_T = REG_S + IMM_SI;
110 JUMP(addiu);
111 COME(addu);
112 REG_D = REG_S + REG_T;
113 JUMP(addu);
114 COME(andi);
115 REG_T = REG_S & IMM_I;
116 JUMP(andi);
117 COME(lui);
118 REG_T = IMM_I << 16;
119 JUMP(lui);
120 COME(ori);
121 REG_T = REG_S | IMM_I;
122 JUMP(ori);
123 COME(sll);
124 REG_D = REG_T << IMM_A;
125 JUMP(sll);
126 COME(srl);
127 REG_D = REG_T >> IMM_A;
128 JUMP(srl);
129 COME(xor);
130 REG_D = REG_S ^ REG_T;
131 JUMP(xor);
132/* */
133 end:
134 statep->pc_exec = pc_exec;
135 statep->pc = pc;
136 return rtn;
137}