1 /* radare2 - LGPL - Copyright 2013-2019 - pancake */
2
3 #include <r_asm.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <mips.h>
7
8 static ut64 t9_pre = UT64_MAX;
9 // http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
10
11 #define OPERAND(x) insn->detail->mips.operands[x]
12 #define REGID(x) insn->detail->mips.operands[x].reg
13 #define REG(x) cs_reg_name (*handle, insn->detail->mips.operands[x].reg)
14 #define IMM(x) insn->detail->mips.operands[x].imm
15 #define MEMBASE(x) cs_reg_name(*handle, insn->detail->mips.operands[x].mem.base)
16 #define MEMINDEX(x) insn->detail->mips.operands[x].mem.index
17 #define MEMDISP(x) insn->detail->mips.operands[x].mem.disp
18 #define OPCOUNT() insn->detail->mips.op_count
19 // TODO scale and disp
20
21 #define SET_VAL(op,i) \
22 if ((i)<OPCOUNT() && OPERAND(i).type == MIPS_OP_IMM) {\
23 (op)->val = OPERAND(i).imm;\
24 }
25
26 #define CREATE_SRC_DST_3(op) \
27 (op)->src[0] = r_anal_value_new ();\
28 (op)->src[1] = r_anal_value_new ();\
29 (op)->dst = r_anal_value_new ();
30
31 #define CREATE_SRC_DST_2(op) \
32 (op)->src[0] = r_anal_value_new ();\
33 (op)->dst = r_anal_value_new ();
34
35 #define SET_SRC_DST_3_REGS(op) \
36 CREATE_SRC_DST_3 (op);\
37 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
38 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);\
39 (op)->src[1]->reg = r_reg_get (anal->reg, REG (2), R_REG_TYPE_GPR);
40
41 #define SET_SRC_DST_3_IMM(op) \
42 CREATE_SRC_DST_3 (op);\
43 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
44 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);\
45 (op)->src[1]->imm = IMM (2);
46
47 #define SET_SRC_DST_2_REGS(op) \
48 CREATE_SRC_DST_2 (op);\
49 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
50 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);
51
52 #define SET_SRC_DST_3_REG_OR_IMM(op) \
53 if (OPERAND(2).type == MIPS_OP_IMM) {\
54 SET_SRC_DST_3_IMM (op);\
55 } else if (OPERAND(2).type == MIPS_OP_REG) {\
56 SET_SRC_DST_3_REGS (op);\
57 }
58
59
60 // ESIL macros:
61
62 // put the sign bit on the stack
63 #define ES_IS_NEGATIVE(arg) "1,"arg",<<<,1,&"
64
65
66 // call with delay slot
67 #define ES_CALL_DR(ra, addr) "pc,4,+,"ra",=,"ES_J(addr)
68 #define ES_CALL_D(addr) ES_CALL_DR("ra", addr)
69
70 // call without delay slot
71 #define ES_CALL_NDR(ra, addr) "pc,"ra",=,"ES_J(addr)
72 #define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr)
73
74 #define USE_DS 0
75 #if USE_DS
76 // emit ERR trap if executed in a delay slot
77 #define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,},"
78 // jump to address
79 #define ES_J(addr) addr",SETJT,1,SETD"
80 #else
81 #define ES_TRAP_DS() ""
82 #define ES_J(addr) addr",pc,="
83 #endif
84
85 #define ES_B(x) "0xff,"x",&"
86 #define ES_H(x) "0xffff,"x",&"
87 #define ES_W(x) "0xffffffff,"x",&"
88
89 // sign extend 32 -> 64
90 #define ES_SIGN32_64(arg) es_sign_n_64 (a, op, arg, 32)
91 #define ES_SIGN16_64(arg) es_sign_n_64 (a, op, arg, 16)
92
93 #define ES_ADD_CK32_OVERF(x, y, z) es_add_ck (op, x, y, z, 32)
94 #define ES_ADD_CK64_OVERF(x, y, z) es_add_ck (op, x, y, z, 64)
95
es_sign_n_64(RAnal * a,RAnalOp * op,const char * arg,int bit)96 static inline void es_sign_n_64(RAnal *a, RAnalOp *op, const char *arg, int bit)
97 {
98 if (a->bits == 64) {
99 r_strbuf_appendf (&op->esil, ",%d,%s,~,%s,=,", bit, arg, arg);
100 } else {
101 r_strbuf_append (&op->esil,",");
102 }
103 }
104
es_add_ck(RAnalOp * op,const char * a1,const char * a2,const char * re,int bit)105 static inline void es_add_ck(RAnalOp *op, const char *a1, const char *a2, const char *re, int bit)
106 {
107 ut64 mask = 1ULL << (bit-1);
108 r_strbuf_appendf (&op->esil,
109 "%d,0x%" PFMT64x ",%s,%s,^,&,>>,%d,0x%" PFMT64x ",%s,%s,+,&,>>,|,1,==,$z,?{,$$,1,TRAP,}{,%s,%s,+,%s,=,}",
110 bit-2, mask, a1, a2, bit-1, mask, a1, a2, a1, a2, re);
111 }
112
113 #define PROTECT_ZERO() \
114 if (REG(0)[0]=='z'){\
115 r_strbuf_appendf (&op->esil, ",");\
116 } else
117
118 #define ESIL_LOAD(size) \
119 PROTECT_ZERO () {\
120 r_strbuf_appendf (&op->esil, "%s,["size"],%s,=",\
121 ARG(1), REG(0));\
122 }
123
opex(RStrBuf * buf,csh handle,cs_insn * insn)124 static void opex(RStrBuf *buf, csh handle, cs_insn *insn) {
125 int i;
126 PJ *pj = pj_new ();
127 if (!pj) {
128 return;
129 }
130 pj_o (pj);
131 pj_ka (pj, "operands");
132 cs_mips *x = &insn->detail->mips;
133 for (i = 0; i < x->op_count; i++) {
134 cs_mips_op *op = x->operands + i;
135 pj_o (pj);
136 switch (op->type) {
137 case MIPS_OP_REG:
138 pj_ks (pj, "type", "reg");
139 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
140 break;
141 case MIPS_OP_IMM:
142 pj_ks (pj, "type", "imm");
143 pj_kN (pj, "value", op->imm);
144 break;
145 case MIPS_OP_MEM:
146 pj_ks (pj, "type", "mem");
147 if (op->mem.base != MIPS_REG_INVALID) {
148 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
149 }
150 pj_kN (pj, "disp", op->mem.disp);
151 break;
152 default:
153 pj_ks (pj, "type", "invalid");
154 break;
155 }
156 pj_end (pj); /* o operand */
157 }
158 pj_end (pj); /* a operands */
159 pj_end (pj);
160
161 r_strbuf_init (buf);
162 r_strbuf_append (buf, pj_string (pj));
163 pj_free (pj);
164 }
165
arg(csh * handle,cs_insn * insn,char * buf,int n)166 static const char *arg(csh *handle, cs_insn *insn, char *buf, int n) {
167 *buf = 0;
168 switch (insn->detail->mips.operands[n].type) {
169 case MIPS_OP_INVALID:
170 break;
171 case MIPS_OP_REG:
172 sprintf (buf, "%s",
173 cs_reg_name (*handle,
174 insn->detail->mips.operands[n].reg));
175 break;
176 case MIPS_OP_IMM:
177 {
178 st64 x = (st64)insn->detail->mips.operands[n].imm;
179 sprintf (buf, "%"PFMT64d, x);
180 }
181 break;
182 case MIPS_OP_MEM:
183 {
184 int disp = insn->detail->mips.operands[n].mem.disp;
185 if (disp<0) {
186 sprintf (buf, "%"PFMT64d",%s,-",
187 (ut64)-insn->detail->mips.operands[n].mem.disp,
188 cs_reg_name (*handle,
189 insn->detail->mips.operands[n].mem.base));
190 } else {
191 sprintf (buf, "0x%"PFMT64x",%s,+",
192 (ut64)insn->detail->mips.operands[n].mem.disp,
193 cs_reg_name (*handle,
194 insn->detail->mips.operands[n].mem.base));
195 }
196 }
197 break;
198 }
199 return buf;
200 }
201
202 #define ARG(x) (*str[x]!=0)?str[x]:arg(handle, insn, str[x], x)
203
analop_esil(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)204 static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
205 char str[8][32] = {{0}};
206 int i;
207
208 r_strbuf_init (&op->esil);
209 r_strbuf_set (&op->esil, "");
210
211 if (insn) {
212 // caching operands
213 for (i = 0; i < insn->detail->mips.op_count && i < 8; i++) {
214 *str[i] = 0;
215 ARG (i);
216 }
217 }
218
219 if (insn) {
220 switch (insn->id) {
221 case MIPS_INS_NOP:
222 r_strbuf_setf (&op->esil, ",");
223 break;
224 case MIPS_INS_BREAK:
225 r_strbuf_setf (&op->esil, "%"PFMT64d",%" PFMT64d ",TRAP", (st64)IMM (0), (st64)IMM (0));
226 break;
227 case MIPS_INS_SD:
228 r_strbuf_appendf (&op->esil, "%s,%s,=[8]",
229 ARG (0), ARG (1));
230 break;
231 case MIPS_INS_SW:
232 case MIPS_INS_SWL:
233 case MIPS_INS_SWR:
234 r_strbuf_appendf (&op->esil, "%s,%s,=[4]",
235 ARG (0), ARG (1));
236 break;
237 case MIPS_INS_SH:
238 r_strbuf_appendf (&op->esil, "%s,%s,=[2]",
239 ARG (0), ARG (1));
240 break;
241 case MIPS_INS_SWC1:
242 case MIPS_INS_SWC2:
243 r_strbuf_setf (&op->esil, "%s,$", ARG (1));
244 break;
245 case MIPS_INS_SB:
246 r_strbuf_appendf (&op->esil, "%s,%s,=[1]",
247 ARG (0), ARG (1));
248 break;
249 case MIPS_INS_CMP:
250 case MIPS_INS_CMPU:
251 case MIPS_INS_CMPGU:
252 case MIPS_INS_CMPGDU:
253 case MIPS_INS_CMPI:
254 r_strbuf_appendf (&op->esil, "%s,%s,==", ARG (1), ARG (0));
255 break;
256 case MIPS_INS_DSRA:
257 r_strbuf_appendf (&op->esil,
258 "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=",
259 ARG (2), ARG (1), ARG (1), ARG (2), ARG (0));
260 break;
261 case MIPS_INS_SHRAV:
262 case MIPS_INS_SHRAV_R:
263 case MIPS_INS_SHRA:
264 case MIPS_INS_SHRA_R:
265 case MIPS_INS_SRA:
266 r_strbuf_appendf (&op->esil,
267 "0xffffffff,%s,%s,>>,&,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=",
268 ARG (2), ARG (1), ARG (1), ARG (2), ARG (0));
269 break;
270 case MIPS_INS_SHRL:
271 // suffix 'S' forces conditional flag to be updated
272 case MIPS_INS_SRLV:
273 case MIPS_INS_SRL:
274 r_strbuf_appendf (&op->esil, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0));
275 break;
276 case MIPS_INS_SLLV:
277 case MIPS_INS_SLL:
278 r_strbuf_appendf (&op->esil, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0));
279 break;
280 case MIPS_INS_BAL:
281 case MIPS_INS_JAL:
282 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_D ("%s"), ARG (0));
283 break;
284 case MIPS_INS_JALR:
285 case MIPS_INS_JALRS:
286 if (OPCOUNT () < 2) {
287 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_D ("%s"), ARG (0));
288 } else {
289 PROTECT_ZERO () {
290 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_DR ("%s", "%s"), ARG (0), ARG (1));
291 }
292 }
293 break;
294 case MIPS_INS_JALRC: // no delay
295 if (OPCOUNT () < 2) {
296 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_ND ("%s"), ARG (0));
297 } else {
298 PROTECT_ZERO () {
299 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_CALL_NDR ("%s", "%s"), ARG (0), ARG (1));
300 }
301 }
302 break;
303 case MIPS_INS_JRADDIUSP:
304 // increment stackpointer in X and jump to %ra
305 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,sp,+=," ES_J ("ra"), ARG (0));
306 break;
307 case MIPS_INS_JR:
308 case MIPS_INS_JRC:
309 case MIPS_INS_J:
310 case MIPS_INS_B: // ???
311 // jump to address with conditional
312 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "" ES_J ("%s"), ARG (0));
313 break;
314 case MIPS_INS_BNE: // bne $s, $t, offset
315 case MIPS_INS_BNEL:
316 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,!,?{," ES_J ("%s") ",}",
317 ARG (0), ARG (1), ARG (2));
318 break;
319 case MIPS_INS_BEQ:
320 case MIPS_INS_BEQL:
321 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,%s,==,$z,?{," ES_J ("%s") ",}",
322 ARG (0), ARG (1), ARG (2));
323 break;
324 case MIPS_INS_BZ:
325 case MIPS_INS_BEQZ:
326 case MIPS_INS_BEQZC:
327 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,?{," ES_J ("%s") ",}",
328 ARG (0), ARG (1));
329 break;
330 case MIPS_INS_BNEZ:
331 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,!,?{," ES_J ("%s") ",}",
332 ARG (0), ARG (1));
333 break;
334 case MIPS_INS_BEQZALC:
335 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "%s,0,==,$z,?{," ES_CALL_ND ("%s") ",}",
336 ARG (0), ARG (1));
337 break;
338 case MIPS_INS_BLEZ:
339 case MIPS_INS_BLEZC:
340 case MIPS_INS_BLEZL:
341 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{," ES_J ("%s") ",BREAK,},",
342 ARG (0), ARG (1));
343 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}",
344 ARG (0), ARG (1));
345 break;
346 case MIPS_INS_BGEZ:
347 case MIPS_INS_BGEZC:
348 case MIPS_INS_BGEZL:
349 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}",
350 ARG (0), ARG (1));
351 break;
352 case MIPS_INS_BGEZAL:
353 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_CALL_D ("%s") ",}",
354 ARG (0), ARG (1));
355 break;
356 case MIPS_INS_BGEZALC:
357 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_CALL_ND ("%s") ",}",
358 ARG (0), ARG (1));
359 break;
360 case MIPS_INS_BGTZALC:
361 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{,BREAK,},", ARG (0));
362 r_strbuf_appendf (&op->esil, "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_CALL_ND ("%s") ",}",
363 ARG (0), ARG (1));
364 break;
365 case MIPS_INS_BLTZAL:
366 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_CALL_D ("%s") ",}", ARG (0), ARG (1));
367 break;
368 case MIPS_INS_BLTZ:
369 case MIPS_INS_BLTZC:
370 case MIPS_INS_BLTZL:
371 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "1," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}",
372 ARG (0), ARG (1));
373 break;
374 case MIPS_INS_BGTZ:
375 case MIPS_INS_BGTZC:
376 case MIPS_INS_BGTZL:
377 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,%s,==,$z,?{,BREAK,},", ARG (0));
378 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0," ES_IS_NEGATIVE ("%s") ",==,$z,?{," ES_J ("%s") ",}",
379 ARG (0), ARG (1));
380 break;
381 case MIPS_INS_BTEQZ:
382 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,?{," ES_J ("%s") ",}", ARG (0));
383 break;
384 case MIPS_INS_BTNEZ:
385 r_strbuf_appendf (&op->esil, ES_TRAP_DS () "0,t,==,$z,!,?{," ES_J ("%s") ",}", ARG (0));
386 break;
387 case MIPS_INS_MOV:
388 case MIPS_INS_MOVE:
389 PROTECT_ZERO () {
390 r_strbuf_appendf (&op->esil, "%s,%s,=", ARG (1), REG (0));
391 }
392 break;
393 case MIPS_INS_MOVZ:
394 case MIPS_INS_MOVF:
395 PROTECT_ZERO () {
396 r_strbuf_appendf (&op->esil, "0,%s,==,$z,?{,%s,%s,=,}",
397 ARG (2), ARG (1), REG (0));
398 }
399 break;
400 case MIPS_INS_MOVT:
401 PROTECT_ZERO () {
402 r_strbuf_appendf (&op->esil, "1,%s,==,$z,?{,%s,%s,=,}",
403 ARG (2), ARG (1), REG (0));
404 }
405 break;
406 case MIPS_INS_FSUB:
407 case MIPS_INS_SUB:
408 case MIPS_INS_SUBU:
409 case MIPS_INS_DSUB:
410 case MIPS_INS_DSUBU:
411 PROTECT_ZERO () {
412 r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=",
413 ARG (2), ARG (1), ARG (0));
414 }
415 break;
416 case MIPS_INS_NEG:
417 case MIPS_INS_NEGU:
418 r_strbuf_appendf (&op->esil, "%s,0,-,%s,=,",
419 ARG (1), ARG (0));
420 break;
421
422 /** signed -- sets overflow flag */
423 case MIPS_INS_ADD: {
424 PROTECT_ZERO () {
425 ES_ADD_CK32_OVERF (ARG(1), ARG(2), ARG(0));
426 }
427 }
428 break;
429 case MIPS_INS_ADDI:
430 PROTECT_ZERO () {
431 ES_ADD_CK32_OVERF (ARG(1), ARG(2), ARG(0));
432 }
433 break;
434 case MIPS_INS_DADD:
435 case MIPS_INS_DADDI:
436 ES_ADD_CK64_OVERF (ARG(1), ARG(2), ARG(0));
437 break;
438 /** unsigned */
439 case MIPS_INS_DADDU:
440 case MIPS_INS_ADDU:
441 case MIPS_INS_ADDIU:
442 case MIPS_INS_DADDIU:
443 {
444 const char *arg0 = ARG(0);
445 const char *arg1 = ARG(1);
446 const char *arg2 = ARG(2);
447 PROTECT_ZERO () {
448 if (*arg2 == '-') {
449 r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=",
450 arg2+1, arg1, arg0);
451 } else {
452 r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=",
453 arg2, arg1, arg0);
454 }
455 }
456 }
457 break;
458 case MIPS_INS_LI:
459 case MIPS_INS_LDI:
460 r_strbuf_appendf (&op->esil, "0x%" PFMT64x ",%s,=", (ut64)IMM(1), ARG(0));
461 break;
462 case MIPS_INS_LUI:
463 r_strbuf_appendf (&op->esil, "0x%" PFMT64x "0000,%s,=", (ut64)IMM(1), ARG(0));
464 break;
465 case MIPS_INS_LB:
466 op->sign = true;
467 ESIL_LOAD ("1");
468 break;
469 case MIPS_INS_LBU:
470 //one of these is wrong
471 ESIL_LOAD ("1");
472 break;
473 case MIPS_INS_LW:
474 case MIPS_INS_LWC1:
475 case MIPS_INS_LWC2:
476 case MIPS_INS_LWL:
477 case MIPS_INS_LWR:
478 case MIPS_INS_LWU:
479 case MIPS_INS_LL:
480 ESIL_LOAD ("4");
481 break;
482
483 case MIPS_INS_LDL:
484 case MIPS_INS_LDC1:
485 case MIPS_INS_LDC2:
486 case MIPS_INS_LLD:
487 case MIPS_INS_LD:
488 ESIL_LOAD ("8");
489 break;
490
491 case MIPS_INS_LWX:
492 case MIPS_INS_LH:
493 case MIPS_INS_LHU:
494 case MIPS_INS_LHX:
495 ESIL_LOAD ("2");
496 break;
497
498 case MIPS_INS_AND:
499 case MIPS_INS_ANDI:
500 {
501 const char *arg0 = ARG(0);
502 const char *arg1 = ARG(1);
503 const char *arg2 = ARG(2);
504 if (!strcmp (arg0, arg1)) {
505 r_strbuf_appendf (&op->esil, "%s,%s,&=", arg2, arg1);
506 } else {
507 r_strbuf_appendf (&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0);
508 }
509 }
510 break;
511 case MIPS_INS_OR:
512 case MIPS_INS_ORI:
513 {
514 const char *arg0 = ARG(0);
515 const char *arg1 = ARG(1);
516 const char *arg2 = ARG(2);
517 PROTECT_ZERO () {
518 r_strbuf_appendf (&op->esil, "%s,%s,|,%s,=",
519 arg2, arg1, arg0);
520 }
521 }
522 break;
523 case MIPS_INS_XOR:
524 case MIPS_INS_XORI:
525 {
526 const char *arg0 = ARG(0);
527 const char *arg1 = ARG(1);
528 const char *arg2 = ARG(2);
529 PROTECT_ZERO () {
530 r_strbuf_appendf (&op->esil, "%s,%s,^,%s,=",
531 arg2, arg1, arg0);
532 }
533 }
534 break;
535 case MIPS_INS_NOR:
536 {
537 const char *arg0 = ARG(0);
538 const char *arg1 = ARG(1);
539 const char *arg2 = ARG(2);
540 PROTECT_ZERO () {
541 r_strbuf_appendf (&op->esil, "%s,%s,|,0xffffffff,^,%s,=",
542 arg2, arg1, arg0);
543 }
544 }
545 break;
546 case MIPS_INS_SLT:
547 case MIPS_INS_SLTI:
548 if (OPCOUNT () < 3) {
549 r_strbuf_appendf (&op->esil, "%s,%s,<,t,=", ARG(1), ARG(0));
550 } else {
551 r_strbuf_appendf (&op->esil, "%s,%s,<,%s,=", ARG(2), ARG(1), ARG(0));
552 }
553 break;
554 case MIPS_INS_SLTU:
555 case MIPS_INS_SLTIU:
556 if (OPCOUNT () < 3) {
557 r_strbuf_appendf (&op->esil, ES_W("%s")","ES_W("%s")",<,t,=",
558 ARG (1), ARG (0));
559 } else {
560 r_strbuf_appendf (&op->esil, ES_W("%s")","ES_W("%s")",<,%s,=",
561 ARG (2), ARG (1), ARG (0));
562 }
563 break;
564 case MIPS_INS_MUL:
565 r_strbuf_appendf (&op->esil, ES_W("%s,%s,*")",%s,=", ARG(1), ARG(2), ARG(0));
566 ES_SIGN32_64 (ARG(0));
567 break;
568 case MIPS_INS_MULT:
569 case MIPS_INS_MULTU:
570 r_strbuf_appendf (&op->esil, ES_W("%s,%s,*")",lo,=", ARG (0), ARG (1));
571 ES_SIGN32_64 ("lo");
572 r_strbuf_appendf (&op->esil, ES_W("32,%s,%s,*,>>")",hi,=", ARG (0), ARG (1));
573 ES_SIGN32_64 ("hi");
574 break;
575 case MIPS_INS_MFLO:
576 PROTECT_ZERO () {
577 r_strbuf_appendf (&op->esil, "lo,%s,=", REG (0));
578 }
579 break;
580 case MIPS_INS_MFHI:
581 PROTECT_ZERO () {
582 r_strbuf_appendf (&op->esil, "hi,%s,=", REG (0));
583 }
584 break;
585 case MIPS_INS_MTLO:
586 r_strbuf_appendf (&op->esil, "%s,lo,=", REG (0));
587 ES_SIGN32_64 ("lo");
588 break;
589 case MIPS_INS_MTHI:
590 r_strbuf_appendf (&op->esil, "%s,hi,=", REG (0));
591 ES_SIGN32_64 ("hi");
592 break;
593 #if 0
594 // could not test div
595 case MIPS_INS_DIV:
596 case MIPS_INS_DIVU:
597 case MIPS_INS_DDIV:
598 case MIPS_INS_DDIVU:
599 PROTECT_ZERO () {
600 // 32 bit needs sign extend
601 r_strbuf_appendf (&op->esil, "%s,%s,/,lo,=,%s,%s,%%,hi,=", REG(1), REG(0), REG(1), REG(0));
602 }
603 break;
604 #endif
605 default:
606 return -1;
607 }
608 }
609 return 0;
610 }
611
parse_reg_name(RRegItem * reg,csh handle,cs_insn * insn,int reg_num)612 static int parse_reg_name(RRegItem *reg, csh handle, cs_insn *insn, int reg_num) {
613 if (!reg) {
614 return -1;
615 }
616 switch (OPERAND (reg_num).type) {
617 case MIPS_OP_REG:
618 reg->name = (char *)cs_reg_name (handle, OPERAND (reg_num).reg);
619 break;
620 case MIPS_OP_MEM:
621 if (OPERAND (reg_num).mem.base != MIPS_REG_INVALID) {
622 reg->name = (char *)cs_reg_name (handle, OPERAND (reg_num).mem.base);
623 }
624 default:
625 break;
626 }
627 return 0;
628 }
629
op_fillval(RAnal * anal,RAnalOp * op,csh * handle,cs_insn * insn)630 static void op_fillval(RAnal *anal, RAnalOp *op, csh *handle, cs_insn *insn) {
631 static RRegItem reg;
632 switch (op->type & R_ANAL_OP_TYPE_MASK) {
633 case R_ANAL_OP_TYPE_LOAD:
634 if (OPERAND(1).type == MIPS_OP_MEM) {
635 ZERO_FILL (reg);
636 op->src[0] = r_anal_value_new ();
637 op->src[0]->reg = ®
638 parse_reg_name (op->src[0]->reg, *handle, insn, 1);
639 op->src[0]->delta = OPERAND(1).mem.disp;
640 }
641 break;
642 case R_ANAL_OP_TYPE_STORE:
643 if (OPERAND(1).type == MIPS_OP_MEM) {
644 ZERO_FILL (reg);
645 op->dst = r_anal_value_new ();
646 op->dst->reg = ®
647 parse_reg_name (op->dst->reg, *handle, insn, 1);
648 op->dst->delta = OPERAND(1).mem.disp;
649 }
650 break;
651 case R_ANAL_OP_TYPE_SHL:
652 case R_ANAL_OP_TYPE_SHR:
653 case R_ANAL_OP_TYPE_SAR:
654 case R_ANAL_OP_TYPE_XOR:
655 case R_ANAL_OP_TYPE_SUB:
656 case R_ANAL_OP_TYPE_AND:
657 case R_ANAL_OP_TYPE_ADD:
658 case R_ANAL_OP_TYPE_OR:
659 SET_SRC_DST_3_REG_OR_IMM (op);
660 break;
661 case R_ANAL_OP_TYPE_MOV:
662 SET_SRC_DST_3_REG_OR_IMM (op);
663 break;
664 case R_ANAL_OP_TYPE_DIV: // UDIV
665 #if 0
666 capstone bug
667 ------------
668 $ r2 -a mips -e cfg.bigendian=1 -c "wx 0083001b" -
669 // should be 3 regs, right?
670 [0x00000000]> aoj~{}
671 [
672 {
673 "opcode": "divu zero, a0, v1",
674 "disasm": "divu zero, a0, v1",
675 "mnemonic": "divu",
676 "sign": false,
677 "prefix": 0,
678 "id": 192,
679 "opex": {
680 "operands": [
681 {
682 "type": "reg",
683 "value": "a0"
684 },
685 {
686 "type": "reg",
687 "value": "v1"
688 }
689 ]
690 },
691 #endif
692 if (OPERAND(0).type == MIPS_OP_REG && OPERAND(1).type == MIPS_OP_REG && OPERAND(2).type == MIPS_OP_REG) {
693 SET_SRC_DST_3_REGS (op);
694 } else if (OPERAND(0).type == MIPS_OP_REG && OPERAND(1).type == MIPS_OP_REG) {
695 SET_SRC_DST_2_REGS (op);
696 } else {
697 eprintf ("Unknown div at 0x%08"PFMT64x"\n", op->addr);
698 }
699 break;
700 }
701 if (insn && (insn->id == MIPS_INS_SLTI || insn->id == MIPS_INS_SLTIU)) {
702 SET_SRC_DST_3_IMM (op);
703 }
704 }
705
706 static void set_opdir(RAnalOp *op) {
707 switch (op->type & R_ANAL_OP_TYPE_MASK) {
708 case R_ANAL_OP_TYPE_LOAD:
709 op->direction = R_ANAL_OP_DIR_READ;
710 break;
711 case R_ANAL_OP_TYPE_STORE:
712 op->direction = R_ANAL_OP_DIR_WRITE;
713 break;
714 case R_ANAL_OP_TYPE_LEA:
715 op->direction = R_ANAL_OP_DIR_REF;
716 break;
717 case R_ANAL_OP_TYPE_CALL:
718 case R_ANAL_OP_TYPE_JMP:
719 case R_ANAL_OP_TYPE_UJMP:
720 case R_ANAL_OP_TYPE_UCALL:
721 op->direction = R_ANAL_OP_DIR_EXEC;
722 break;
723 default:
724 break;
725 }
726 }
727
728 static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
729 int n, ret, opsize = -1;
730 static csh hndl = 0;
731 static int omode = -1;
732 static int obits = 32;
733 cs_insn* insn;
734 int mode = anal->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN;
735
736 if (anal->cpu && *anal->cpu) {
737 if (!strcmp (anal->cpu, "micro")) {
738 mode |= CS_MODE_MICRO;
739 } else if (!strcmp (anal->cpu, "r6")) {
740 mode |= CS_MODE_MIPS32R6;
741 } else if (!strcmp (anal->cpu, "v3")) {
742 mode |= CS_MODE_MIPS3;
743 } else if (!strcmp (anal->cpu, "v2")) {
744 #if CS_API_MAJOR > 3
745 mode |= CS_MODE_MIPS2;
746 #endif
747 }
748 }
749 mode |= (anal->bits==64)? CS_MODE_MIPS64: CS_MODE_MIPS32;
750 if (mode != omode || anal->bits != obits) {
751 cs_close (&hndl);
752 hndl = 0;
753 omode = mode;
754 obits = anal->bits;
755 }
756 // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64
757 op->addr = addr;
758 if (len < 4) {
759 return -1;
760 }
761 op->size = 4;
762 if (hndl == 0) {
763 ret = cs_open (CS_ARCH_MIPS, mode, &hndl);
764 if (ret != CS_ERR_OK) {
765 goto fin;
766 }
767 cs_option (hndl, CS_OPT_DETAIL, CS_OPT_ON);
768 }
769 n = cs_disasm (hndl, (ut8*)buf, len, addr, 1, &insn);
770 if (n < 1 || insn->size < 1) {
771 if (mask & R_ANAL_OP_MASK_DISASM) {
772 op->mnemonic = strdup ("invalid");
773 }
774 goto beach;
775 }
776 if (mask & R_ANAL_OP_MASK_DISASM) {
777 op->mnemonic = r_str_newf ("%s%s%s",
778 insn->mnemonic,
779 insn->op_str[0]?" ":"",
780 insn->op_str);
781 }
782 op->id = insn->id;
783 opsize = op->size = insn->size;
784 op->refptr = 0;
785 switch (insn->id) {
786 case MIPS_INS_INVALID:
787 op->type = R_ANAL_OP_TYPE_ILL;
788 break;
789 case MIPS_INS_LB:
790 case MIPS_INS_LBU:
791 case MIPS_INS_LBUX:
792 op->refptr = 1;
793 /* fallthrough */
794 case MIPS_INS_LW:
795 case MIPS_INS_LWC1:
796 case MIPS_INS_LWC2:
797 case MIPS_INS_LWL:
798 case MIPS_INS_LWR:
799 case MIPS_INS_LWXC1:
800 if (!op->refptr) {
801 op->refptr = 4;
802 }
803 /* fallthrough */
804 case MIPS_INS_LD:
805 case MIPS_INS_LDC1:
806 case MIPS_INS_LDC2:
807 case MIPS_INS_LDL:
808 case MIPS_INS_LDR:
809 case MIPS_INS_LDXC1:
810 op->type = R_ANAL_OP_TYPE_LOAD;
811 if (!op->refptr) {
812 op->refptr = 8;
813 }
814 switch (OPERAND(1).type) {
815 case MIPS_OP_MEM:
816 if (OPERAND(1).mem.base == MIPS_REG_GP) {
817 op->ptr = anal->gp + OPERAND(1).mem.disp;
818 if (REGID(0) == MIPS_REG_T9) {
819 t9_pre = op->ptr;
820 }
821 } else if (REGID(0) == MIPS_REG_T9) {
822 t9_pre = UT64_MAX;
823 }
824 break;
825 case MIPS_OP_IMM:
826 op->ptr = OPERAND(1).imm;
827 break;
828 case MIPS_OP_REG:
829 // wtf?
830 break;
831 default:
832 break;
833 }
834 // TODO: fill
835 break;
836 case MIPS_INS_SD:
837 case MIPS_INS_SW:
838 case MIPS_INS_SB:
839 case MIPS_INS_SH:
840 case MIPS_INS_SWC1:
841 case MIPS_INS_SWC2:
842 case MIPS_INS_SWL:
843 case MIPS_INS_SWR:
844 case MIPS_INS_SWXC1:
845 op->type = R_ANAL_OP_TYPE_STORE;
846 break;
847 case MIPS_INS_NOP:
848 op->type = R_ANAL_OP_TYPE_NOP;
849 break;
850 case MIPS_INS_SYSCALL:
851 op->type = R_ANAL_OP_TYPE_SWI;
852 break;
853 case MIPS_INS_BREAK:
854 op->type = R_ANAL_OP_TYPE_TRAP;
855 break;
856 case MIPS_INS_JALR:
857 op->type = R_ANAL_OP_TYPE_UCALL;
858 op->delay = 1;
859 if (REGID(0) == MIPS_REG_25) {
860 op->jump = t9_pre;
861 t9_pre = UT64_MAX;
862 op->type = R_ANAL_OP_TYPE_RCALL;
863 }
864 break;
865 case MIPS_INS_JAL:
866 case MIPS_INS_JALS:
867 case MIPS_INS_JALX:
868 case MIPS_INS_JRADDIUSP:
869 case MIPS_INS_BAL:
870 // (no blezal/bgtzal or blezall/bgtzall, only blezalc/bgtzalc)
871 case MIPS_INS_BLTZAL: // Branch on <0 and link
872 case MIPS_INS_BGEZAL: // Branch on >=0 and link
873 case MIPS_INS_BLTZALL: // "likely" versions
874 case MIPS_INS_BGEZALL:
875 case MIPS_INS_BLTZALC: // compact versions
876 case MIPS_INS_BLEZALC:
877 case MIPS_INS_BGEZALC:
878 case MIPS_INS_BGTZALC:
879 case MIPS_INS_JIALC:
880 case MIPS_INS_JIC:
881 op->type = R_ANAL_OP_TYPE_CALL;
882 op->jump = IMM(0);
883
884 switch (insn->id) {
885 case MIPS_INS_JIALC:
886 case MIPS_INS_JIC:
887 case MIPS_INS_BLTZALC:
888 case MIPS_INS_BLEZALC:
889 case MIPS_INS_BGEZALC:
890 case MIPS_INS_BGTZALC:
891 // compact versions (no delay)
892 op->delay = 0;
893 op->fail = addr+4;
894 break;
895 default:
896 op->delay = 1;
897 op->fail = addr+8;
898 break;
899 }
900 break;
901 case MIPS_INS_LI:
902 case MIPS_INS_LUI:
903 SET_VAL (op, 1);
904 op->type = R_ANAL_OP_TYPE_MOV;
905 break;
906 case MIPS_INS_MOVE:
907 op->type = R_ANAL_OP_TYPE_MOV;
908 break;
909 case MIPS_INS_ADD:
910 case MIPS_INS_ADDI:
911 case MIPS_INS_ADDU:
912 case MIPS_INS_ADDIU:
913 case MIPS_INS_DADD:
914 case MIPS_INS_DADDI:
915 case MIPS_INS_DADDIU:
916 SET_VAL (op, 2);
917 op->sign = (insn->id == MIPS_INS_ADDI || insn->id == MIPS_INS_ADD);
918 op->type = R_ANAL_OP_TYPE_ADD;
919 if (REGID(0) == MIPS_REG_T9) {
920 t9_pre += IMM(2);
921 }
922 if (REGID(0) == MIPS_REG_SP) {
923 op->stackop = R_ANAL_STACK_INC;
924 op->stackptr = -IMM(2);
925 }
926 break;
927 case MIPS_INS_SUB:
928 case MIPS_INS_SUBV:
929 case MIPS_INS_SUBVI:
930 case MIPS_INS_DSUBU:
931 case MIPS_INS_FSUB:
932 case MIPS_INS_FMSUB:
933 case MIPS_INS_SUBU:
934 case MIPS_INS_DSUB:
935 case MIPS_INS_SUBS_S:
936 case MIPS_INS_SUBS_U:
937 case MIPS_INS_SUBUH:
938 case MIPS_INS_SUBUH_R:
939 SET_VAL (op,2);
940 op->sign = insn->id == MIPS_INS_SUB;
941 op->type = R_ANAL_OP_TYPE_SUB;
942 break;
943 case MIPS_INS_MULV:
944 case MIPS_INS_MULT:
945 case MIPS_INS_MULSA:
946 case MIPS_INS_FMUL:
947 case MIPS_INS_MUL:
948 case MIPS_INS_DMULT:
949 case MIPS_INS_DMULTU:
950 op->type = R_ANAL_OP_TYPE_MUL;
951 break;
952 case MIPS_INS_XOR:
953 case MIPS_INS_XORI:
954 SET_VAL (op,2);
955 op->type = R_ANAL_OP_TYPE_XOR;
956 break;
957 case MIPS_INS_AND:
958 case MIPS_INS_ANDI:
959 SET_VAL (op,2);
960 op->type = R_ANAL_OP_TYPE_AND;
961 if (REGID(0) == MIPS_REG_SP) {
962 op->stackop = R_ANAL_STACK_ALIGN;
963 }
964 break;
965 case MIPS_INS_NOT:
966 op->type = R_ANAL_OP_TYPE_NOT;
967 break;
968 case MIPS_INS_OR:
969 case MIPS_INS_ORI:
970 SET_VAL (op,2);
971 op->type = R_ANAL_OP_TYPE_OR;
972 break;
973 case MIPS_INS_DIV:
974 case MIPS_INS_DIVU:
975 case MIPS_INS_DDIV:
976 case MIPS_INS_DDIVU:
977 case MIPS_INS_FDIV:
978 case MIPS_INS_DIV_S:
979 case MIPS_INS_DIV_U:
980 op->type = R_ANAL_OP_TYPE_DIV;
981 break;
982 case MIPS_INS_CMPGDU:
983 case MIPS_INS_CMPGU:
984 case MIPS_INS_CMPU:
985 case MIPS_INS_CMPI:
986 op->type = R_ANAL_OP_TYPE_CMP;
987 break;
988 case MIPS_INS_J:
989 case MIPS_INS_B:
990 case MIPS_INS_BZ:
991 case MIPS_INS_BEQ:
992 case MIPS_INS_BNZ:
993 case MIPS_INS_BNE:
994 case MIPS_INS_BNEL:
995 case MIPS_INS_BEQL:
996 case MIPS_INS_BEQZ:
997 case MIPS_INS_BNEG:
998 case MIPS_INS_BNEGI:
999 case MIPS_INS_BNEZ:
1000 case MIPS_INS_BTEQZ:
1001 case MIPS_INS_BTNEZ:
1002 case MIPS_INS_BLTZ:
1003 case MIPS_INS_BLTZL:
1004 case MIPS_INS_BLEZ:
1005 case MIPS_INS_BLEZL:
1006 case MIPS_INS_BGEZ:
1007 case MIPS_INS_BGEZL:
1008 case MIPS_INS_BGTZ:
1009 case MIPS_INS_BGTZL:
1010 case MIPS_INS_BLEZC:
1011 case MIPS_INS_BGEZC:
1012 case MIPS_INS_BLTZC:
1013 case MIPS_INS_BGTZC:
1014 if (insn->id == MIPS_INS_J || insn->id == MIPS_INS_B ) {
1015 op->type = R_ANAL_OP_TYPE_JMP;
1016 } else {
1017 op->type = R_ANAL_OP_TYPE_CJMP;
1018 }
1019
1020 if (OPERAND(0).type == MIPS_OP_IMM) {
1021 op->jump = IMM(0);
1022 } else if (OPERAND(1).type == MIPS_OP_IMM) {
1023 op->jump = IMM(1);
1024 } else if (OPERAND(2).type == MIPS_OP_IMM) {
1025 op->jump = IMM(2);
1026 }
1027
1028 switch (insn->id) {
1029 case MIPS_INS_BLEZC:
1030 case MIPS_INS_BGEZC:
1031 case MIPS_INS_BLTZC:
1032 case MIPS_INS_BGTZC:
1033 // compact versions (no delay)
1034 op->delay = 0;
1035 op->fail = addr+4;
1036 break;
1037 default:
1038 op->delay = 1;
1039 op->fail = addr+8;
1040 break;
1041 }
1042
1043 break;
1044 case MIPS_INS_JR:
1045 case MIPS_INS_JRC:
1046 op->type = R_ANAL_OP_TYPE_RJMP;
1047 op->delay = 1;
1048 // register is $ra, so jmp is a return
1049 if (insn->detail->mips.operands[0].reg == MIPS_REG_RA) {
1050 op->type = R_ANAL_OP_TYPE_RET;
1051 t9_pre = UT64_MAX;
1052 }
1053 if (REGID(0) == MIPS_REG_25) {
1054 op->jump = t9_pre;
1055 t9_pre = UT64_MAX;
1056 }
1057
1058 break;
1059 case MIPS_INS_SLT:
1060 case MIPS_INS_SLTI:
1061 op->sign = true;
1062 SET_VAL (op, 2);
1063 break;
1064 case MIPS_INS_SLTIU:
1065 SET_VAL (op, 2);
1066 break;
1067 case MIPS_INS_SHRAV:
1068 case MIPS_INS_SHRAV_R:
1069 case MIPS_INS_SHRA:
1070 case MIPS_INS_SHRA_R:
1071 case MIPS_INS_SRA:
1072 op->type = R_ANAL_OP_TYPE_SAR;
1073 SET_VAL (op,2);
1074 break;
1075 case MIPS_INS_SHRL:
1076 case MIPS_INS_SRLV:
1077 case MIPS_INS_SRL:
1078 op->type = R_ANAL_OP_TYPE_SHR;
1079 SET_VAL (op,2);
1080 break;
1081 case MIPS_INS_SLLV:
1082 case MIPS_INS_SLL:
1083 op->type = R_ANAL_OP_TYPE_SHL;
1084 SET_VAL (op,2);
1085 break;
1086 }
1087 beach:
1088 set_opdir (op);
1089 if (insn && mask & R_ANAL_OP_MASK_OPEX) {
1090 opex (&op->opex, hndl, insn);
1091 }
1092 if (mask & R_ANAL_OP_MASK_ESIL) {
1093 if (analop_esil (anal, op, addr, buf, len, &hndl, insn) != 0) {
1094 r_strbuf_fini (&op->esil);
1095 }
1096 }
1097 if (mask & R_ANAL_OP_MASK_VAL) {
1098 op_fillval (anal, op, &hndl, insn);
1099 }
1100 cs_free (insn, n);
1101 //cs_close (&handle);
1102 fin:
1103 return opsize;
1104 }
1105
1106 static char *get_reg_profile(RAnal *anal) {
1107 const char *p = NULL;
1108 switch (anal->bits) {
1109 default:
1110 case 32: p =
1111 "=PC pc\n"
1112 "=SP sp\n"
1113 "=BP fp\n"
1114 "=SN v0\n"
1115 "=A0 a0\n"
1116 "=A1 a1\n"
1117 "=A2 a2\n"
1118 "=A3 a3\n"
1119 "=R0 v0\n"
1120 "=R1 v1\n"
1121 "gpr zero .32 ? 0\n"
1122 "gpr at .32 4 0\n"
1123 "gpr v0 .32 8 0\n"
1124 "gpr v1 .32 12 0\n"
1125 "gpr a0 .32 16 0\n"
1126 "gpr a1 .32 20 0\n"
1127 "gpr a2 .32 24 0\n"
1128 "gpr a3 .32 28 0\n"
1129 "gpr t0 .32 32 0\n"
1130 "gpr t1 .32 36 0\n"
1131 "gpr t2 .32 40 0\n"
1132 "gpr t3 .32 44 0\n"
1133 "gpr t4 .32 48 0\n"
1134 "gpr t5 .32 52 0\n"
1135 "gpr t6 .32 56 0\n"
1136 "gpr t7 .32 60 0\n"
1137 "gpr s0 .32 64 0\n"
1138 "gpr s1 .32 68 0\n"
1139 "gpr s2 .32 72 0\n"
1140 "gpr s3 .32 76 0\n"
1141 "gpr s4 .32 80 0\n"
1142 "gpr s5 .32 84 0\n"
1143 "gpr s6 .32 88 0\n"
1144 "gpr s7 .32 92 0\n"
1145 "gpr t8 .32 96 0\n"
1146 "gpr t9 .32 100 0\n"
1147 "gpr k0 .32 104 0\n"
1148 "gpr k1 .32 108 0\n"
1149 "gpr gp .32 112 0\n"
1150 "gpr sp .32 116 0\n"
1151 "gpr fp .32 120 0\n"
1152 "gpr ra .32 124 0\n"
1153 "gpr pc .32 128 0\n"
1154 "gpr hi .32 132 0\n"
1155 "gpr lo .32 136 0\n"
1156 "gpr t .32 140 0\n";
1157 break;
1158 case 64: p =
1159 "=PC pc\n"
1160 "=SP sp\n"
1161 "=BP fp\n"
1162 "=A0 a0\n"
1163 "=A1 a1\n"
1164 "=A2 a2\n"
1165 "=A3 a3\n"
1166 "=SN v0\n"
1167 "=R0 v0\n"
1168 "=R1 v1\n"
1169 "gpr zero .64 ? 0\n"
1170 "gpr at .64 8 0\n"
1171 "gpr v0 .64 16 0\n"
1172 "gpr v1 .64 24 0\n"
1173 "gpr a0 .64 32 0\n"
1174 "gpr a1 .64 40 0\n"
1175 "gpr a2 .64 48 0\n"
1176 "gpr a3 .64 56 0\n"
1177 "gpr t0 .64 64 0\n"
1178 "gpr t1 .64 72 0\n"
1179 "gpr t2 .64 80 0\n"
1180 "gpr t3 .64 88 0\n"
1181 "gpr t4 .64 96 0\n"
1182 "gpr t5 .64 104 0\n"
1183 "gpr t6 .64 112 0\n"
1184 "gpr t7 .64 120 0\n"
1185 "gpr s0 .64 128 0\n"
1186 "gpr s1 .64 136 0\n"
1187 "gpr s2 .64 144 0\n"
1188 "gpr s3 .64 152 0\n"
1189 "gpr s4 .64 160 0\n"
1190 "gpr s5 .64 168 0\n"
1191 "gpr s6 .64 176 0\n"
1192 "gpr s7 .64 184 0\n"
1193 "gpr t8 .64 192 0\n"
1194 "gpr t9 .64 200 0\n"
1195 "gpr k0 .64 208 0\n"
1196 "gpr k1 .64 216 0\n"
1197 "gpr gp .64 224 0\n"
1198 "gpr sp .64 232 0\n"
1199 "gpr fp .64 240 0\n"
1200 "gpr ra .64 248 0\n"
1201 "gpr pc .64 256 0\n"
1202 "gpr hi .64 264 0\n"
1203 "gpr lo .64 272 0\n"
1204 "gpr t .64 280 0\n";
1205 break;
1206 }
1207 return p? strdup (p): NULL;
1208 }
1209
1210 static int archinfo(RAnal *anal, int q) {
1211 return 4;
1212 }
1213
1214 static RList *anal_preludes(RAnal *anal) {
1215 #define KW(d,ds,m,ms) r_list_append (l, r_search_keyword_new((const ut8*)d,ds,(const ut8*)m, ms, NULL))
1216 RList *l = r_list_newf ((RListFree)r_search_keyword_free);
1217 KW ("\x27\xbd\x00", 3, NULL, 0);
1218 return l;
1219 }
1220
1221 RAnalPlugin r_anal_plugin_mips_cs = {
1222 .name = "mips",
1223 .desc = "Capstone MIPS analyzer",
1224 .license = "BSD",
1225 .esil = true,
1226 .arch = "mips",
1227 .get_reg_profile = get_reg_profile,
1228 .archinfo = archinfo,
1229 .preludes = anal_preludes,
1230 .bits = 16|32|64,
1231 .op = &analop,
1232 };
1233
1234 #ifndef R2_PLUGIN_INCORE
1235 R_API RLibStruct radare_plugin = {
1236 .type = R_LIB_TYPE_ANAL,
1237 .data = &r_anal_plugin_mips_cs,
1238 .version = R2_VERSION
1239 };
1240 #endif
1241