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 = &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 = &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