1 /* radare2 - LGPL - Copyright 2013-2019 - pancake */
2 
3 #include <r_anal.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6 #include <x86.h>
7 
8 #if 0
9 CYCLES:
10 ======
11 register access = 1
12 memory access = 2
13 jump = 3
14 call = 4
15 #endif
16 
17 #define CYCLE_REG 0
18 #define CYCLE_MEM 1
19 #define CYCLE_JMP 2
20 
21 // TODO: when capstone-4 is released, add proper check here
22 
23 #if CS_NEXT_VERSION>0
24 #define HAVE_CSGRP_PRIVILEGE 1
25 #else
26 #define HAVE_CSGRP_PRIVILEGE 0
27 #endif
28 
29 #define USE_ITER_API 0
30 
31 #if CS_API_MAJOR < 2
32 #error Old Capstone not supported
33 #endif
34 
35 #define esilprintf(op, fmt, ...) r_strbuf_setf (&op->esil, fmt, ##__VA_ARGS__)
36 #define opexprintf(op, fmt, ...) r_strbuf_setf (&op->opex, fmt, ##__VA_ARGS__)
37 #define INSOP(n) insn->detail->x86.operands[n]
38 #define INSOPS insn->detail->x86.op_count
39 #define ISIMM(x) insn->detail->x86.operands[x].type == X86_OP_IMM
40 #define ISMEM(x) insn->detail->x86.operands[x].type == X86_OP_MEM
41 
42 #define BUF_SZ      64
43 
44 #define AR_DIM       4
45 
46 #define SRC_AR       0
47 #define DST_AR       1
48 #define DST_R_AR     1
49 #define DST_W_AR     2
50 #define SRC2_AR      2
51 #define DST2_AR      2
52 #define DSTADD_AR    3
53 #define ARG0_AR      0
54 #define ARG1_AR      1
55 #define ARG2_AR      2
56 
57 struct Getarg {
58 	csh handle;
59 	cs_insn *insn;
60 	int bits;
61 };
62 
63 static csh handle = 0;
64 
hidden_op(cs_insn * insn,cs_x86 * x,int mode)65 static void hidden_op(cs_insn *insn, cs_x86 *x, int mode) {
66 	unsigned int id = insn->id;
67 	int regsz = 4;
68 	switch (mode) {
69 	case CS_MODE_64:
70 		regsz = 8;
71 		break;
72 	case CS_MODE_16:
73 		regsz = 2;
74 		break;
75 	default:
76 		regsz = 4; //32 bit
77 		break;
78 	}
79 
80 	switch (id) {
81 	case X86_INS_PUSHF:
82 	case X86_INS_POPF:
83 	case X86_INS_PUSHFD:
84 	case X86_INS_POPFD:
85 	case X86_INS_PUSHFQ:
86 	case X86_INS_POPFQ:
87 		x->op_count = 1;
88 		cs_x86_op *op = &x->operands[0];
89 		op->type = X86_OP_REG;
90 		op->reg = X86_REG_EFLAGS;
91 		op->size = regsz;
92 #if CS_API_MAJOR >=4
93 		if (id == X86_INS_PUSHF || id == X86_INS_PUSHFD || id == X86_INS_PUSHFQ) {
94 			op->access = 1;
95 		} else {
96 			op->access = 2;
97 		}
98 #endif
99 		break;
100 	case X86_INS_PUSHAW:
101 	case X86_INS_PUSHAL:
102 	case X86_INS_POPAW:
103 	case X86_INS_POPAL:
104 	default:
105 		break;
106 	}
107 }
108 
opex(RStrBuf * buf,cs_insn * insn,int mode)109 static void opex(RStrBuf *buf, cs_insn *insn, int mode) {
110 	int i;
111 	PJ *pj = pj_new ();
112 	if (!pj) {
113 		return;
114 	}
115 	pj_o (pj);
116 	cs_x86 *x = &insn->detail->x86;
117 	if (x->op_count == 0) {
118 		hidden_op (insn, x, mode);
119 	}
120 	pj_ka (pj, "operands");
121 	for (i = 0; i < x->op_count; i++) {
122 		cs_x86_op *op = x->operands + i;
123 		pj_o (pj);
124 		pj_ki (pj, "size", op->size);
125 #if CS_API_MAJOR >= 4
126 		pj_ki (pj, "rw", op->access); // read, write, read|write
127 #endif
128 		switch (op->type) {
129 		case X86_OP_REG:
130 			pj_ks (pj, "type", "reg");
131 			pj_ks (pj, "value", cs_reg_name (handle, op->reg));
132 			break;
133 		case X86_OP_IMM:
134 			pj_ks (pj, "type", "imm");
135 			pj_kN (pj, "value", op->imm);
136 			break;
137 		case X86_OP_MEM:
138 			pj_ks (pj, "type", "mem");
139 			if (op->mem.segment != X86_REG_INVALID) {
140 				pj_ks (pj, "segment", cs_reg_name (handle, op->mem.segment));
141 			}
142 			if (op->mem.base != X86_REG_INVALID) {
143 				pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
144 			}
145 			if (op->mem.index != X86_REG_INVALID) {
146 				pj_ks (pj, "index", cs_reg_name (handle, op->mem.index));
147 			}
148 			pj_ki (pj, "scale", op->mem.scale);
149 			pj_kN (pj, "disp", op->mem.disp);
150 			break;
151 		default:
152 			pj_ks (pj, "type", "invalid");
153 			break;
154 		}
155 		pj_end (pj); /* o operand */
156 	}
157 	pj_end (pj); /* a operands */
158 	if (x->rex) {
159 		pj_kb (pj, "rex", true);
160 	}
161 	if (x->modrm) {
162 		pj_kb (pj, "modrm", true);
163 	}
164 	if (x->sib) {
165 		pj_ki (pj, "sib", x->sib);
166 	}
167 	if (x->disp) {
168 		pj_kN (pj, "disp", x->disp);
169 	}
170 	if (x->sib_index != X86_REG_INVALID) {
171 		pj_ki (pj, "sib_scale", x->sib_scale);
172 		pj_ks (pj, "sib_index", cs_reg_name (handle, x->sib_index));
173 	}
174 	if (x->sib_base != X86_REG_INVALID) {
175 		pj_ks (pj, "sib_base", cs_reg_name (handle, x->sib_base));
176 	}
177 	pj_end (pj);
178 
179 	r_strbuf_init (buf);
180 	r_strbuf_append (buf, pj_string (pj));
181 	pj_free (pj);
182 }
183 
is_xmm_reg(cs_x86_op op)184 static bool is_xmm_reg(cs_x86_op op) {
185 	switch (op.reg) {
186 	case X86_REG_XMM0:
187 	case X86_REG_XMM1:
188 	case X86_REG_XMM2:
189 	case X86_REG_XMM3:
190 	case X86_REG_XMM4:
191 	case X86_REG_XMM5:
192 	case X86_REG_XMM6:
193 	case X86_REG_XMM7:
194 	case X86_REG_XMM8:
195 	case X86_REG_XMM9:
196 	case X86_REG_XMM10:
197 	case X86_REG_XMM11:
198 	case X86_REG_XMM12:
199 	case X86_REG_XMM13:
200 	case X86_REG_XMM14:
201 	case X86_REG_XMM15:
202 	case X86_REG_XMM16:
203 	case X86_REG_XMM17:
204 	case X86_REG_XMM18:
205 	case X86_REG_XMM19:
206 	case X86_REG_XMM20:
207 	case X86_REG_XMM21:
208 	case X86_REG_XMM22:
209 	case X86_REG_XMM23:
210 	case X86_REG_XMM24:
211 	case X86_REG_XMM25:
212 	case X86_REG_XMM26:
213 	case X86_REG_XMM27:
214 	case X86_REG_XMM28:
215 	case X86_REG_XMM29:
216 	case X86_REG_XMM30:
217 	case X86_REG_XMM31: return true;
218 	default: return false;
219 	}
220 }
221 
222 /**
223  * Translates operand N to esil
224  *
225  * @param  handle  csh
226  * @param  insn    cs_insn
227  * @param  n       Operand index
228  * @param  set     if 1 it adds set (=) to the operand
229  * @param  setoper Extra operation for the set (^, -, +, etc...)
230  * @param  sel     Selector for output buffer in staic array
231  * @return         Pointer to esil operand in static array
232  */
getarg(struct Getarg * gop,int n,int set,char * setop,int sel,ut32 * bitsize)233 static char *getarg(struct Getarg* gop, int n, int set, char *setop, int sel, ut32 *bitsize) {
234 	static char buf[AR_DIM][BUF_SZ];
235 	char *out = buf[sel];
236 	const char *setarg = r_str_get (setop);
237 	cs_insn *insn = gop->insn;
238 	csh handle = gop->handle;
239 	cs_x86_op op;
240 
241 	if (!insn->detail) {
242 		return NULL;
243 	}
244 	if (n < 0 || n >= INSOPS) {
245 		return NULL;
246 	}
247 	out[0] = 0;
248 	op = INSOP (n);
249 	if (bitsize) {
250 		*bitsize = op.size * 8;
251 	}
252 	switch (op.type) {
253 #if CS_API_MAJOR == 3
254 	case X86_OP_FP:
255 		return "invalid";
256 #endif
257 	case X86_OP_INVALID:
258 		return "invalid";
259 	case X86_OP_REG:
260 		if (set == 1) {
261 			snprintf (out, BUF_SZ, "%s,%s=",
262 				cs_reg_name (handle, op.reg), setarg);
263 			return out;
264 		}
265 		return (char *)cs_reg_name (handle, op.reg);
266 	case X86_OP_IMM:
267 		if (set == 1) {
268 			snprintf (out, BUF_SZ, "%"PFMT64u",%s=[%d]",
269 				(ut64)op.imm, setarg, op.size);
270 			return out;
271 		}
272 		snprintf (out, BUF_SZ, "%"PFMT64u, (ut64)op.imm);
273 		return out;
274 	case X86_OP_MEM:
275 		{
276 		// address = (base + (index * scale) + offset)
277 		char buf_[BUF_SZ] = {0};
278 		int component_count = 0;
279 		const char *base = cs_reg_name (handle, op.mem.base);
280 		const char *index = cs_reg_name (handle, op.mem.index);
281 		int scale = op.mem.scale;
282 		st64 disp = op.mem.disp;
283 
284 		if (disp != 0) {
285 			snprintf (out, BUF_SZ, "0x%"PFMT64x",", (disp < 0) ? -disp : disp);
286 			component_count++;
287 		}
288 
289 		if (index) {
290 			if (scale > 1) {
291 				snprintf (buf_, BUF_SZ, "%s%s,%d,*,", out, index, scale);
292 			} else {
293 				snprintf (buf_, BUF_SZ, "%s%s,", out, index);
294 			}
295 			strncpy (out, buf_, BUF_SZ);
296 			component_count++;
297 		}
298 
299 		if (base) {
300 			snprintf (buf_, BUF_SZ, "%s%s,", out, base);
301 			strncpy (out, buf_, BUF_SZ);
302 			component_count++;
303 		}
304 
305 		if (component_count > 1) {
306 			if (component_count > 2) {
307 				snprintf (buf_, BUF_SZ, "%s+,", out);
308 				strncpy (out, buf_, BUF_SZ);
309 			}
310 			if (disp < 0) {
311 				snprintf (buf_, BUF_SZ, "%s-", out);
312 			} else {
313 				snprintf (buf_, BUF_SZ, "%s+", out);
314 			}
315 			strncpy (out, buf_, BUF_SZ);
316 		} else {
317 			// Remove the trailing ',' from esil statement.
318 			if (*out) {
319 				int out_len = strlen (out);
320 				out[out_len> 0? out_len - 1: 0] = 0;
321 			}
322 		}
323 
324 		// set = 2 is reserved for lea, where the operand is a memory address,
325 		// but the corresponding memory is not loaded.
326 		if (set == 1) {
327 			size_t len = strlen (setarg);
328 			if (len > 0 && setarg[len - 1] == ',') {
329 				snprintf (buf_, BUF_SZ, "%s,%s%s=[%d]", out, setarg,
330 					gop->bits == 32 ? "0xffffffff,&," : "", op.size==10?8:op.size);
331 			} else {
332 				snprintf (buf_, BUF_SZ, "%s,%s=[%d]", out, setarg, op.size==10?8:op.size);
333 			}
334 			strncpy (out, buf_, BUF_SZ);
335 		} else if (set == 0) {
336 			if (!*out) {
337 				strcpy (out, "0");
338 			}
339 			snprintf (buf_, BUF_SZ, "%s,[%d]", out, op.size==10? 8: op.size);
340 			strncpy (out, buf_, BUF_SZ);
341 		}
342 		out[BUF_SZ - 1] = 0;
343 		}
344 		return out;
345 	}
346 	return NULL;
347 }
348 
cond_x862r2(int id)349 static int cond_x862r2(int id) {
350 	switch (id) {
351 	case X86_INS_JE:
352 		return R_ANAL_COND_EQ;
353 	case X86_INS_JNE:
354 		return R_ANAL_COND_NE;
355 	case X86_INS_JB:
356 	case X86_INS_JL:
357 		return R_ANAL_COND_LT;
358 	case X86_INS_JBE:
359 	case X86_INS_JLE:
360 		return R_ANAL_COND_LE;
361 	case X86_INS_JG:
362 	case X86_INS_JA:
363 		return R_ANAL_COND_GT;
364 	case X86_INS_JAE:
365 		return R_ANAL_COND_GE;
366 	case X86_INS_JS:
367 	case X86_INS_JNS:
368 	case X86_INS_JO:
369 	case X86_INS_JNO:
370 	case X86_INS_JGE:
371 	case X86_INS_JP:
372 	case X86_INS_JNP:
373 	case X86_INS_JCXZ:
374 	case X86_INS_JECXZ:
375 		break;
376 	}
377 	return 0;
378 }
379 
380 /* reg indices are based on Intel doc for 32-bit ModR/M byte */
reg32_to_name(ut8 reg)381 static const char *reg32_to_name(ut8 reg) {
382 	const char * const names[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
383 	return reg < R_ARRAY_SIZE (names) ? names[reg] : "unk";
384 }
385 
anop_esil(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)386 static void anop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
387 	int rs = a->bits/8;
388 	const char *pc = (a->bits==16)?"ip":
389 		(a->bits==32)?"eip":"rip";
390 	const char *sp = (a->bits==16)?"sp":
391 		(a->bits==32)?"esp":"rsp";
392 	const char *bp = (a->bits==16)?"bp":
393 		(a->bits==32)?"ebp":"rbp";
394 	const char *si = (a->bits==16)?"si":
395 		(a->bits==32)?"esi":"rsi";
396 	struct Getarg gop = {
397 		.handle = *handle,
398 		.insn = insn,
399 		.bits = a->bits
400 	};
401 	char *src;
402 	char *src2;
403 	char *dst;
404 	char *dst2;
405 	char *dst_r;
406 	char *dst_w;
407 	char *dstAdd;
408 	char *arg0;
409 	char *arg1;
410 	char *arg2;
411 
412 	// counter for rep prefix
413 	const char *counter = (a->bits==16)?"cx":
414 		(a->bits==32)?"ecx":"rcx";
415 
416 	bool repe = false;
417 
418 	switch (insn->id) {
419 	case X86_INS_FNOP:
420 	case X86_INS_NOP:
421 	case X86_INS_PAUSE:
422 		esilprintf (op, ",");
423 		break;
424 	case X86_INS_HLT:
425 		break;
426 	case X86_INS_FBLD:
427 	case X86_INS_FBSTP:
428 	case X86_INS_FCOMPP:
429 	case X86_INS_FDECSTP:
430 	case X86_INS_FEMMS:
431 	case X86_INS_FFREE:
432 	case X86_INS_FICOM:
433 	case X86_INS_FICOMP:
434 	case X86_INS_FINCSTP:
435 	case X86_INS_FNCLEX:
436 	case X86_INS_FNINIT:
437 	case X86_INS_FNSTCW:
438 	case X86_INS_FNSTSW:
439 	case X86_INS_FPATAN:
440 	case X86_INS_FPREM:
441 	case X86_INS_FPREM1:
442 	case X86_INS_FPTAN:
443 #if CS_API_MAJOR >=4
444 	case X86_INS_FFREEP:
445 #endif
446 	case X86_INS_FRNDINT:
447 	case X86_INS_FRSTOR:
448 	case X86_INS_FNSAVE:
449 	case X86_INS_FSCALE:
450 	case X86_INS_FSETPM:
451 	case X86_INS_FSINCOS:
452 	case X86_INS_FNSTENV:
453 	case X86_INS_FXAM:
454 	case X86_INS_FXSAVE:
455 	case X86_INS_FXSAVE64:
456 	case X86_INS_FXTRACT:
457 	case X86_INS_FYL2X:
458 	case X86_INS_FYL2XP1:
459 	case X86_INS_FISTTP:
460 	case X86_INS_FSQRT:
461 	case X86_INS_FXCH:
462 		break;
463 	case X86_INS_FTST:
464 	case X86_INS_FUCOMI:
465 	case X86_INS_FUCOMPP:
466 	case X86_INS_FUCOMP:
467 	case X86_INS_FUCOM:
468 		break;
469 	case X86_INS_FABS:
470 		break;
471 	case X86_INS_FLDCW:
472 	case X86_INS_FLDENV:
473 	case X86_INS_FLDL2E:
474 	case X86_INS_FLDL2T:
475 	case X86_INS_FLDLG2:
476 	case X86_INS_FLDLN2:
477 	case X86_INS_FLDPI:
478 	case X86_INS_FLDZ:
479 	case X86_INS_FLD1:
480 	case X86_INS_FLD:
481 		break;
482 	case X86_INS_FIST:
483 	case X86_INS_FISTP:
484 	case X86_INS_FST:
485 	case X86_INS_FSTP:
486 	case X86_INS_FSTPNCE:
487 	case X86_INS_FXRSTOR:
488 	case X86_INS_FXRSTOR64:
489 		break;
490 	case X86_INS_FIDIV:
491 	case X86_INS_FIDIVR:
492 	case X86_INS_FDIV:
493 	case X86_INS_FDIVP:
494 	case X86_INS_FDIVR:
495 	case X86_INS_FDIVRP:
496 		break;
497 	case X86_INS_FSUBR:
498 	case X86_INS_FISUBR:
499 	case X86_INS_FSUBRP:
500 	case X86_INS_FSUB:
501 	case X86_INS_FISUB:
502 	case X86_INS_FSUBP:
503 		break;
504 	case X86_INS_FMUL:
505 	case X86_INS_FIMUL:
506 	case X86_INS_FMULP:
507 		break;
508 	case X86_INS_CLI:
509 		esilprintf (op, "0,if,:=");
510 		break;
511 	case X86_INS_STI:
512 		esilprintf (op, "1,if,:=");
513 		break;
514 	case X86_INS_CLC:
515 		esilprintf (op, "0,cf,:=");
516 		break;
517 	case X86_INS_CMC:
518 		esilprintf (op, "cf,!,cf,=");
519 		break;
520 	case X86_INS_STC:
521 		esilprintf (op, "1,cf,:=");
522 		break;
523 	case X86_INS_CLAC:
524 	case X86_INS_CLGI:
525 	case X86_INS_CLTS:
526 #if CS_API_MAJOR >= 4
527 	case X86_INS_CLWB:
528 #endif
529 	case X86_INS_STAC:
530 	case X86_INS_STGI:
531 		break;
532 	// cmov
533 	case X86_INS_SETNE:
534 	case X86_INS_SETNO:
535 	case X86_INS_SETNP:
536 	case X86_INS_SETNS:
537 	case X86_INS_SETO:
538 	case X86_INS_SETP:
539 	case X86_INS_SETS:
540 	case X86_INS_SETL:
541 	case X86_INS_SETLE:
542 	case X86_INS_SETB:
543 	case X86_INS_SETG:
544 	case X86_INS_SETAE:
545 	case X86_INS_SETA:
546 	case X86_INS_SETBE:
547 	case X86_INS_SETE:
548 	case X86_INS_SETGE:
549 		{
550 			dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
551 			switch (insn->id) {
552 			case X86_INS_SETE:  esilprintf (op, "zf,%s", dst); break;
553 			case X86_INS_SETNE: esilprintf (op, "zf,!,%s", dst); break;
554 			case X86_INS_SETO:  esilprintf (op, "of,%s", dst); break;
555 			case X86_INS_SETNO: esilprintf (op, "of,!,%s", dst); break;
556 			case X86_INS_SETP:  esilprintf (op, "pf,%s", dst); break;
557 			case X86_INS_SETNP: esilprintf (op, "pf,!,%s", dst); break;
558 			case X86_INS_SETS:  esilprintf (op, "sf,%s", dst); break;
559 			case X86_INS_SETNS: esilprintf (op, "sf,!,%s", dst); break;
560 			case X86_INS_SETB:  esilprintf (op, "cf,%s", dst); break;
561 			case X86_INS_SETAE: esilprintf (op, "cf,!,%s", dst); break;
562 			case X86_INS_SETL:  esilprintf (op, "sf,of,^,%s", dst); break;
563 			case X86_INS_SETLE: esilprintf (op, "zf,sf,of,^,|,%s", dst); break;
564 			case X86_INS_SETG:  esilprintf (op, "zf,!,sf,of,^,!,&,%s", dst); break;
565 			case X86_INS_SETGE: esilprintf (op, "sf,of,^,!,%s", dst); break;
566 			case X86_INS_SETA:  esilprintf (op, "cf,zf,|,!,%s", dst); break;
567 			case X86_INS_SETBE: esilprintf (op, "cf,zf,|,%s", dst); break;
568 			}
569 		}
570 		break;
571 	// cmov
572 	case X86_INS_FCMOVBE:
573 	case X86_INS_FCMOVB:
574 	case X86_INS_FCMOVNBE:
575 	case X86_INS_FCMOVNB:
576 	case X86_INS_FCMOVE:
577 	case X86_INS_FCMOVNE:
578 	case X86_INS_FCMOVNU:
579 	case X86_INS_FCMOVU:
580 		break;
581 	case X86_INS_CMOVA:
582 	case X86_INS_CMOVAE:
583 	case X86_INS_CMOVB:
584 	case X86_INS_CMOVBE:
585 	case X86_INS_CMOVE:
586 	case X86_INS_CMOVG:
587 	case X86_INS_CMOVGE:
588 	case X86_INS_CMOVL:
589 	case X86_INS_CMOVLE:
590 	case X86_INS_CMOVNE:
591 	case X86_INS_CMOVNO:
592 	case X86_INS_CMOVNP:
593 	case X86_INS_CMOVNS:
594 	case X86_INS_CMOVO:
595 	case X86_INS_CMOVP:
596 	case X86_INS_CMOVS: {
597 		const char *conditional = NULL;
598 		src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
599 		dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
600 		switch (insn->id) {
601 		case X86_INS_CMOVA:
602 			// mov if CF = 0 *AND* ZF = 0
603 			conditional = "cf,zf,|,!";
604 			break;
605 		case X86_INS_CMOVAE:
606 			// mov if CF = 0
607 			conditional = "cf,!";
608 			break;
609 		case X86_INS_CMOVB:
610 			// mov if CF = 1
611 			conditional = "cf";
612 			break;
613 		case X86_INS_CMOVBE:
614 			// mov if CF = 1 *OR* ZF = 1
615 			conditional = "cf,zf,|";
616 			break;
617 		case X86_INS_CMOVE:
618 			// mov if ZF = 1
619 			conditional = "zf";
620 			break;
621 		case X86_INS_CMOVG:
622 			// mov if ZF = 0 *AND* SF = OF
623 			conditional = "zf,!,sf,of,^,!,&";
624 			break;
625 		case X86_INS_CMOVGE:
626 			// mov if SF = OF
627 			conditional = "sf,of,^,!";
628 			break;
629 		case X86_INS_CMOVL:
630 			// mov if SF != OF
631 			conditional = "sf,of,^";
632 			break;
633 		case X86_INS_CMOVLE:
634 			// mov if ZF = 1 *OR* SF != OF
635 			conditional = "zf,sf,of,^,|";
636 			break;
637 		case X86_INS_CMOVNE:
638 			// mov if ZF = 0
639 			conditional = "zf,!";
640 			break;
641 		case X86_INS_CMOVNO:
642 			// mov if OF = 0
643 			conditional = "of,!";
644 			break;
645 		case X86_INS_CMOVNP:
646 			// mov if PF = 0
647 			conditional = "pf,!";
648 			break;
649 		case X86_INS_CMOVNS:
650 			// mov if SF = 0
651 			conditional = "sf,!";
652 			break;
653 		case X86_INS_CMOVO:
654 			// mov if OF = 1
655 			conditional = "of";
656 			break;
657 		case X86_INS_CMOVP:
658 			// mov if PF = 1
659 			conditional = "pf";
660 			break;
661 		case X86_INS_CMOVS:
662 			// mov if SF = 1
663 			conditional = "sf";
664 			break;
665 		}
666 		if (src && dst && conditional) {
667 			esilprintf (op, "%s,?{,%s,%s,}", conditional, src, dst);
668 		}
669 	}
670 		break;
671 	case X86_INS_STOSB:
672 		if (a->bits<32) {
673 			r_strbuf_appendf (&op->esil, "al,di,=[1],df,?{,1,di,-=,},df,!,?{,1,di,+=,}");
674 		} else {
675 			r_strbuf_appendf (&op->esil, "al,edi,=[1],df,?{,1,edi,-=,},df,!,?{,1,edi,+=,}");
676 		}
677 		break;
678 	case X86_INS_STOSW:
679 		if (a->bits<32) {
680 			r_strbuf_appendf (&op->esil, "ax,di,=[2],df,?{,2,di,-=,},df,!,?{,2,di,+=,}");
681 		} else {
682 			r_strbuf_appendf (&op->esil, "ax,edi,=[2],df,?{,2,edi,-=,},df,!,?{,2,edi,+=,}");
683 		}
684 		break;
685 	case X86_INS_STOSD:
686 			r_strbuf_appendf (&op->esil, "eax,edi,=[4],df,?{,4,edi,-=,},df,!,?{,4,edi,+=,}");
687 		break;
688 	case X86_INS_STOSQ:
689 			r_strbuf_appendf (&op->esil, "rax,rdi,=[8],df,?{,8,edi,-=,},df,!,?{,8,edi,+=,}");
690 		break;
691 	case X86_INS_LODSB:
692 			r_strbuf_appendf (&op->esil, "%s,[1],al,=,df,?{,1,%s,-=,},df,!,?{,1,%s,+=,}", si, si, si);
693 		break;
694 	case X86_INS_LODSW:
695 			r_strbuf_appendf (&op->esil, "%s,[2],ax,=,df,?{,2,%s,-=,},df,!,?{,2,%s,+=,}", si, si, si);
696 		break;
697 	case X86_INS_LODSD:
698 		r_strbuf_appendf (&op->esil, "esi,[4],eax,=,df,?{,4,esi,-=,},df,!,?{,4,esi,+=,}");
699 		break;
700 	case X86_INS_LODSQ:
701 		r_strbuf_appendf (&op->esil, "rsi,[8],rax,=,df,?{,8,rsi,-=,},df,!,?{,8,rsi,+=,}");
702 		break;
703 	case X86_INS_PEXTRB:
704 		r_strbuf_appendf (&op->esil, "TODO");
705 		break;
706 	// string mov
707 	// PS: MOVSD can correspond to one of the two instruction (yes, intel x86
708 	// has the same pneumonic for two different opcodes!). We can decide which
709 	// of the two it is based on the operands.
710 	// For more information, see:
711 	// http://x86.renejeschke.de/html/file_module_x86_id_203.html
712 	//               (vs)
713 	// http://x86.renejeschke.de/html/file_module_x86_id_204.html
714 	case X86_INS_MOVSD:
715 		// Handle "Move Scalar Double-Precision Floating-Point Value"
716 		if (is_xmm_reg (INSOP(0)) || is_xmm_reg (INSOP(1))) {
717 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
718 			dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
719 			if (src && dst) {
720 				esilprintf (op, "%s,%s", src, dst);
721 			}
722 			break;
723 		}
724 	case X86_INS_MOVSB:
725 	case X86_INS_MOVSQ:
726 	case X86_INS_MOVSW:
727 		if (op->prefix & R_ANAL_OP_PREFIX_REP) {
728 			int width = INSOP(0).size;
729 			src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
730 			dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
731 			r_strbuf_appendf (&op->esil,
732 					"%s,[%d],%s,=[%d],"\
733 					"df,?{,%d,%s,-=,%d,%s,-=,},"\
734 					"df,!,?{,%d,%s,+=,%d,%s,+=,}",
735 					src, width, dst, width,
736 					width, src, width, dst,
737 					width, src, width, dst);
738 		} else {
739 			int width = INSOP(0).size;
740 			src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
741 			dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
742 			esilprintf (op, "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\
743 					"df,!,?{,%d,%s,+=,%d,%s,+=,}",
744 					src, width, dst, width, width, src, width,
745 					dst, width, src, width, dst);
746 		}
747 		break;
748 	// mov
749 	case X86_INS_MOVSS:
750 	case X86_INS_MOV:
751 	case X86_INS_MOVAPS:
752 	case X86_INS_MOVAPD:
753 	case X86_INS_MOVZX:
754 	case X86_INS_MOVUPS:
755 	case X86_INS_MOVABS:
756 	case X86_INS_MOVHPD:
757 	case X86_INS_MOVHPS:
758 	case X86_INS_MOVLPD:
759 	case X86_INS_MOVLPS:
760 	case X86_INS_MOVBE:
761 	case X86_INS_MOVSX:
762 	case X86_INS_MOVSXD:
763 	case X86_INS_MOVD:
764 	case X86_INS_MOVQ:
765 	case X86_INS_MOVDQU:
766 	case X86_INS_MOVDQA:
767 	case X86_INS_MOVDQ2Q:
768 		{
769 		switch (INSOP(0).type) {
770 		case X86_OP_MEM:
771 			if (op->prefix & R_ANAL_OP_PREFIX_REP) {
772 				int width = INSOP(0).size;
773 				src = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
774 				dst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
775 				const char *counter = (a->bits==16)?"cx":
776 					(a->bits==32)?"ecx":"rcx";
777 				esilprintf (op, "%s,!,?{,BREAK,},%s,NUM,%s,NUM,"\
778 						"%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\
779 						"df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \
780 						"?{,8,GOTO,}",
781 						counter, src, dst, src, width, dst,
782 						width, width, src, width, dst, width, src,
783 						width, dst, counter, counter);
784 			} else {
785 				src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
786 				dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
787 				esilprintf (op, "%s,%s", src, dst);
788 			}
789 			break;
790 		case X86_OP_REG:
791 		default:
792 			if (INSOP(0).type == X86_OP_MEM) {
793 				op->direction = 1; // read
794 			}
795 			if (INSOP(1).type == X86_OP_MEM) {
796 				// MOV REG, [PTR + IREG*SCALE]
797 				op->ireg = cs_reg_name (*handle, INSOP (1).mem.index);
798 				op->disp = INSOP(1).mem.disp;
799 				op->scale = INSOP(1).mem.scale;
800 			}
801 			{
802 				int width = INSOP(1).size;
803 
804 				src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
805 				// dst is name of register from instruction.
806 				dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
807 				const char *dst64 = r_reg_32_to_64 (a->reg, dst);
808 				if (a->bits == 64 && dst64) {
809 					// Here it is still correct, because 'e** = X'
810 					// turns into 'r** = X' (first one will keep higher bytes,
811 					// second one will overwrite them with zeros).
812 					if (insn->id == X86_INS_MOVSX || insn->id == X86_INS_MOVSXD) {
813 						esilprintf (op, "%d,%s,~,%s,=", width*8, src, dst64);
814 					} else {
815 						esilprintf (op, "%s,%s,=", src, dst64);
816 					}
817 
818 				} else {
819 					if (insn->id == X86_INS_MOVSX || insn->id == X86_INS_MOVSXD) {
820 						esilprintf (op, "%d,%s,~,%s,=", width*8, src, dst);
821 					} else {
822 						esilprintf (op, "%s,%s,=", src, dst);
823 					}
824 				}
825 			}
826 			break;
827 		}
828 		}
829 		break;
830 	case X86_INS_ROL:
831 	case X86_INS_RCL:
832 		// TODO: RCL Still does not work as intended
833 		//  - Set flags
834 		{
835 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
836 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
837 			esilprintf (op, "%s,%s,<<<,%s,=", src, dst, dst);
838 		}
839 		break;
840 	case X86_INS_ROR:
841 	case X86_INS_RCR:
842 		// TODO: RCR Still does not work as intended
843 		//  - Set flags
844 		{
845 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
846 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
847 			esilprintf (op, "%s,%s,>>>,%s,=", src, dst, dst);
848 		}
849 		break;
850 	case X86_INS_CPUID:
851 		// https://c9x.me/x86/html/file_module_x86_id_45.html
852 		// GenuineIntel
853 		esilprintf (op, "0xa,eax,=,0x756E6547,ebx,=,0x6C65746E,ecx,=,0x49656E69,edx,=");
854 		break;
855 	case X86_INS_SHLD:
856 	case X86_INS_SHLX:
857 		// TODO: SHLD is not implemented yet.
858 		{
859 			ut32 bitsize;
860 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
861 			dst = getarg (&gop, 0, 1, "<<", DST_AR, &bitsize);
862 			esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=", src, dst, bitsize - 1);
863 		}
864 		break;
865 	case X86_INS_SAR:
866 		// TODO: Set CF. See case X86_INS_SHL for more details.
867 		{
868 #if 0
869 			ut64 val = 0;
870 			switch (gop.insn->detail->x86.operands[0].size) {
871 			case 1:
872 				val = 0x80;
873 				break;
874 			case 2:
875 				val = 0x8000;
876 				break;
877 			case 4:
878 				val = 0x80000000;
879 				break;
880 			case 8:
881 				val = 0x8000000000000000;
882 				break;
883 			default:
884 				val = 0x80;
885 			}
886 			src = getarg (&gop, 1, 0, NULL, SRC_AR);
887 			dst = getarg (&gop, 0, 0, NULL, DST_AR);
888 			esilprintf (op, "%s,1,%s,>>,0x%"PFMT64x",%s,&,|,%s,=,1,%s,&,cf,=,1,REPEAT", src, dst, val, dst, dst, dst);
889 #endif
890 			ut32 bitsize;
891 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
892 			dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
893 			dst_w = getarg (&gop, 0, 1, NULL, DST_W_AR, &bitsize);
894 			esilprintf (op, "0,cf,:=,1,%s,-,1,<<,%s,&,?{,1,cf,:=,},%s,%s,>>>>,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=",
895 				src, dst_r, src, dst_r, dst_w, bitsize - 1);
896 		}
897 		break;
898 	case X86_INS_SARX:
899 		{
900 			dst = getarg (&gop, 0, 1, NULL, 0, NULL);
901 			src = getarg (&gop, 1, 0, NULL, 1, NULL);
902 			src2 = getarg (&gop, 1, 0, NULL, 2, NULL);
903 			esilprintf (op, "%s,%s,>>>>,%s,=", src2, src, dst);
904 		}
905 		break;
906 	case X86_INS_SHL:
907 	case X86_INS_SAL:
908 		{
909 		ut64 val = 0;
910 		switch (gop.insn->detail->x86.operands[0].size) {
911 		case 1:
912 			val = 0x80;
913 			break;
914 		case 2:
915 			val = 0x8000;
916 			break;
917 		case 4:
918 			val = 0x80000000;
919 			break;
920 		case 8:
921 			val = 0x8000000000000000;
922 			break;
923 		default:
924 			eprintf ("Error: unknown operand size: %d\n", gop.insn->detail->x86.operands[0].size);
925 			val = 256;
926 		}
927 		ut32 bitsize;
928 		src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
929 		dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
930 		dst2 = getarg (&gop, 0, 1, "<<", DST2_AR, &bitsize);
931 		esilprintf (op, "0,%s,!,!,?{,1,%s,-,%s,<<,0x%llx,&,!,!,^,},%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,cf,=",
932 			src, src, dst, val, src, dst2, bitsize - 1);
933 	   	}
934 		break;
935 	case X86_INS_SALC:
936 		esilprintf (op, "$z,DUP,zf,=,al,=");
937 		break;
938 	case X86_INS_SHR:
939 	case X86_INS_SHRD:
940 	case X86_INS_SHRX:
941 		// TODO: Set CF: See case X86_INS_SAL for more details.
942 		{
943 			ut32 bitsize;
944 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
945 			dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
946 			dst_w = getarg (&gop, 0, 1, NULL, DST_W_AR, &bitsize);
947 			esilprintf (op, "0,cf,:=,1,%s,-,1,<<,%s,&,?{,1,cf,:=,},%s,%s,>>,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=",
948 					src, dst_r, src, dst_r, dst_w, bitsize - 1);
949 		}
950 		break;
951 	case X86_INS_CBW:
952 		esilprintf (op, "al,ax,=,7,ax,>>,?{,0xff00,ax,|=,}");
953 		break;
954 	case X86_INS_CWDE:
955 		esilprintf (op, "ax,eax,=,15,eax,>>,?{,0xffff0000,eax,|=,}");
956 		break;
957 	case X86_INS_CDQ:
958 		esilprintf (op, "0,edx,=,31,eax,>>,?{,0xffffffff,edx,=,}");
959 		break;
960 	case X86_INS_CDQE:
961 		esilprintf (op, "eax,rax,=,31,rax,>>,?{,0xffffffff00000000,rax,|=,}");
962 		break;
963 	case X86_INS_AAA:
964 		esilprintf (op, "0,cf,:=,0,af,:=,9,al,>,?{,10,al,-=,1,ah,+=,1,cf,:=,1,af,:=,}");	//don't
965 		break;
966 	case X86_INS_AAD:
967 		arg0 = "0,zf,:=,0,sf,:=,0,pf,:=,10,ah,*,al,+,ax,=";
968 		arg1 = "0,al,==,?{,1,zf,:=,},2,al,%,0,==,?{,1,pf,:=,},7,al,>>,?{,1,sf,:=,}";
969 		esilprintf (op, "%s,%s", arg0, arg1);
970 		break;
971 	case X86_INS_AAM:
972 		arg0 = "0,zf,:=,0,sf,:=,0,pf,:=,10,al,/,ah,=,10,al,%,al,=";
973 		arg1 = "0,al,==,?{,1,zf,:=,},2,al,%,0,==,?{,1,pf,:=,},7,al,>>,?{,1,sf,:=,}";
974 		esilprintf (op, "%s,%s", arg0, arg1);
975 		break;
976 	// XXX: case X86_INS_AAS: too tough to implement. BCD is deprecated anyways
977 	case X86_INS_CMPPD:
978 	case X86_INS_CMPPS:
979 	case X86_INS_CMPSW:
980 	case X86_INS_CMPSD:
981 	case X86_INS_CMPSQ:
982 	case X86_INS_CMPSB:
983 	case X86_INS_CMPSS:
984 		repe = true;
985 	case X86_INS_CMP:
986 	case X86_INS_TEST:
987 		{
988 			ut32 bitsize;
989 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
990 			dst = getarg (&gop, 0, 0, NULL, DST_AR, &bitsize);
991 
992 			if (!bitsize || bitsize > 64) {
993 				break;
994 			}
995 
996 			if (insn->id == X86_INS_TEST) {
997 				esilprintf (op, "0,%s,%s,&,==,$z,zf,:=,$p,pf,:=,%u,$s,sf,:=,0,cf,:=,0,of,:=",
998 					src, dst, bitsize - 1);
999 			} else if (insn->id == X86_INS_CMP) {
1000 				esilprintf (op,
1001 					"%s,%s,==,$z,zf,:=,%u,$b,cf,:=,$p,pf,:=,%u,$s,sf,:=,"\
1002 					"%s,0x%"PFMT64x",-,!,%u,$o,^,of,:=,3,$b,af,:=",
1003 					src, dst, bitsize, bitsize - 1, src, 1ULL << (bitsize - 1), bitsize - 1);
1004 			} else {
1005 				char *rsrc = (char *)cs_reg_name(*handle, INSOP(1).mem.base);
1006 				char *rdst = (char *)cs_reg_name(*handle, INSOP(0).mem.base);
1007 				const int width = INSOP(0).size;
1008 				esilprintf (op,
1009 					"%s,%s,==,$z,zf,:=,%u,$b,cf,:=,$p,pf,:=,%u,$s,sf,:=,%s,0x%"PFMT64x","\
1010 					"-,!,%u,$o,^,of,:=,3,$b,af,:=,df,?{,%d,%s,-=,%d,%s,-=,}{,%d,%s,+=,%d,%s,+=,}",
1011 					src, dst, bitsize, bitsize - 1, src, 1ULL << (bitsize - 1), bitsize - 1,
1012 					width, rsrc, width, rdst, width, rsrc, width, rdst);
1013 			}
1014 		}
1015 		break;
1016 	case X86_INS_LEA:
1017 		{
1018 			src = getarg (&gop, 1, 2, NULL, SRC_AR, NULL);
1019 			dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1020 			esilprintf (op, "%s,%s", src, dst);
1021 		}
1022 		break;
1023 	case X86_INS_PUSHAW:
1024 	// pushal, popal - push/pop EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
1025 	case X86_INS_PUSHAL:
1026 		{
1027 			esilprintf (op,
1028 				"0,%s,+,"
1029 				"%d,%s,-=,%s,%s,=[%d],"
1030 				"%d,%s,-=,%s,%s,=[%d],"
1031 				"%d,%s,-=,%s,%s,=[%d],"
1032 				"%d,%s,-=,%s,%s,=[%d],"
1033 				"%d,%s,-=,%s,=[%d],"
1034 				"%d,%s,-=,%s,%s,=[%d],"
1035 				"%d,%s,-=,%s,%s,=[%d],"
1036 				"%d,%s,-=,%s,%s,=[%d]",
1037 				sp,
1038 				rs, sp, "eax", sp, rs,
1039 				rs, sp, "ecx", sp, rs,
1040 				rs, sp, "edx", sp, rs,
1041 				rs, sp, "ebx", sp, rs,
1042 				rs, sp, "esp", rs,
1043 				rs, sp, "ebp", sp, rs,
1044 				rs, sp, "esi", sp, rs,
1045 				rs, sp, "edi", sp, rs
1046 				);
1047 		}
1048 		break;
1049 	case X86_INS_ENTER:
1050 	case X86_INS_PUSH:
1051 		{
1052 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1053 			esilprintf (op, "%s,%d,%s,-,=[%d],%d,%s,-=",
1054 				r_str_get_fail (dst, "eax"), rs, sp, rs, rs, sp);
1055 		}
1056 		break;
1057 	case X86_INS_PUSHF:
1058 	case X86_INS_PUSHFD:
1059 	case X86_INS_PUSHFQ:
1060 		esilprintf (op, "%d,%s,-=,eflags,%s,=[%d]", rs, sp, sp, rs);
1061 		break;
1062 	case X86_INS_LEAVE:
1063 		esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=",
1064 			bp, sp, sp, rs, bp, rs, sp);
1065 		break;
1066 	case X86_INS_POPAW:
1067 	case X86_INS_POPAL:
1068 		{
1069 			esilprintf (op,
1070 				"%s,[%d],%d,%s,+=,%s,=,"
1071 				"%s,[%d],%d,%s,+=,%s,=,"
1072 				"%s,[%d],%d,%s,+=,%s,=,"
1073 				"%s,[%d],%d,%s,+=,"
1074 				"%s,[%d],%d,%s,+=,%s,=,"
1075 				"%s,[%d],%d,%s,+=,%s,=,"
1076 				"%s,[%d],%d,%s,+=,%s,=,"
1077 				"%s,[%d],%d,%s,+=,%s,=,"
1078 				"%s,=",
1079 				sp, rs, rs, sp, "edi",
1080 				sp, rs, rs, sp, "esi",
1081 				sp, rs, rs, sp, "ebp",
1082 				sp, rs, rs, sp,
1083 				sp, rs, rs, sp, "ebx",
1084 				sp, rs, rs, sp, "edx",
1085 				sp, rs, rs, sp, "ecx",
1086 				sp, rs, rs, sp, "eax",
1087 				sp
1088 				);
1089 		}
1090 		break;
1091 	case X86_INS_POP:
1092 		{
1093 			switch (INSOP(0).type) {
1094 			case X86_OP_MEM:
1095 				{
1096 					dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1097 					esilprintf (op,
1098 						"%s,[%d],%s,%d,%s,+=",
1099 						sp, rs, dst, rs, sp);
1100 					break;
1101 				}
1102 			case X86_OP_REG:
1103 			default:
1104 				{
1105 					dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1106 					esilprintf (op,
1107 						"%s,[%d],%s,=,%d,%s,+=",
1108 						sp, rs, dst, rs, sp);
1109 					break;
1110 				}
1111 			}
1112 		}
1113 		break;
1114 	case X86_INS_POPF:
1115 	case X86_INS_POPFD:
1116 	case X86_INS_POPFQ:
1117 		esilprintf (op, "%s,[%d],eflags,=", sp, rs);
1118 		break;
1119 	case X86_INS_RET:
1120 	case X86_INS_RETF:
1121 	case X86_INS_RETFQ:
1122 	case X86_INS_IRET:
1123 	case X86_INS_IRETD:
1124 	case X86_INS_IRETQ:
1125 	case X86_INS_SYSRET:
1126 		{
1127 		int cleanup = 0;
1128 		if (INSOPS > 0) {
1129 			cleanup = (int)INSOP(0).imm;
1130 		}
1131 		esilprintf (op, "%s,[%d],%s,=,%d,%s,+=",
1132 			sp, rs, pc, rs + cleanup, sp);
1133 		}
1134 		break;
1135 	case X86_INS_INT3:
1136 		esilprintf (op, "3,$");
1137 		break;
1138 	case X86_INS_INT1:
1139 		esilprintf (op, "1,$");
1140 		break;
1141 	case X86_INS_INT:
1142 		esilprintf (op, "%d,$",
1143 			R_ABS((int)INSOP(0).imm));
1144 		break;
1145 	case X86_INS_SYSCALL:
1146 		esilprintf (op, "rax,()");
1147 		break;
1148 	case X86_INS_SYSENTER:
1149 	case X86_INS_SYSEXIT:
1150 		break;
1151 	case X86_INS_INTO:
1152 	case X86_INS_VMCALL:
1153 	case X86_INS_VMMCALL:
1154 		esilprintf (op, "%d,$", (int)INSOP(0).imm);
1155 		break;
1156 	case X86_INS_JL:
1157 	case X86_INS_JLE:
1158 	case X86_INS_JA:
1159 	case X86_INS_JAE:
1160 	case X86_INS_JB:
1161 	case X86_INS_JBE:
1162 	case X86_INS_JCXZ:
1163 	case X86_INS_JECXZ:
1164 	case X86_INS_JRCXZ:
1165 	case X86_INS_JO:
1166 	case X86_INS_JNO:
1167 	case X86_INS_JS:
1168 	case X86_INS_JNS:
1169 	case X86_INS_JP:
1170 	case X86_INS_JNP:
1171 	case X86_INS_JE:
1172 	case X86_INS_JNE:
1173 	case X86_INS_JG:
1174 	case X86_INS_JGE:
1175 	case X86_INS_LOOP:
1176 	case X86_INS_LOOPE:
1177 	case X86_INS_LOOPNE:
1178 		{
1179 			const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx";
1180 			dst = getarg (&gop, 0, 2, NULL, DST_AR, NULL);
1181 			switch (insn->id) {
1182 			case X86_INS_JL:
1183 				esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc);
1184 				break;
1185 			case X86_INS_JLE:
1186 				esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc);
1187 				break;
1188 			case X86_INS_JA:
1189 				esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc);
1190 				break;
1191 			case X86_INS_JAE:
1192 				esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc);
1193 				break;
1194 			case X86_INS_JB:
1195 				esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc);
1196 				break;
1197 			case X86_INS_JO:
1198 				esilprintf (op, "of,?{,%s,%s,=,}", dst, pc);
1199 				break;
1200 			case X86_INS_JNO:
1201 				esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc);
1202 				break;
1203 			case X86_INS_JE:
1204 				esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc);
1205 				break;
1206 			case X86_INS_JGE:
1207 				esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc);
1208 				break;
1209 			case X86_INS_JNE:
1210 				esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc);
1211 				break;
1212 			case X86_INS_JG:
1213 				esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc);
1214 				break;
1215 			case X86_INS_JS:
1216 				esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc);
1217 				break;
1218 			case X86_INS_JNS:
1219 				esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc);
1220 				break;
1221 			case X86_INS_JP:
1222 				esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc);
1223 				break;
1224 			case X86_INS_JNP:
1225 				esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc);
1226 				break;
1227 			case X86_INS_JBE:
1228 				esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc);
1229 				break;
1230 			case X86_INS_JCXZ:
1231 				esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc);
1232 				break;
1233 			case X86_INS_JECXZ:
1234 				esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc);
1235 				break;
1236 			case X86_INS_JRCXZ:
1237 				esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc);
1238 				break;
1239 			case X86_INS_LOOP:
1240 				esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc);
1241 				break;
1242 			case X86_INS_LOOPE:
1243 				esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}",
1244 					cnt, cnt, dst, pc);
1245 				break;
1246 			case X86_INS_LOOPNE:
1247 				esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}",
1248 					cnt, cnt, dst, pc);
1249 				break;
1250 			}
1251 		}
1252 		break;
1253 	case X86_INS_CALL:
1254 		{
1255 			if (a->read_at && a->bits != 16) {
1256 				ut8 thunk[4] = {0};
1257 				if (a->read_at (a, (ut64)INSOP (0).imm, thunk, sizeof (thunk))) {
1258 					/* 8b xx x4    mov <reg>, dword [esp]
1259 					   c3          ret
1260 					*/
1261 					if (thunk[0] == 0x8b && thunk[3] == 0xc3
1262 					    && (thunk[1] & 0xc7) == 4        /* 00rrr100 */
1263 					    && (thunk[2] & 0x3f) == 0x24) {  /* --100100: ignore scale in SIB byte */
1264 						ut8 reg = (thunk[1] & 0x38) >> 3;
1265 						esilprintf (op, "0x%"PFMT64x",%s,=", addr + op->size,
1266 						            reg32_to_name (reg));
1267 						break;
1268 					}
1269 				}
1270 			}
1271 			arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1272 			esilprintf (op,
1273 					"%s,%s,"
1274 					"%d,%s,-=,%s,"
1275 					"=[],"
1276 					"%s,=",
1277 					arg0, pc, rs, sp, sp, pc);
1278 		}
1279 		break;
1280 	case X86_INS_LCALL:
1281 		{
1282 			arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1283 			arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1284 			if (arg1) {
1285 				esilprintf (op,
1286 						"2,%s,-=,cs,%s,=[2],"	// push CS
1287 						"%d,%s,-=,%s,%s,=[],"	// push IP/EIP
1288 						"%s,cs,=,"		// set CS
1289 						"%s,%s,=",		// set IP/EIP
1290 						sp, sp, rs, sp, pc, sp, arg0, arg1, pc);
1291 			} else {
1292 				esilprintf (op,
1293 						"%s,%s,-=,%d,%s,=[],"	// push IP/EIP
1294 						"%s,%s,=",		// set IP/EIP
1295 						sp, sp, rs, sp, arg0, pc);
1296 			}
1297 		}
1298 		break;
1299 	case X86_INS_JMP:
1300 	case X86_INS_LJMP:
1301 		{
1302 			src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1303 			esilprintf (op, "%s,%s,=", src, pc);
1304 		}
1305 		// TODO: what if UJMP?
1306 		switch (INSOP(0).type) {
1307 		case X86_OP_IMM:
1308 			if (INSOP(1).type == X86_OP_IMM) {
1309 				ut64 seg = INSOP(0).imm;
1310 				ut64 off = INSOP(1).imm;
1311 				esilprintf (
1312 					op,
1313 					"0x%"PFMT64x",cs,=,"
1314 					"0x%"PFMT64x",%s,=",
1315 					seg, off, pc);
1316 			} else {
1317 				ut64 dst = INSOP(0).imm;
1318 				esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc);
1319 			}
1320 			break;
1321 		case X86_OP_MEM:
1322 			if (INSOP(0).mem.base == X86_REG_RIP) {
1323 				/* nothing here */
1324 			} else {
1325 				cs_x86_op in = INSOP (0);
1326 				if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) {
1327 					if (in.mem.segment != X86_REG_INVALID) {
1328 						esilprintf (
1329 							op,
1330 							"4,%s,<<,0x%"PFMT64x",+,[],%s,=",
1331 							INSOP(0).mem.segment == X86_REG_ES ? "es"
1332 							: INSOP(0).mem.segment == X86_REG_CS ? "cs"
1333 							: INSOP(0).mem.segment == X86_REG_DS ? "ds"
1334 							: INSOP(0).mem.segment == X86_REG_FS ? "fs"
1335 							: INSOP(0).mem.segment == X86_REG_GS ? "gs"
1336 							: INSOP(0).mem.segment == X86_REG_SS ? "ss"
1337 							: "unknown_segment_register",
1338 							(ut64)INSOP(0).mem.disp,
1339 							pc);
1340 					} else {
1341 						esilprintf (
1342 							op,
1343 							"0x%"PFMT64x",[],%s,=",
1344 							(ut64)INSOP(0).mem.disp, pc);
1345 					}
1346 				}
1347 			}
1348 			break;
1349 		case X86_OP_REG:
1350 			{
1351 			src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1352 			op->src[0] = r_anal_value_new ();
1353 			op->src[0]->reg = r_reg_get (a->reg, src, R_REG_TYPE_GPR);
1354 			//XXX fallthrough
1355 			}
1356 		//case X86_OP_FP:
1357 		default: // other?
1358 			break;
1359 		}
1360 		break;
1361 	case X86_INS_IN:
1362 	case X86_INS_INSW:
1363 	case X86_INS_INSD:
1364 	case X86_INS_INSB:
1365 		if (ISIMM (1)) {
1366 			op->val = INSOP (1).imm;
1367 		}
1368 		break;
1369 	case X86_INS_OUT:
1370 	case X86_INS_OUTSB:
1371 	case X86_INS_OUTSD:
1372 	case X86_INS_OUTSW:
1373 		if (ISIMM (0)) {
1374 			op->val = INSOP (0).imm;
1375 		}
1376 		break;
1377 	case X86_INS_VXORPD:
1378 	case X86_INS_VXORPS:
1379 	case X86_INS_VPXORD:
1380 	case X86_INS_VPXORQ:
1381 	case X86_INS_VPXOR:
1382 	case X86_INS_XORPS:
1383 	case X86_INS_KXORW:
1384 	case X86_INS_PXOR:
1385 	case X86_INS_XOR:
1386 		{
1387 			ut32 bitsize;
1388 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1389 			dst = getarg (&gop, 0, 1, "^", DST_AR, &bitsize);
1390 			dst2 = getarg (&gop, 0, 0, NULL, DST2_AR, NULL);
1391 			const char *dst_reg64 = r_reg_32_to_64 (a->reg, dst2);		// 64-bit destination if exists
1392 			if (a->bits == 64 && dst_reg64) {
1393 				// (64-bit ^ 32-bit) & 0xFFFF FFFF -> 64-bit, it's alright, higher bytes will be eliminated
1394 				// (consider this is operation with 32-bit regs in 64-bit environment).
1395 				esilprintf (op, "%s,%s,^,0xffffffff,&,%s,=,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1396 					src, dst_reg64, dst_reg64, bitsize - 1);
1397 			} else {
1398 				esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1399 					src, dst, bitsize - 1);
1400 			}
1401 		}
1402 		break;
1403 	case X86_INS_BSF:
1404 		{
1405 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1406 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1407 			int bits = INSOP (0).size * 8;
1408 
1409 			/*
1410 			 * Here we first set ZF depending on the source operand
1411 			 * (and bail out if it's 0), then test each bit in a loop
1412 			 * by creating a mask on the stack and applying it, returning
1413 			 * result if bit is set.
1414 			 */
1415 			esilprintf (op, "%s,!,?{,1,zf,=,BREAK,},0,zf,=,"
1416 					"%d,DUP,%d,-,1,<<,%s,&,?{,%d,-,%s,=,BREAK,},12,REPEAT",
1417 					src, bits, bits, src, bits, dst);
1418 		}
1419 		break;
1420 	case X86_INS_BSR:
1421 		{
1422 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1423 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1424 			int bits = INSOP (0).size * 8;
1425 
1426 			/*
1427 			 * Similar to BSF, except we naturally don't
1428 			 * need to subtract anything to create
1429 			 * a mask and return the result.
1430 			 */
1431 			esilprintf (op, "%s,!,?{,1,zf,=,BREAK,},0,zf,=,"
1432 					"%d,DUP,1,<<,%s,&,?{,%s,=,BREAK,},12,REPEAT",
1433 					src, bits, src, dst);
1434 		}
1435 		break;
1436 	case X86_INS_BSWAP:
1437 		{
1438 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1439 			if (INSOP(0).size == 4) {
1440 				esilprintf (op, "0xff000000,24,%s,NUM,<<,&,24,%s,NUM,>>,|,"
1441 						"8,0x00ff0000,%s,NUM,&,>>,|,"
1442 						"8,0x0000ff00,%s,NUM,&,<<,|,"
1443 						"%s,=", dst, dst, dst, dst, dst);
1444 			} else {
1445 				esilprintf (op, "0xff00000000000000,56,%s,NUM,<<,&,"
1446 						"56,%s,NUM,>>,|,40,0xff000000000000,%s,NUM,&,>>,|,"
1447 						"40,0xff00,%s,NUM,&,<<,|,24,0xff0000000000,%s,NUM,&,>>,|,"
1448 						"24,0xff0000,%s,NUM,&,<<,|,8,0xff00000000,%s,NUM,&,>>,|,"
1449 						"8,0xff000000,%s,NUM,&,<<,|,"
1450 						"%s,=", dst, dst, dst, dst, dst, dst, dst, dst, dst);
1451 			}
1452 		}
1453 		break;
1454 	case X86_INS_OR:
1455 		// The OF and CF flags are cleared; the SF, ZF, and PF flags are
1456 		// set according to the result. The state of the AF flag is
1457 		// undefined.
1458 		{
1459 			ut32 bitsize;
1460 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1461 			dst = getarg (&gop, 0, 1, "|", DST_AR, &bitsize);
1462 			esilprintf (op, "%s,%s,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,0,of,:=,0,cf,:=",
1463 					src, dst, bitsize - 1);
1464 		}
1465 		break;
1466 	case X86_INS_INC:
1467 		// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
1468 		// are set according to the result.
1469 		{
1470 			ut32 bitsize;
1471 			src = getarg (&gop, 0, 1, "++", SRC_AR, &bitsize);
1472 			esilprintf (op, "%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,3,$c,af,:=", src, bitsize - 1, bitsize - 1);
1473 		}
1474 		break;
1475 	case X86_INS_DEC:
1476 		// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
1477 		// are set according to the result.
1478 		{
1479 			ut32 bitsize;
1480 			src = getarg (&gop, 0, 1, "--", SRC_AR, &bitsize);
1481 			esilprintf (op, "%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,3,$b,af,:=", src, bitsize - 1, bitsize - 1);
1482 		}
1483 		break;
1484 	case X86_INS_PSUBB:
1485 	case X86_INS_PSUBW:
1486 	case X86_INS_PSUBD:
1487 	case X86_INS_PSUBQ:
1488 	case X86_INS_PSUBSB:
1489 	case X86_INS_PSUBSW:
1490 	case X86_INS_PSUBUSB:
1491 	case X86_INS_PSUBUSW:
1492 		{
1493 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1494 			dst = getarg (&gop, 0, 1, "-", DST_AR, NULL);
1495 			esilprintf (op, "%s,%s", src, dst);
1496 		}
1497 		break;
1498 	case X86_INS_SUB:
1499 		{
1500 			ut32 bitsize;
1501 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1502 			dst = getarg (&gop, 0, 1, "-", DST_AR, &bitsize);
1503 
1504 			if (!bitsize || bitsize > 64) {
1505 				break;
1506 			}
1507 
1508 			// Set OF, SF, ZF, AF, PF, and CF flags.
1509 			// We use $b rather than $c here as the carry flag really
1510 			// represents a "borrow"
1511 			esilprintf (op, "%s,%s,%s,0x%"PFMT64x",-,!,%u,$o,^,of,:=,%u,$s,sf,:=,$z,zf,:=,$p,pf,:=,%u,$b,cf,:=,3,$b,af,:=",
1512 				src, dst, src, 1ULL << (bitsize - 1), bitsize - 1, bitsize - 1, bitsize);
1513 		}
1514 		break;
1515 	case X86_INS_SBB:
1516 		// dst = dst - (src + cf)
1517 		{
1518 			ut32 bitsize;
1519 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1520 			dst = getarg (&gop, 0, 0, NULL, DST_AR, &bitsize);
1521 			esilprintf (op, "cf,%s,+,%s,-=,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,$p,pf,:=,%d,$b,cf,:=",
1522 				src, dst, bitsize - 1, bitsize - 1, bitsize);
1523 		}
1524 		break;
1525 	case X86_INS_LIDT:
1526 		break;
1527 	case X86_INS_SIDT:
1528 		break;
1529 	case X86_INS_RDRAND:
1530 	case X86_INS_RDSEED:
1531 	case X86_INS_RDMSR:
1532 	case X86_INS_RDPMC:
1533 	case X86_INS_RDTSC:
1534 	case X86_INS_RDTSCP:
1535 	case X86_INS_CRC32:
1536 	case X86_INS_SHA1MSG1:
1537 	case X86_INS_SHA1MSG2:
1538 	case X86_INS_SHA1NEXTE:
1539 	case X86_INS_SHA1RNDS4:
1540 	case X86_INS_SHA256MSG1:
1541 	case X86_INS_SHA256MSG2:
1542 	case X86_INS_SHA256RNDS2:
1543 	case X86_INS_AESDECLAST:
1544 	case X86_INS_AESDEC:
1545 	case X86_INS_AESENCLAST:
1546 	case X86_INS_AESENC:
1547 	case X86_INS_AESIMC:
1548 	case X86_INS_AESKEYGENASSIST:
1549 		// AES instructions
1550 		break;
1551 	case X86_INS_AND:
1552 	case X86_INS_ANDN:
1553 	case X86_INS_ANDPD:
1554 	case X86_INS_ANDPS:
1555 	case X86_INS_ANDNPD:
1556 	case X86_INS_ANDNPS:
1557 		{
1558 			ut32 bitsize;
1559 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1560 			dst = getarg (&gop, 0, 1, "&", DST_AR, &bitsize);
1561 			dst2 = getarg (&gop, 0, 0, NULL, DST2_AR, NULL);
1562 			const char *dst_reg64 = r_reg_32_to_64 (a->reg, dst2);		// 64-bit destination if exists
1563 			if (a->bits == 64 && dst_reg64) {
1564 				// (64-bit & 32-bit) & 0xFFFF FFFF -> 64-bit, it's alright, higher bytes will be eliminated
1565 				// (consider this is operation with 32-bit regs in 64-bit environment).
1566 				esilprintf (op, "%s,%s,&,0xffffffff,&,%s,=,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=",
1567 						src, dst_reg64, dst_reg64, bitsize - 1);
1568 			} else {
1569 				esilprintf (op, "%s,%s,$z,zf,:=,$p,pf,:=,%d,$s,sf,:=,0,cf,:=,0,of,:=", src, dst, bitsize - 1);
1570 			}
1571 		}
1572 		break;
1573 	case X86_INS_IDIV:
1574 		{
1575 			arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1576 			arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1577 			arg2 = getarg (&gop, 2, 0, NULL, ARG2_AR, NULL);
1578 			// DONE handle signedness
1579 			// IDIV does not change flags
1580 			op->sign = true;
1581 			if (!arg2 && !arg1) {
1582 				// TODO: IDIV rbx not implemented. this is just a workaround
1583 				//
1584 				// http://www.tptp.cc/mirrors/siyobik.info/instruction/IDIV.html
1585 				// Divides (signed) the value in the AX, DX:AX, or EDX:EAX registers (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends on the operand size (dividend/divisor), as shown in the following table:
1586 				// IDIV RBX    ==   RDX:RAX /= RBX
1587 
1588 				//
1589 				if (arg0) {
1590 					int width = INSOP(0).size;
1591 					const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1592 					const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1593 					const char *r_nume = (width==1)?"ax": r_quot;
1594 
1595 
1596 					esilprintf (op, "%d,%s,~,%d,%s,<<,%s,+,~%%,%d,%s,~,%d,%s,<<,%s,+,~/,%s,=,%s,=",
1597 							width*8, arg0, width*8, r_rema, r_nume, width*8, arg0, width*8, r_rema, r_nume, r_quot, r_rema);
1598 				}
1599 				else {
1600 					/* should never happen */
1601 				}
1602 			} else {
1603 				// does this instruction even exist?
1604 				int width = INSOP(0).size;
1605 				esilprintf (op, "%d,%s,~,%d,%s,~,~/,%s,=", width*8, arg2, width*8, arg1, arg0);
1606 			}
1607 		}
1608 		break;
1609 	case X86_INS_DIV:
1610 		{
1611 			int width = INSOP(0).size;
1612 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1613 			const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1614 			const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1615 			const char *r_nume = (width==1)?"ax": r_quot;
1616 			// DIV does not change flags and is unsigned
1617 
1618 			esilprintf (op, "%s,%d,%s,<<,%s,+,%%,%s,%d,%s,<<,%s,+,/,%s,=,%s,=",
1619 					dst, width*8, r_rema, r_nume, dst, width*8, r_rema, r_nume, r_quot, r_rema);
1620 		}
1621 		break;
1622 	case X86_INS_IMUL:
1623 		{
1624 			arg0 = getarg (&gop, 0, 0, NULL, ARG0_AR, NULL);
1625 			arg1 = getarg (&gop, 1, 0, NULL, ARG1_AR, NULL);
1626 			arg2 = getarg (&gop, 2, 0, NULL, ARG2_AR, NULL);
1627 			op->sign = true;
1628 			int width = INSOP(0).size;
1629 			if (arg2) {
1630 				// flags and sign have been handled
1631 				esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,%s,=,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=", width*8, arg2, width*8, arg1, arg0, arg0);
1632 			} else {
1633 				if (arg1) {
1634 					esilprintf (op, "%d,%s,~,%d,%s,~,*,DUP,%s,=,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=", width*8, arg0, width*8, arg1, arg0, arg0);
1635 				} else {
1636 					if (arg0) {
1637 						const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1638 						const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1639 						const char *r_nume = (width==1)?"ax": r_quot;
1640 
1641 						if ( width == 1 ) {
1642 							esilprintf(op, "0xffffff00,eflags,&=,%s,%s,%%,eflags,|=,%s,%s,*,%s,=,0xff,eflags,&,%s,=,0xffffff00,eflags,&=,2,eflags,|=",
1643 								arg0, r_nume, arg0, r_nume, r_quot, r_rema);
1644 						} else {
1645 							// this got a little bit crazy,
1646 							esilprintf (op, "%d,%d,%s,~,%d,%s,~,*,>>,%s,=,%s,%s,*=,%d,%d,%s,~,>>,%s,-,?{,1,1,}{,0,0,},cf,:=,of,:=",
1647 									width*8, width*8, arg0, width*8, r_nume, r_rema, arg0, r_nume, width*8, width*8, r_nume, r_rema);
1648 						}
1649 					}
1650 					else {
1651 						/* should never happen */
1652 					}
1653 				}
1654 			}
1655 		}
1656 		break;
1657 	case X86_INS_MUL:
1658 		{
1659 			src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1660 			if (src) {
1661 				int width = INSOP(0).size;
1662 				const char *r_quot = (width==1)?"al": (width==2)?"ax": (width==4)?"eax":"rax";
1663 				const char *r_rema = (width==1)?"ah": (width==2)?"dx": (width==4)?"edx":"rdx";
1664 				const char *r_nume = (width==1)?"ax": r_quot;
1665 
1666 				if ( width == 1 ) {
1667 					esilprintf(op, "0xffffff00,eflags,&=,%s,%s,%%,eflags,|=,%s,%s,*,%s,=,0xff,eflags,&,%s,=,0xffffff00,eflags,&=,2,eflags,|=",
1668 						src, r_nume, src, r_nume, r_quot, r_rema);
1669 				} else {
1670 					esilprintf (op, "%d,%s,%s,*,>>,%s,=,%s,%s,*=,%s,?{,1,1,}{,0,0,},cf,:=,of,:=",
1671 							width*8, src, r_nume, r_rema, src, r_nume, r_rema);
1672 				}
1673 			} else {
1674 				/* should never happen */
1675 			}
1676 		}
1677 		break;
1678 	case X86_INS_MULX:
1679 	case X86_INS_MULPD:
1680 	case X86_INS_MULPS:
1681 	case X86_INS_MULSD:
1682 	case X86_INS_MULSS:
1683 		{
1684 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1685 			dst = getarg (&gop, 0, 1, "*", DST_AR, NULL);
1686 			if (!src && dst) {
1687 				switch (dst[0]) {
1688 				case 'r':
1689 					src = "rax";
1690 					break;
1691 				case 'e':
1692 					src = "eax";
1693 					break;
1694 				default:
1695 					src = "al";
1696 					break;
1697 				}
1698 			}
1699 			esilprintf (op, "%s,%s", src, dst);
1700 		}
1701 		break;
1702 	case X86_INS_NEG:
1703 		{
1704 			ut32 bitsize;
1705 			src = getarg (&gop, 0, 0, NULL, SRC_AR, NULL);
1706 			dst = getarg (&gop, 0, 1, NULL, DST_AR, &bitsize);
1707 			ut64 xor = 0;
1708 			switch (bitsize) {
1709 			case 8:
1710 				xor = 0xff;
1711 				break;
1712 			case 16:
1713 				xor = 0xffff;
1714 				break;
1715 			case 32:
1716 				xor = 0xffffffff;
1717 				break;
1718 			case 64:
1719 				xor = 0xffffffffffffffff;
1720 				break;
1721 			default:
1722 				eprintf ("Neg: Unhandled bitsize %d\n", bitsize);
1723 			}
1724 			esilprintf (op, "%s,!,!,cf,:=,%s,0x%"PFMT64x",^,1,+,%s,$z,zf,:=,0,of,:=,%d,$s,sf,:=,%d,$o,pf,:=",
1725 				src, src, xor, dst, bitsize - 1, bitsize - 1);
1726 		}
1727 		break;
1728 	case X86_INS_NOT:
1729 		{
1730 			dst = getarg (&gop, 0, 1, "^", DST_AR, NULL);
1731 			esilprintf (op, "-1,%s", dst);
1732 		}
1733 		break;
1734 	case X86_INS_PACKSSDW:
1735 	case X86_INS_PACKSSWB:
1736 	case X86_INS_PACKUSWB:
1737 		break;
1738 	case X86_INS_PADDB:
1739 	case X86_INS_PADDD:
1740 	case X86_INS_PADDW:
1741 	case X86_INS_PADDSB:
1742 	case X86_INS_PADDSW:
1743 	case X86_INS_PADDUSB:
1744 	case X86_INS_PADDUSW:
1745 		break;
1746 	case X86_INS_XCHG:
1747 		{
1748 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1749 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1750 			if (INSOP(0).type == X86_OP_MEM) {
1751 				dst2 = getarg (&gop, 0, 1, NULL, DST2_AR, NULL);
1752 				esilprintf (op,
1753 					"%s,%s,^,%s,=,"
1754 					"%s,%s,^,%s,"
1755 					"%s,%s,^,%s,=",
1756 					dst, src, src,	// x = x ^ y
1757 					src, dst, dst2,	// y = y ^ x
1758 					dst, src, src); // x = x ^ y
1759 			} else {
1760 				esilprintf (op,
1761 					"%s,%s,^,%s,=,"
1762 					"%s,%s,^,%s,=,"
1763 					"%s,%s,^,%s,=",
1764 					dst, src, src,  // x = x ^ y
1765 					src, dst, dst,  // y = y ^ x
1766 					dst, src, src); // x = x ^ y
1767 				//esilprintf (op, "%s,%s,%s,=,%s", src, dst, src, dst);
1768 			}
1769 		}
1770 		break;
1771 	case X86_INS_XADD: /* xchg + add */
1772 		{
1773 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1774 			dst = getarg (&gop, 0, 0, NULL, DST_AR, NULL);
1775 			dstAdd = getarg (&gop, 0, 1, "+", DSTADD_AR, NULL);
1776 			if (INSOP(0).type == X86_OP_MEM) {
1777 				dst2 = getarg (&gop, 0, 1, NULL, DST2_AR, NULL);
1778 				esilprintf (op,
1779 					"%s,%s,^,%s,=,"
1780 					"%s,%s,^,%s,"
1781 					"%s,%s,^,%s,=,"
1782 					"%s,%s",
1783 					dst, src, src,	// x = x ^ y
1784 					src, dst, dst2,	// y = y ^ x
1785 					dst, src, src,  // x = x ^ y
1786 					src, dstAdd);
1787 			} else {
1788 				esilprintf (op,
1789 					"%s,%s,^,%s,=,"
1790 					"%s,%s,^,%s,=,"
1791 					"%s,%s,^,%s,=,"
1792 					"%s,%s",
1793 					dst, src, src,  // x = x ^ y
1794 					src, dst, dst,  // y = y ^ x
1795 					dst, src, src,  // x = x ^ y
1796 					src, dstAdd);
1797 				//esilprintf (op, "%s,%s,%s,=,%s", src, dst, src, dst);
1798 			}
1799 		}
1800 		break;
1801 	case X86_INS_FADD:
1802 #if CS_API_MAJOR > 4
1803 	case X86_INS_PFADD:
1804 #else
1805 	case X86_INS_FADDP:
1806 #endif
1807 		break;
1808 	case X86_INS_ADDPS:
1809 	case X86_INS_ADDSD:
1810 	case X86_INS_ADDSS:
1811 	case X86_INS_ADDSUBPD:
1812 	case X86_INS_ADDSUBPS:
1813 	case X86_INS_ADDPD:
1814 		// The OF, SF, ZF, AF, CF, and PF flags are set according to the
1815 		// result.
1816 		if (INSOP(0).type == X86_OP_MEM) {
1817 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1818 			src2 = getarg (&gop, 0, 0, NULL, SRC2_AR, NULL);
1819 			dst = getarg (&gop, 0, 1, NULL, DST_AR, NULL);
1820 			esilprintf (op, "%s,%s,+,%s", src, src2, dst);
1821 		} else {
1822 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1823 			dst = getarg (&gop, 0, 1, "+", DST_AR, NULL);
1824 			esilprintf (op, "%s,%s", src, dst);
1825 		}
1826 		break;
1827 	case X86_INS_ADD:
1828 		// The OF, SF, ZF, AF, CF, and PF flags are set according to the
1829 		// result.
1830 		{
1831 			ut32 bitsize;
1832 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1833 			dst = getarg (&gop, 0, 1, "+", DST_AR, &bitsize);
1834 			esilprintf (op, "%s,%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,%d,$c,cf,:=,$p,pf,:=,3,$c,af,:=",
1835 				src, dst, bitsize - 1, bitsize - 1, bitsize - 1);
1836 		}
1837 		break;
1838 	case X86_INS_ADC:
1839 		{
1840 			ut32 bitsize;
1841 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1842 			dst = getarg (&gop, 0, 1, "+", DST_AR, &bitsize);
1843 			// dst = dst + src + cf
1844 			// NOTE: We would like to add the carry first before adding the
1845 			// source to ensure that the flag computation from $c belongs
1846 			// to the operation of adding dst += src rather than the one
1847 			// that adds carry (as esil only keeps track of the last
1848 			// addition to set the flags).
1849 			esilprintf (op, "cf,%s,+,%s,%d,$o,of,:=,%d,$s,sf,:=,$z,zf,:=,%d,$c,cf,:=,$p,pf,:=,3,$c,af,:=",
1850 					src, dst, bitsize - 1, bitsize - 1, bitsize - 1);
1851 		}
1852 		break;
1853 		/* Direction flag */
1854 	case X86_INS_CLD:
1855 		esilprintf (op, "0,df,:=");
1856 		break;
1857 	case X86_INS_STD:
1858 		esilprintf (op, "1,df,:=");
1859 		break;
1860 	case X86_INS_SUBSD:    //cvtss2sd
1861 	case X86_INS_CVTSS2SD: //cvtss2sd
1862 		break;
1863 	case X86_INS_BT:
1864 	case X86_INS_BTC:
1865 	case X86_INS_BTR:
1866 	case X86_INS_BTS:
1867 		if (INSOP(0).type == X86_OP_MEM && INSOP(1).type == X86_OP_REG) {
1868 			int width = INSOP(0).size;
1869 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1870 			dst_r = getarg (&gop, 0, 2 /* use the address without loading */, NULL, DST_R_AR, NULL);
1871 			esilprintf (op, "0,cf,:=,%d,%s,%%,1,<<,%d,%s,/,%s,+,[%d],&,?{,1,cf,:=,}",
1872 					width * 8, src, width * 8, src, dst_r, width);
1873 			switch (insn->id) {
1874 			case X86_INS_BTS:
1875 			case X86_INS_BTC:
1876 				r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,%d,%s,/,%s,+,%c=[%d]",
1877 						width * 8, src, width * 8, src, dst_r,
1878 						(insn->id == X86_INS_BTS)?'|':'^', width);
1879 				break;
1880 			case X86_INS_BTR:
1881 				dst_w = getarg (&gop, 0, 1, "&", DST_R_AR, NULL);
1882 				r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,-1,^,%d,%s,/,%s,+,&=[%d]",
1883 						width * 8, src, width * 8, src, dst_r, width);
1884 				break;
1885 			}
1886 		} else {
1887 			int width = INSOP(0).size;
1888 			src = getarg (&gop, 1, 0, NULL, SRC_AR, NULL);
1889 			dst_r = getarg (&gop, 0, 0, NULL, DST_R_AR, NULL);
1890 			esilprintf (op, "0,cf,:=,%d,%s,%%,1,<<,%s,&,?{,1,cf,:=,}",
1891 					width * 8, src, dst_r);
1892 			switch (insn->id) {
1893 			case X86_INS_BTS:
1894 			case X86_INS_BTC:
1895 				dst_w = getarg (&gop, 0, 1, (insn->id == X86_INS_BTS)?"|":"^", DST_R_AR, NULL);
1896 				r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,%s", width * 8, src, dst_w);
1897 				break;
1898 			case X86_INS_BTR:
1899 				dst_w = getarg (&gop, 0, 1, "&", DST_R_AR, NULL);
1900 				r_strbuf_appendf (&op->esil, ",%d,%s,%%,1,<<,-1,^,%s", width * 8, src, dst_w);
1901 				break;
1902 			}
1903 		}
1904 		break;
1905 	}
1906 
1907 	if (op->prefix & R_ANAL_OP_PREFIX_REP) {
1908 		r_strbuf_prepend (&op->esil, ",!,?{,BREAK,},");
1909 		r_strbuf_prepend (&op->esil, counter);
1910 		if (repe) {
1911 			r_strbuf_appendf (&op->esil, ",%s,--=,zf,!,?{,BREAK,},0,GOTO", counter);
1912 		} else {
1913 			r_strbuf_appendf (&op->esil, ",%s,--=,0,GOTO", counter);
1914 		}
1915 	}
1916 	if (op->prefix & R_ANAL_OP_PREFIX_REPNE) {
1917 		r_strbuf_prepend (&op->esil, ",!,?{,BREAK,},");
1918 		r_strbuf_prepend (&op->esil, counter);
1919 		r_strbuf_appendf (&op->esil, ",%s,--=,zf,?{,BREAK,},0,GOTO", counter);
1920 	}
1921 }
1922 
cs_reg2reg(RReg * reg,csh * h,int id)1923 static RRegItem *cs_reg2reg(RReg *reg, csh *h, int id) {
1924 	if (id == X86_REG_INVALID) {
1925 		return NULL;
1926 	}
1927 	return r_reg_get (reg, (char *)cs_reg_name (*h, id), -1);
1928 }
1929 
set_access_info(RReg * reg,RAnalOp * op,csh * handle,cs_insn * insn,int mode)1930 static void set_access_info(RReg *reg, RAnalOp *op, csh *handle, cs_insn *insn, int mode) {
1931 	int i;
1932 	RAnalValue *val;
1933 	int regsz;
1934 	x86_reg sp;
1935 	switch (mode) {
1936 	case CS_MODE_64:
1937 		regsz = 8;
1938 		sp = X86_REG_RSP;
1939 		break;
1940 	case CS_MODE_32:
1941 		regsz = 4;
1942 		sp = X86_REG_ESP;
1943 		break;
1944 	case CS_MODE_16:
1945 		regsz = 4;
1946 		sp = X86_REG_ESP;
1947 		break;
1948 	default:
1949 		regsz = 4;
1950 		sp = X86_REG_ESP;
1951 		break;
1952 	}
1953 	RList *ret = r_list_newf ((RListFree)r_anal_value_free);
1954 	if (!ret) {
1955 		return;
1956 	}
1957 
1958 	// PC register
1959 	val = r_anal_value_new ();
1960 	val->type = R_ANAL_VAL_REG;
1961 	val->access = R_ANAL_ACC_W;
1962 	val->reg = cs_reg2reg (reg, handle, X86_REG_RIP);
1963 	r_list_append (ret, val);
1964 
1965 #if CS_API_MAJOR >= 4
1966 	// Register access info
1967 	cs_regs regs_read, regs_write;
1968 	ut8 read_count, write_count;
1969 	if (cs_regs_access (*handle, insn, regs_read, &read_count, regs_write, &write_count) == 0) {
1970 		if (read_count > 0) {
1971 			for (i = 0; i < read_count; i++) {
1972 				val = r_anal_value_new ();
1973 				val->type = R_ANAL_VAL_REG;
1974 				val->access = R_ANAL_ACC_R;
1975 				val->reg = cs_reg2reg (reg, handle, regs_read[i]);
1976 				r_list_append (ret, val);
1977 			}
1978 		}
1979 		if (write_count > 0) {
1980 			for (i = 0; i < write_count; i++) {
1981 				val = r_anal_value_new ();
1982 				val->type = R_ANAL_VAL_REG;
1983 				val->access = R_ANAL_ACC_W;
1984 				val->reg = cs_reg2reg (reg, handle, regs_write[i]);
1985 				r_list_append (ret, val);
1986 			}
1987 		}
1988 	}
1989 #endif
1990 
1991 	switch (insn->id) {
1992 	case X86_INS_PUSH:
1993 		val = r_anal_value_new ();
1994 		val->type = R_ANAL_VAL_MEM;
1995 		val->access = R_ANAL_ACC_W;
1996 		val->reg = cs_reg2reg (reg, handle, sp);
1997 		val->delta = -INSOP(0).size;
1998 		val->memref = INSOP(0).size;
1999 		r_list_append (ret, val);
2000 		break;
2001 	case X86_INS_PUSHAW:
2002 		// AX, CX, DX, BX, SP, BP, SI, DI
2003 		val = r_anal_value_new ();
2004 		val->type = R_ANAL_VAL_MEM;
2005 		val->access = R_ANAL_ACC_W;
2006 		val->reg = cs_reg2reg (reg, handle, sp);
2007 		val->delta = -16;
2008 		val->memref = 16;
2009 		r_list_append (ret, val);
2010 		break;
2011 	case X86_INS_PUSHAL:
2012 		// EAX, ECX, EDX, EBX, EBP, ESP, EBP, ESI, EDI
2013 		val = r_anal_value_new ();
2014 		val->type = R_ANAL_VAL_MEM;
2015 		val->access = R_ANAL_ACC_W;
2016 		val->reg = cs_reg2reg (reg, handle, sp);
2017 		val->delta = -32;
2018 		val->memref = 32;
2019 		r_list_append (ret, val);
2020 		break;
2021 	case X86_INS_PUSHF:
2022 		val = r_anal_value_new ();
2023 		val->type = R_ANAL_VAL_MEM;
2024 		val->access = R_ANAL_ACC_W;
2025 		val->reg = cs_reg2reg (reg, handle, sp);
2026 		val->delta = -2;
2027 		val->memref = 2;
2028 		r_list_append (ret, val);
2029 		break;
2030 	case X86_INS_PUSHFD:
2031 		val = r_anal_value_new ();
2032 		val->type = R_ANAL_VAL_MEM;
2033 		val->access = R_ANAL_ACC_W;
2034 		val->reg = cs_reg2reg (reg, handle, sp);
2035 		val->delta = -4;
2036 		val->memref = 4;
2037 		r_list_append (ret, val);
2038 		break;
2039 	case X86_INS_PUSHFQ:
2040 		val = r_anal_value_new ();
2041 		val->type = R_ANAL_VAL_MEM;
2042 		val->access = R_ANAL_ACC_W;
2043 		val->reg = cs_reg2reg (reg, handle, sp);
2044 		val->delta = -8;
2045 		val->memref = 8;
2046 		r_list_append (ret, val);
2047 		break;
2048 	case X86_INS_CALL:
2049 	case X86_INS_LCALL:
2050 		val = r_anal_value_new ();
2051 		val->type = R_ANAL_VAL_MEM;
2052 		val->access = R_ANAL_ACC_W;
2053 		val->reg = cs_reg2reg (reg, handle, sp);
2054 		val->delta = -regsz;
2055 		val->memref = regsz;
2056 		r_list_append (ret, val);
2057 		break;
2058 	default:
2059 		break;
2060 	}
2061 
2062 	// Memory access info based on operands
2063 	for (i = 0; i < INSOPS; i++) {
2064 		if (INSOP (i).type == X86_OP_MEM) {
2065 			val = r_anal_value_new ();
2066 			val->type = R_ANAL_VAL_MEM;
2067 #if CS_API_MAJOR >= 4
2068 			switch (INSOP (i).access) {
2069 			case CS_AC_READ:
2070 				val->access = R_ANAL_ACC_R;
2071 				break;
2072 			case CS_AC_WRITE:
2073 				val->access = R_ANAL_ACC_W;
2074 				break;
2075 			case CS_AC_INVALID:
2076 				val->access = R_ANAL_ACC_UNKNOWN;
2077 				break;
2078 			}
2079 #else
2080 			val->access = R_ANAL_ACC_UNKNOWN;
2081 #endif
2082 			val->mul = INSOP (i).mem.scale;
2083 			val->delta = INSOP (i).mem.disp;
2084 			if (INSOP(0).mem.base == X86_REG_RIP ||
2085 				INSOP(0).mem.base == X86_REG_EIP) {
2086 				val->delta += insn->size;
2087 			}
2088 			val->memref = INSOP (i).size;
2089 			val->seg = cs_reg2reg (reg, handle, INSOP (i).mem.segment);
2090 			val->reg = cs_reg2reg (reg, handle, INSOP (i).mem.base);
2091 			val->regdelta = cs_reg2reg (reg, handle, INSOP (i).mem.index);
2092 			r_list_append (ret, val);
2093 		}
2094 	}
2095 
2096 	op->access = ret;
2097 }
2098 
2099 #define CREATE_SRC_DST(op) \
2100 	(op)->src[0] = r_anal_value_new (); \
2101 	(op)->src[1] = r_anal_value_new (); \
2102 	(op)->src[2] = r_anal_value_new (); \
2103 	(op)->dst = r_anal_value_new ();
2104 
set_src_dst(RReg * reg,RAnalValue * val,csh * handle,cs_insn * insn,int x)2105 static void set_src_dst(RReg *reg, RAnalValue *val, csh *handle, cs_insn *insn, int x) {
2106 	switch (INSOP (x).type) {
2107 	case X86_OP_MEM:
2108 		val->mul = INSOP (x).mem.scale;
2109 		val->delta = INSOP (x).mem.disp;
2110 		val->memref = INSOP (x).size;
2111 		val->seg = cs_reg2reg (reg, handle, INSOP (x).mem.segment);
2112 		val->reg = cs_reg2reg (reg, handle, INSOP (x).mem.base);
2113 		val->regdelta = cs_reg2reg (reg, handle, INSOP (x).mem.index);
2114 		break;
2115 	case X86_OP_REG:
2116 		val->reg = cs_reg2reg (reg, handle, INSOP (x).reg);
2117 		break;
2118 	case X86_OP_IMM:
2119 		val->imm = INSOP (x).imm;
2120 		break;
2121 	default:
2122 		break;
2123 	}
2124 }
2125 
op_fillval(RAnal * a,RAnalOp * op,csh * handle,cs_insn * insn,int mode)2126 static void op_fillval(RAnal *a, RAnalOp *op, csh *handle, cs_insn *insn, int mode) {
2127 	set_access_info (a->reg, op, handle, insn, mode);
2128 	switch (op->type & R_ANAL_OP_TYPE_MASK) {
2129 	case R_ANAL_OP_TYPE_MOV:
2130 	case R_ANAL_OP_TYPE_CMP:
2131 	case R_ANAL_OP_TYPE_LEA:
2132 	case R_ANAL_OP_TYPE_CMOV:
2133 	case R_ANAL_OP_TYPE_SHL:
2134 	case R_ANAL_OP_TYPE_SHR:
2135 	case R_ANAL_OP_TYPE_SAL:
2136 	case R_ANAL_OP_TYPE_SAR:
2137 	case R_ANAL_OP_TYPE_ROL:
2138 	case R_ANAL_OP_TYPE_ROR:
2139 	case R_ANAL_OP_TYPE_ADD:
2140 	case R_ANAL_OP_TYPE_AND:
2141 	case R_ANAL_OP_TYPE_OR:
2142 	case R_ANAL_OP_TYPE_XOR:
2143 	case R_ANAL_OP_TYPE_SUB:
2144 	case R_ANAL_OP_TYPE_XCHG:
2145 	case R_ANAL_OP_TYPE_POP:
2146 	case R_ANAL_OP_TYPE_NOT:
2147 	case R_ANAL_OP_TYPE_ACMP:
2148 		CREATE_SRC_DST (op);
2149 		set_src_dst (a->reg, op->dst, handle, insn, 0);
2150 		set_src_dst (a->reg, op->src[0], handle, insn, 1);
2151 		set_src_dst (a->reg, op->src[1], handle, insn, 2);
2152 		set_src_dst (a->reg, op->src[2], handle, insn, 3);
2153 		break;
2154 	case R_ANAL_OP_TYPE_UPUSH:
2155 		if ((op->type & R_ANAL_OP_TYPE_REG)) {
2156 			CREATE_SRC_DST (op);
2157 			set_src_dst (a->reg, op->src[0], handle, insn, 0);
2158 		}
2159 		break;
2160 	default:
2161 		break;
2162 	}
2163 }
2164 
op0_memimmhandle(RAnalOp * op,cs_insn * insn,ut64 addr,int regsz)2165 static void op0_memimmhandle(RAnalOp *op, cs_insn *insn, ut64 addr, int regsz) {
2166 	op->ptr = UT64_MAX;
2167 	switch (INSOP(0).type) {
2168 	case X86_OP_MEM:
2169 		op->cycles = CYCLE_MEM;
2170 		op->disp = INSOP(0).mem.disp;
2171 		if (!op->disp) {
2172 			op->disp = UT64_MAX;
2173 		}
2174 		op->refptr = INSOP(0).size;
2175 		if (INSOP(0).mem.base == X86_REG_RIP) {
2176 			op->ptr = addr + insn->size + op->disp;
2177 		} else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
2178 			op->type |= R_ANAL_OP_TYPE_REG;
2179 			op->stackop = R_ANAL_STACK_SET;
2180 			op->stackptr = regsz;
2181 		} else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
2182 			   && INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
2183 			op->ptr = op->disp;
2184 			if (op->ptr < 0x1000) {
2185 				op->ptr = UT64_MAX;
2186 			}
2187 		}
2188 		if (INSOP(1).type == X86_OP_IMM) {
2189 			op->val = INSOP(1).imm;
2190 		}
2191 		break;
2192 	case X86_OP_REG:
2193 		if (INSOP(1).type == X86_OP_IMM) {
2194 		//	(INSOP(0).reg != X86_REG_RSP) && (INSOP(0).reg != X86_REG_ESP)) {
2195 			op->val = INSOP(1).imm;
2196 		}
2197 		break;
2198 	default:
2199 		break;
2200 	}
2201 }
2202 
op1_memimmhandle(RAnalOp * op,cs_insn * insn,ut64 addr,int regsz)2203 static void op1_memimmhandle(RAnalOp *op, cs_insn *insn, ut64 addr, int regsz) {
2204 	if (op->refptr < 1 || op->ptr == UT64_MAX) {
2205 		switch (INSOP(1).type) {
2206 		case X86_OP_MEM:
2207 			op->disp = INSOP(1).mem.disp;
2208 			op->refptr = INSOP(1).size;
2209 			if (INSOP(1).mem.base == X86_REG_RIP) {
2210 				op->ptr = addr + insn->size + op->disp;
2211 			} else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
2212 				op->stackop = R_ANAL_STACK_GET;
2213 				op->stackptr = regsz;
2214 			} else if (INSOP(1).mem.segment == X86_REG_INVALID && INSOP(1).mem.base == X86_REG_INVALID
2215 			           && INSOP(1).mem.index == X86_REG_INVALID && INSOP(1).mem.scale == 1) { // [<addr>]
2216 				op->ptr = op->disp;
2217 			}
2218 			break;
2219 		case X86_OP_IMM:
2220 			if ((INSOP (1).imm > 10) &&
2221 				(INSOP(0).reg != X86_REG_RSP) && (INSOP(0).reg != X86_REG_ESP)) {
2222 				op->ptr = INSOP (1).imm;
2223 			}
2224 			break;
2225 		default:
2226 			break;
2227 		}
2228 	}
2229 }
2230 
op_stackidx(RAnalOp * op,cs_insn * insn,bool minus)2231 static void op_stackidx(RAnalOp *op, cs_insn *insn, bool minus) {
2232 	if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) {
2233 		if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) {
2234 			op->stackop = R_ANAL_STACK_INC;
2235 			if (minus) {
2236 				op->stackptr = -INSOP(1).imm;
2237 			} else {
2238 				op->stackptr = INSOP(1).imm;
2239 			}
2240 		}
2241 	}
2242 }
2243 
set_opdir(RAnalOp * op,cs_insn * insn)2244 static void set_opdir(RAnalOp *op, cs_insn *insn) {
2245 	switch (op->type & R_ANAL_OP_TYPE_MASK) {
2246 	case R_ANAL_OP_TYPE_MOV:
2247 		switch (INSOP(0).type) {
2248 		case X86_OP_MEM:
2249 			op->direction = R_ANAL_OP_DIR_WRITE;
2250 			break;
2251 		case X86_OP_REG:
2252 			if (INSOP(1).type == X86_OP_MEM) {
2253 				op->direction = R_ANAL_OP_DIR_READ;
2254 			}
2255 			break;
2256 		default:
2257 			break;
2258 		}
2259 		break;
2260 	case R_ANAL_OP_TYPE_LEA:
2261 		op->direction = R_ANAL_OP_DIR_REF;
2262 		break;
2263 	case R_ANAL_OP_TYPE_CALL:
2264 	case R_ANAL_OP_TYPE_JMP:
2265 	case R_ANAL_OP_TYPE_UJMP:
2266 	case R_ANAL_OP_TYPE_UCALL:
2267 		op->direction = R_ANAL_OP_DIR_EXEC;
2268 		break;
2269 	default:
2270 		break;
2271 	}
2272 }
2273 
anop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)2274 static void anop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
2275 	struct Getarg gop = {
2276 		.handle = *handle,
2277 		.insn = insn,
2278 		.bits = a->bits
2279 	};
2280 	int regsz = 4;
2281 	switch (a->bits) {
2282 	case 64: regsz = 8; break;
2283 	case 16: regsz = 2; break;
2284 	default: regsz = 4; break; // 32
2285 	}
2286 	switch (insn->id) {
2287 	case X86_INS_FNOP:
2288 		op->family = R_ANAL_OP_FAMILY_FPU;
2289 		/* fallthru */
2290 	case X86_INS_NOP:
2291 	case X86_INS_PAUSE:
2292 		op->type = R_ANAL_OP_TYPE_NOP;
2293 		break;
2294 	case X86_INS_HLT:
2295 		op->type = R_ANAL_OP_TYPE_TRAP;
2296 		break;
2297 	case X86_INS_FBLD:
2298 	case X86_INS_FBSTP:
2299 	case X86_INS_FCOMPP:
2300 	case X86_INS_FDECSTP:
2301 	case X86_INS_FEMMS:
2302 	case X86_INS_FFREE:
2303 	case X86_INS_FICOM:
2304 	case X86_INS_FICOMP:
2305 	case X86_INS_FINCSTP:
2306 	case X86_INS_FNCLEX:
2307 	case X86_INS_FNINIT:
2308 	case X86_INS_FNSTCW:
2309 	case X86_INS_FNSTSW:
2310 	case X86_INS_FPATAN:
2311 	case X86_INS_FPREM:
2312 	case X86_INS_FPREM1:
2313 	case X86_INS_FPTAN:
2314 #if CS_API_MAJOR >= 4
2315 	case X86_INS_FFREEP:
2316 #endif
2317 	case X86_INS_FRNDINT:
2318 	case X86_INS_FRSTOR:
2319 	case X86_INS_FNSAVE:
2320 	case X86_INS_FSCALE:
2321 	case X86_INS_FSETPM:
2322 	case X86_INS_FSINCOS:
2323 	case X86_INS_FNSTENV:
2324 	case X86_INS_FXAM:
2325 	case X86_INS_FXSAVE:
2326 	case X86_INS_FXSAVE64:
2327 	case X86_INS_FXTRACT:
2328 	case X86_INS_FYL2X:
2329 	case X86_INS_FYL2XP1:
2330 	case X86_INS_FISTTP:
2331 	case X86_INS_FSQRT:
2332 	case X86_INS_FXCH:
2333 		op->family = R_ANAL_OP_FAMILY_FPU;
2334 		op->type = R_ANAL_OP_TYPE_STORE;
2335 		break;
2336 	case X86_INS_FTST:
2337 	case X86_INS_FUCOMI:
2338 	case X86_INS_FUCOMPP:
2339 	case X86_INS_FUCOMP:
2340 	case X86_INS_FUCOM:
2341 		op->family = R_ANAL_OP_FAMILY_FPU;
2342 		op->type = R_ANAL_OP_TYPE_CMP;
2343 		break;
2344 	case X86_INS_BT:
2345 	case X86_INS_BTC:
2346 	case X86_INS_BTR:
2347 	case X86_INS_BTS:
2348 		op->type = R_ANAL_OP_TYPE_CMP;
2349 		break;
2350 	case X86_INS_FABS:
2351 		op->type = R_ANAL_OP_TYPE_ABS;
2352 		op->family = R_ANAL_OP_FAMILY_FPU;
2353 		break;
2354 	case X86_INS_FLDCW:
2355 	case X86_INS_FLDENV:
2356 	case X86_INS_FLDL2E:
2357 	case X86_INS_FLDL2T:
2358 	case X86_INS_FLDLG2:
2359 	case X86_INS_FLDLN2:
2360 	case X86_INS_FLDPI:
2361 	case X86_INS_FLDZ:
2362 	case X86_INS_FLD1:
2363 	case X86_INS_FLD:
2364 		op->type = R_ANAL_OP_TYPE_LOAD;
2365 		op->family = R_ANAL_OP_FAMILY_FPU;
2366 		break;
2367 	case X86_INS_FIST:
2368 	case X86_INS_FISTP:
2369 	case X86_INS_FST:
2370 	case X86_INS_FSTP:
2371 	case X86_INS_FSTPNCE:
2372 	case X86_INS_FXRSTOR:
2373 	case X86_INS_FXRSTOR64:
2374 		op->type = R_ANAL_OP_TYPE_STORE;
2375 		op->family = R_ANAL_OP_FAMILY_FPU;
2376 		break;
2377 	case X86_INS_FDIV:
2378 	case X86_INS_FIDIV:
2379 	case X86_INS_FDIVP:
2380 	case X86_INS_FDIVR:
2381 	case X86_INS_FIDIVR:
2382 	case X86_INS_FDIVRP:
2383 		op->type = R_ANAL_OP_TYPE_DIV;
2384 		op->family = R_ANAL_OP_FAMILY_FPU;
2385 		break;
2386 	case X86_INS_FSUBR:
2387 	case X86_INS_FISUBR:
2388 	case X86_INS_FSUBRP:
2389 	case X86_INS_FSUB:
2390 	case X86_INS_FISUB:
2391 	case X86_INS_FSUBP:
2392 		op->type = R_ANAL_OP_TYPE_SUB;
2393 		op->family = R_ANAL_OP_FAMILY_FPU;
2394 		break;
2395 	case X86_INS_FMUL:
2396 	case X86_INS_FIMUL:
2397 	case X86_INS_FMULP:
2398 		op->type = R_ANAL_OP_TYPE_MUL;
2399 		op->family = R_ANAL_OP_FAMILY_FPU;
2400 		break;
2401 	case X86_INS_CLI:
2402 	case X86_INS_STI:
2403 		op->type = R_ANAL_OP_TYPE_MOV;
2404 		op->family = R_ANAL_OP_FAMILY_PRIV;
2405 		break;
2406 	case X86_INS_CLC:
2407 	case X86_INS_STC:
2408 	case X86_INS_CLAC:
2409 	case X86_INS_CLGI:
2410 	case X86_INS_CLTS:
2411 #if CS_API_MAJOR >= 4
2412 	case X86_INS_CLWB:
2413 #endif
2414 	case X86_INS_STAC:
2415 	case X86_INS_STGI:
2416 		op->type = R_ANAL_OP_TYPE_MOV;
2417 		break;
2418 	// cmov
2419 	case X86_INS_SETNE:
2420 	case X86_INS_SETNO:
2421 	case X86_INS_SETNP:
2422 	case X86_INS_SETNS:
2423 	case X86_INS_SETO:
2424 	case X86_INS_SETP:
2425 	case X86_INS_SETS:
2426 	case X86_INS_SETL:
2427 	case X86_INS_SETLE:
2428 	case X86_INS_SETB:
2429 	case X86_INS_SETG:
2430 	case X86_INS_SETAE:
2431 	case X86_INS_SETA:
2432 	case X86_INS_SETBE:
2433 	case X86_INS_SETE:
2434 	case X86_INS_SETGE:
2435 		op->type = R_ANAL_OP_TYPE_CMOV;
2436 		op->family = 0;
2437 		break;
2438 	// cmov
2439 	case X86_INS_FCMOVBE:
2440 	case X86_INS_FCMOVB:
2441 	case X86_INS_FCMOVNBE:
2442 	case X86_INS_FCMOVNB:
2443 	case X86_INS_FCMOVE:
2444 	case X86_INS_FCMOVNE:
2445 	case X86_INS_FCMOVNU:
2446 	case X86_INS_FCMOVU:
2447 		op->family = R_ANAL_OP_FAMILY_FPU;
2448 		op->type = R_ANAL_OP_TYPE_CMOV;
2449 		break;
2450 	case X86_INS_CMOVA:
2451 	case X86_INS_CMOVAE:
2452 	case X86_INS_CMOVB:
2453 	case X86_INS_CMOVBE:
2454 	case X86_INS_CMOVE:
2455 	case X86_INS_CMOVG:
2456 	case X86_INS_CMOVGE:
2457 	case X86_INS_CMOVL:
2458 	case X86_INS_CMOVLE:
2459 	case X86_INS_CMOVNE:
2460 	case X86_INS_CMOVNO:
2461 	case X86_INS_CMOVNP:
2462 	case X86_INS_CMOVNS:
2463 	case X86_INS_CMOVO:
2464 	case X86_INS_CMOVP:
2465 	case X86_INS_CMOVS:
2466 		op->type = R_ANAL_OP_TYPE_CMOV;
2467 		break;
2468 	case X86_INS_STOSB:
2469 	case X86_INS_STOSD:
2470 	case X86_INS_STOSQ:
2471 	case X86_INS_STOSW:
2472 		op->type = R_ANAL_OP_TYPE_STORE;
2473 		break;
2474 	case X86_INS_LODSB:
2475 	case X86_INS_LODSD:
2476 	case X86_INS_LODSQ:
2477 	case X86_INS_LODSW:
2478 		op->type = R_ANAL_OP_TYPE_LOAD;
2479 		break;
2480 	case X86_INS_PALIGNR:
2481 	case X86_INS_VALIGND:
2482 	case X86_INS_VALIGNQ:
2483 	case X86_INS_VPALIGNR:
2484 		op->type = R_ANAL_OP_TYPE_AND;
2485 		op->family = R_ANAL_OP_FAMILY_CPU;
2486 		break;
2487 	case X86_INS_CPUID:
2488 		op->type = R_ANAL_OP_TYPE_MOV;
2489 		op->family = R_ANAL_OP_FAMILY_CPU;
2490 		break;
2491 	case X86_INS_SFENCE:
2492 	case X86_INS_LFENCE:
2493 	case X86_INS_MFENCE:
2494 		op->type = R_ANAL_OP_TYPE_NOP;
2495 		op->family = R_ANAL_OP_FAMILY_THREAD;
2496 		break;
2497 	// mov
2498 	case X86_INS_MOVNTQ:
2499 	case X86_INS_MOVNTDQA:
2500 	case X86_INS_MOVNTDQ:
2501 	case X86_INS_MOVNTI:
2502 	case X86_INS_MOVNTPD:
2503 	case X86_INS_MOVNTPS:
2504 	case X86_INS_MOVNTSD:
2505 	case X86_INS_MOVNTSS:
2506 	case X86_INS_VMOVNTDQA:
2507 	case X86_INS_VMOVNTDQ:
2508 	case X86_INS_VMOVNTPD:
2509 	case X86_INS_VMOVNTPS:
2510 		op->type = R_ANAL_OP_TYPE_MOV;
2511 		op->family = R_ANAL_OP_FAMILY_SSE;
2512 		break;
2513 	case X86_INS_PCMPEQB:
2514 	case X86_INS_PCMPEQD:
2515 	case X86_INS_PCMPEQW:
2516 	case X86_INS_PCMPGTB:
2517 	case X86_INS_PCMPGTD:
2518 	case X86_INS_PCMPGTW:
2519 	case X86_INS_PCMPEQQ:
2520 	case X86_INS_PCMPESTRI:
2521 	case X86_INS_PCMPESTRM:
2522 	case X86_INS_PCMPGTQ:
2523 	case X86_INS_PCMPISTRI:
2524 	case X86_INS_PCMPISTRM:
2525 #if CS_API_MAJOR >= 4
2526 	case X86_INS_VPCMPB:
2527 #endif
2528 	case X86_INS_VPCMPD:
2529 	case X86_INS_VPCMPEQB:
2530 	case X86_INS_VPCMPEQD:
2531 	case X86_INS_VPCMPEQQ:
2532 	case X86_INS_VPCMPEQW:
2533 	case X86_INS_VPCMPESTRI:
2534 	case X86_INS_VPCMPESTRM:
2535 	case X86_INS_VPCMPGTB:
2536 	case X86_INS_VPCMPGTD:
2537 	case X86_INS_VPCMPGTQ:
2538 	case X86_INS_VPCMPGTW:
2539 	case X86_INS_VPCMPISTRI:
2540 	case X86_INS_VPCMPISTRM:
2541 	case X86_INS_VPCMPQ:
2542 #if CS_API_MAJOR >= 4
2543 	case X86_INS_VPCMPUB:
2544 #endif
2545 	case X86_INS_VPCMPUD:
2546 	case X86_INS_VPCMPUQ:
2547 #if CS_API_MAJOR >= 4
2548 	case X86_INS_VPCMPUW:
2549 	case X86_INS_VPCMPW:
2550 #endif
2551 		op->type = R_ANAL_OP_TYPE_CMP;
2552 		op->family = R_ANAL_OP_FAMILY_SSE;
2553 		break;
2554 	case X86_INS_MOVSS:
2555 	case X86_INS_MOV:
2556 	case X86_INS_MOVAPS:
2557 	case X86_INS_MOVAPD:
2558 	case X86_INS_MOVZX:
2559 	case X86_INS_MOVUPS:
2560 	case X86_INS_MOVABS:
2561 	case X86_INS_MOVHPD:
2562 	case X86_INS_MOVHPS:
2563 	case X86_INS_MOVLPD:
2564 	case X86_INS_MOVLPS:
2565 	case X86_INS_MOVBE:
2566 	case X86_INS_MOVSB:
2567 	case X86_INS_MOVSD:
2568 	case X86_INS_MOVSQ:
2569 	case X86_INS_MOVSX:
2570 	case X86_INS_MOVSXD:
2571 	case X86_INS_MOVSW:
2572 	case X86_INS_MOVD:
2573 	case X86_INS_MOVQ:
2574 	case X86_INS_MOVDQ2Q:
2575 		{
2576 		op->type = R_ANAL_OP_TYPE_MOV;
2577 		op0_memimmhandle (op, insn, addr, regsz);
2578 		op1_memimmhandle (op, insn, addr, regsz);
2579 		}
2580 		break;
2581 	case X86_INS_ROL:
2582 	case X86_INS_RCL:
2583 		// TODO: RCL Still does not work as intended
2584 		//  - Set flags
2585 		op->type = R_ANAL_OP_TYPE_ROL;
2586 		break;
2587 	case X86_INS_ROR:
2588 	case X86_INS_RCR:
2589 		// TODO: RCR Still does not work as intended
2590 		//  - Set flags
2591 		op->type = R_ANAL_OP_TYPE_ROR;
2592 		break;
2593 	case X86_INS_SHL:
2594 	case X86_INS_SHLD:
2595 	case X86_INS_SHLX:
2596 		// TODO: Set CF: Carry flag is the last bit shifted out due to
2597 		// this operation. It is undefined for SHL and SHR where the
2598 		// number of bits shifted is greater than the size of the
2599 		// destination.
2600 		op->type = R_ANAL_OP_TYPE_SHL;
2601 		break;
2602 	case X86_INS_SAR:
2603 	case X86_INS_SARX:
2604 		// TODO: Set CF. See case X86_INS_SHL for more details.
2605 		op->type = R_ANAL_OP_TYPE_SAR;
2606 		break;
2607 	case X86_INS_SAL:
2608 		// TODO: Set CF: See case X86_INS_SAL for more details.
2609 		op->type = R_ANAL_OP_TYPE_SAL;
2610 		break;
2611 	case X86_INS_SALC:
2612 		op->type = R_ANAL_OP_TYPE_SAL;
2613 		break;
2614 	case X86_INS_SHR:
2615 	case X86_INS_SHRD:
2616 	case X86_INS_SHRX:
2617 		// TODO: Set CF: See case X86_INS_SAL for more details.
2618 		op->type = R_ANAL_OP_TYPE_SHR;
2619 		op->val = INSOP(1).imm;
2620 		// XXX this should be op->imm
2621 		//op->src[0] = r_anal_value_new ();
2622 		//op->src[0]->imm = INSOP(1).imm;
2623 		break;
2624 	case X86_INS_CMP:
2625 	case X86_INS_CMPPD:
2626 	case X86_INS_CMPPS:
2627 	case X86_INS_CMPSW:
2628 	case X86_INS_CMPSD:
2629 	case X86_INS_CMPSQ:
2630 	case X86_INS_CMPSB:
2631 	case X86_INS_CMPSS:
2632 	case X86_INS_TEST:
2633 		if (insn->id == X86_INS_TEST) {
2634 			op->type = R_ANAL_OP_TYPE_ACMP;					//compare via and
2635 		} else {
2636 			op->type = R_ANAL_OP_TYPE_CMP;
2637 		}
2638 		switch (INSOP(0).type) {
2639 		case X86_OP_MEM:
2640 			op->disp = INSOP(0).mem.disp;
2641 			op->refptr = INSOP(0).size;
2642 			if (INSOP(0).mem.base == X86_REG_RIP) {
2643 				op->ptr = addr + insn->size + op->disp;
2644 			} else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) {
2645 				op->stackop = R_ANAL_STACK_SET;
2646 				op->stackptr = regsz;
2647 				op->type |= R_ANAL_OP_TYPE_REG;
2648 			} else if (INSOP(0).mem.segment == X86_REG_INVALID && INSOP(0).mem.base == X86_REG_INVALID
2649 			           && INSOP(0).mem.index == X86_REG_INVALID && INSOP(0).mem.scale == 1) { // [<addr>]
2650 				op->ptr = op->disp;
2651 			}
2652 			if (INSOP(1).type == X86_OP_IMM) {
2653 				op->val = INSOP(1).imm;
2654 			}
2655 			break;
2656 		default:
2657 			switch (INSOP(1).type) {
2658 			case X86_OP_MEM:
2659 				op->disp = INSOP(1).mem.disp;
2660 				op->refptr = INSOP(1).size;
2661 				if (INSOP(1).mem.base == X86_REG_RIP) {
2662 					op->ptr = addr + insn->size + op->disp;;
2663 				} else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) {
2664 					op->type |= R_ANAL_OP_TYPE_REG;
2665 					op->stackop = R_ANAL_STACK_SET;
2666 					op->stackptr = regsz;
2667 				} else if (INSOP(1).mem.segment == X86_REG_INVALID
2668 				           && INSOP(1).mem.base == X86_REG_INVALID
2669 				           && INSOP(1).mem.index == X86_REG_INVALID
2670 				           && INSOP(1).mem.scale == 1) { // [<addr>]
2671 					op->ptr = op->disp;
2672 				}
2673 				if (INSOP(0).type == X86_OP_IMM) {
2674 					op->val = INSOP(0).imm;
2675 				}
2676 				break;
2677 			case X86_OP_IMM:
2678 				op->val = op->ptr = INSOP(1).imm;
2679 				break;
2680 			default:
2681 				break;
2682 			}
2683 			break;
2684 		}
2685 		break;
2686 	case X86_INS_LEA:
2687 		op->type = R_ANAL_OP_TYPE_LEA;
2688 		switch (INSOP(1).type) {
2689 		case X86_OP_MEM:
2690 			// op->type = R_ANAL_OP_TYPE_ULEA;
2691 			op->disp = INSOP(1).mem.disp;
2692 			op->refptr = INSOP(1).size;
2693 			switch (INSOP(1).mem.base) {
2694 			case X86_REG_RIP:
2695 				op->ptr = addr + op->size + op->disp;
2696 				break;
2697 			case X86_REG_RBP:
2698 			case X86_REG_EBP:
2699 				op->stackop = R_ANAL_STACK_GET;
2700 				op->stackptr = regsz;
2701 				break;
2702 			default:
2703 				/* unhandled */
2704 				break;
2705 			}
2706 			break;
2707 		case X86_OP_IMM:
2708 			if (INSOP(1).imm > 10) {
2709 				op->ptr = INSOP(1).imm;
2710 			}
2711 			break;
2712 		default:
2713 			break;
2714 		}
2715 		break;
2716 	case X86_INS_PUSHAW:
2717 	// pushal, popal - push/pop EAX,EBX,ECX,EDX,ESP,EBP,ESI,EDI
2718 	case X86_INS_PUSHAL:
2719 		op->ptr = UT64_MAX;
2720 		op->type = R_ANAL_OP_TYPE_UPUSH;
2721 		op->stackop = R_ANAL_STACK_INC;
2722 		op->stackptr = regsz * 8;
2723 		break;
2724 	case X86_INS_ENTER:
2725 	case X86_INS_PUSH:
2726 	case X86_INS_PUSHF:
2727 	case X86_INS_PUSHFD:
2728 	case X86_INS_PUSHFQ:
2729 		switch (INSOP(0).type) {
2730 		case X86_OP_MEM:
2731 			if (INSOP(0).mem.disp && !INSOP(0).mem.base && !INSOP(0).mem.index) {
2732 				op->val = op->ptr = INSOP(0).mem.disp;
2733 				op->type = R_ANAL_OP_TYPE_PUSH;
2734 			} else {
2735 				op->type = R_ANAL_OP_TYPE_UPUSH;
2736 			}
2737 			op->cycles = CYCLE_REG + CYCLE_MEM;
2738 			break;
2739 		case X86_OP_IMM:
2740 			op->val = op->ptr = INSOP(0).imm;
2741 			op->type = R_ANAL_OP_TYPE_PUSH;
2742 			op->cycles = CYCLE_REG + CYCLE_MEM;
2743 			break;
2744 		case X86_OP_REG:
2745 			op->type = R_ANAL_OP_TYPE_RPUSH;
2746 			op->cycles = CYCLE_REG + CYCLE_MEM;
2747 			break;
2748 		default:
2749 			op->type = R_ANAL_OP_TYPE_UPUSH;
2750 			op->cycles = CYCLE_MEM + CYCLE_MEM;
2751 			break;
2752 		}
2753 		op->stackop = R_ANAL_STACK_INC;
2754 		op->stackptr = regsz;
2755 		break;
2756 	case X86_INS_LEAVE:
2757 		op->type = R_ANAL_OP_TYPE_POP;
2758 		op->stackop = R_ANAL_STACK_INC;
2759 		op->stackptr = -regsz;
2760 		break;
2761 	case X86_INS_POP:
2762 	case X86_INS_POPF:
2763 	case X86_INS_POPFD:
2764 	case X86_INS_POPFQ:
2765 		op->type = R_ANAL_OP_TYPE_POP;
2766 		op->stackop = R_ANAL_STACK_INC;
2767 		op->stackptr = -regsz;
2768 		break;
2769 	case X86_INS_POPAW:
2770 	case X86_INS_POPAL:
2771 		op->type = R_ANAL_OP_TYPE_POP;
2772 		op->stackop = R_ANAL_STACK_INC;
2773 		op->stackptr = -regsz * 8;
2774 		break;
2775 	case X86_INS_IRET:
2776 	case X86_INS_IRETD:
2777 	case X86_INS_IRETQ:
2778 	case X86_INS_SYSRET:
2779 		op->family = R_ANAL_OP_FAMILY_PRIV;
2780 		/* fallthrough */
2781 	case X86_INS_RET:
2782 	case X86_INS_RETF:
2783 	case X86_INS_RETFQ:
2784 		op->type = R_ANAL_OP_TYPE_RET;
2785 		op->stackop = R_ANAL_STACK_INC;
2786 		op->stackptr = -regsz;
2787 		op->cycles = CYCLE_MEM + CYCLE_JMP;
2788 		break;
2789 #if CS_API_MAJOR >= 4
2790 	case X86_INS_UD0:
2791 #endif
2792 	case X86_INS_UD2:
2793 #if CS_API_MAJOR == 4
2794 	case X86_INS_UD2B:
2795 #endif
2796 	case X86_INS_INT3:
2797 		op->type = R_ANAL_OP_TYPE_TRAP; // TRAP
2798 		break;
2799 	case X86_INS_INT1:
2800 		op->type = R_ANAL_OP_TYPE_SWI;
2801 		op->val = 1;
2802 		break;
2803 	case X86_INS_INT:
2804 		op->type = R_ANAL_OP_TYPE_SWI;
2805 		op->val = (int)INSOP(0).imm;
2806 		break;
2807 	case X86_INS_SYSCALL:
2808 	case X86_INS_SYSENTER:
2809 		op->type = R_ANAL_OP_TYPE_SWI;
2810 		op->cycles = CYCLE_JMP;
2811 		break;
2812 	case X86_INS_SYSEXIT:
2813 		op->type = R_ANAL_OP_TYPE_SWI;
2814 		op->family = R_ANAL_OP_FAMILY_PRIV;
2815 		break;
2816 	case X86_INS_INTO:
2817 		op->type = R_ANAL_OP_TYPE_SWI;
2818 		// int4 if overflow bit is set , so this is an optional swi
2819 		op->type |= R_ANAL_OP_TYPE_COND;
2820 		break;
2821 	case X86_INS_VMCALL:
2822 	case X86_INS_VMMCALL:
2823 		op->type = R_ANAL_OP_TYPE_TRAP;
2824 		break;
2825 	case X86_INS_JL:
2826 	case X86_INS_JLE:
2827 	case X86_INS_JA:
2828 	case X86_INS_JAE:
2829 	case X86_INS_JB:
2830 	case X86_INS_JBE:
2831 	case X86_INS_JCXZ:
2832 	case X86_INS_JECXZ:
2833 	case X86_INS_JRCXZ:
2834 	case X86_INS_JO:
2835 	case X86_INS_JNO:
2836 	case X86_INS_JS:
2837 	case X86_INS_JNS:
2838 	case X86_INS_JP:
2839 	case X86_INS_JNP:
2840 	case X86_INS_JE:
2841 	case X86_INS_JNE:
2842 	case X86_INS_JG:
2843 	case X86_INS_JGE:
2844 	case X86_INS_LOOP:
2845 	case X86_INS_LOOPE:
2846 	case X86_INS_LOOPNE:
2847 		op->type = R_ANAL_OP_TYPE_CJMP;
2848 		op->jump = INSOP(0).imm;
2849 		op->fail = addr + op->size;
2850 		op->cycles = CYCLE_JMP;
2851 		switch (insn->id) {
2852 		case X86_INS_JL:
2853 		case X86_INS_JLE:
2854 		case X86_INS_JS:
2855 		case X86_INS_JG:
2856 		case X86_INS_JGE:
2857 			op->sign = true;
2858 			break;
2859 		}
2860 		break;
2861 	case X86_INS_CALL:
2862 	case X86_INS_LCALL:
2863 		op->cycles = CYCLE_JMP + CYCLE_MEM;
2864 		switch (INSOP(0).type) {
2865 		case X86_OP_IMM:
2866 			op->type = R_ANAL_OP_TYPE_CALL;
2867 			// TODO: what if UCALL?
2868 			if (INSOP(1).type == X86_OP_IMM) {
2869 				ut64 seg = INSOP(0).imm;
2870 				ut64 off = INSOP(1).imm;
2871 				op->ptr = INSOP (0).mem.disp;
2872 				op->jump = (seg << a->seggrn) + off;
2873 			} else {
2874 				op->jump = INSOP(0).imm;
2875 			}
2876 			op->fail = addr + op->size;
2877 			break;
2878 		case X86_OP_MEM:
2879 			op->type = R_ANAL_OP_TYPE_UCALL;
2880 			op->jump = UT64_MAX;
2881 			op->ptr = INSOP (0).mem.disp;
2882 			op->disp = INSOP (0).mem.disp;
2883 			op->reg = NULL;
2884 			op->ireg = NULL;
2885 			op->cycles += CYCLE_MEM;
2886 			if (INSOP (0).mem.index == X86_REG_INVALID) {
2887 				if (INSOP (0).mem.base != X86_REG_INVALID) {
2888 					op->reg = cs_reg_name (*handle, INSOP (0).mem.base);
2889 					op->type = R_ANAL_OP_TYPE_IRCALL;
2890 				}
2891 			} else {
2892 				op->ireg = cs_reg_name (*handle, INSOP (0).mem.index);
2893 				op->scale = INSOP(0).mem.scale;
2894 			}
2895 			if (INSOP (0).mem.base == X86_REG_RIP) {
2896 				op->ptr += addr + insn->size;
2897 				op->refptr = 8;
2898 			}
2899 			break;
2900 		case X86_OP_REG:
2901 			op->reg = cs_reg_name (*handle, INSOP (0).reg);
2902 			op->type = R_ANAL_OP_TYPE_RCALL;
2903 			op->ptr = UT64_MAX;
2904 			op->cycles += CYCLE_REG;
2905 			break;
2906 		default:
2907 			op->type = R_ANAL_OP_TYPE_UCALL;
2908 			op->jump = UT64_MAX;
2909 			break;
2910 		}
2911 		break;
2912 	case X86_INS_JMP:
2913 	case X86_INS_LJMP:
2914 		// TODO: what if UJMP?
2915 		switch (INSOP(0).type) {
2916 		case X86_OP_IMM:
2917 			if (INSOP(1).type == X86_OP_IMM) {
2918 				ut64 seg = INSOP(0).imm;
2919 				ut64 off = INSOP(1).imm;
2920 				op->ptr = INSOP (0).mem.disp;
2921 				op->jump = (seg << a->seggrn) + off;
2922 			} else {
2923 				op->jump = INSOP(0).imm;
2924 			}
2925 			op->type = R_ANAL_OP_TYPE_JMP;
2926 			op->cycles = CYCLE_JMP;
2927 			break;
2928 		case X86_OP_MEM:
2929 			// op->type = R_ANAL_OP_TYPE_UJMP;
2930 			op->type = R_ANAL_OP_TYPE_MJMP;
2931 			op->ptr = INSOP (0).mem.disp;
2932 			op->disp = INSOP (0).mem.disp;
2933 			op->reg = NULL;
2934 			op->ireg = NULL;
2935 			op->cycles = CYCLE_JMP + CYCLE_MEM;
2936 			if (INSOP(0).mem.base != X86_REG_INVALID) {
2937 				if (INSOP (0).mem.base != X86_REG_INVALID) {
2938 					op->reg = cs_reg_name (*handle, INSOP (0).mem.base);
2939 					op->type = R_ANAL_OP_TYPE_IRJMP;
2940 				}
2941 			}
2942 			if (INSOP (0).mem.index == X86_REG_INVALID) {
2943 				op->ireg = NULL;
2944 			} else {
2945 				op->type = R_ANAL_OP_TYPE_UJMP;
2946 				op->ireg = cs_reg_name (*handle, INSOP (0).mem.index);
2947 				op->scale = INSOP (0).mem.scale;
2948 			}
2949 			if (INSOP(0).mem.base == X86_REG_RIP) {
2950 				op->ptr += addr + insn->size;
2951 				op->refptr = 8;
2952 			}
2953 			break;
2954 		case X86_OP_REG:
2955 			{
2956 			op->cycles = CYCLE_JMP + CYCLE_REG;
2957 			op->reg = cs_reg_name (gop.handle, INSOP(0).reg);
2958 			op->type = R_ANAL_OP_TYPE_RJMP;
2959 			op->ptr = UT64_MAX;
2960 			}
2961 			break;
2962 		//case X86_OP_FP:
2963 		default: // other?
2964 			op->type = R_ANAL_OP_TYPE_UJMP;
2965 			op->ptr = UT64_MAX;
2966 			break;
2967 		}
2968 		break;
2969 	case X86_INS_IN:
2970 	case X86_INS_INSW:
2971 	case X86_INS_INSD:
2972 	case X86_INS_INSB:
2973 		op->type = R_ANAL_OP_TYPE_IO;
2974 		op->type2 = 0;
2975 		break;
2976 	case X86_INS_OUT:
2977 	case X86_INS_OUTSB:
2978 	case X86_INS_OUTSD:
2979 	case X86_INS_OUTSW:
2980 		op->type = R_ANAL_OP_TYPE_IO;
2981 		op->type2 = 1;
2982 		break;
2983 	case X86_INS_VXORPD:
2984 	case X86_INS_VXORPS:
2985 	case X86_INS_VPXORD:
2986 	case X86_INS_VPXORQ:
2987 	case X86_INS_VPXOR:
2988 	case X86_INS_XORPS:
2989 	case X86_INS_KXORW:
2990 	case X86_INS_PXOR:
2991 		op->type = R_ANAL_OP_TYPE_XOR;
2992 		break;
2993 	case X86_INS_XOR:
2994 		op->type = R_ANAL_OP_TYPE_XOR;
2995 		// TODO: Add stack indexing handling chang
2996 		op0_memimmhandle (op, insn, addr, regsz);
2997 		op1_memimmhandle (op, insn, addr, regsz);
2998 		break;
2999 	case X86_INS_OR:
3000 		// The OF and CF flags are cleared; the SF, ZF, and PF flags are
3001 		// set according to the result. The state of the AF flag is
3002 		// undefined.
3003 		op->type = R_ANAL_OP_TYPE_OR;
3004 		// TODO: Add stack indexing handling chang
3005 		op0_memimmhandle (op, insn, addr, regsz);
3006 		op1_memimmhandle (op, insn, addr, regsz);
3007 		break;
3008 	case X86_INS_INC:
3009 		// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
3010 		// are set according to the result.
3011 		op->type = R_ANAL_OP_TYPE_ADD;
3012 		op->val = 1;
3013 		break;
3014 	case X86_INS_DEC:
3015 		// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
3016 		// are set according to the result.
3017 		op->type = R_ANAL_OP_TYPE_SUB;
3018 		op->val = 1;
3019 		break;
3020 	case X86_INS_NEG:
3021 		op->type = R_ANAL_OP_TYPE_SUB;
3022 		op->family = R_ANAL_OP_FAMILY_CPU;
3023 		break;
3024 	case X86_INS_NOT:
3025 		op->type = R_ANAL_OP_TYPE_NOT;
3026 		op->family = R_ANAL_OP_FAMILY_CPU;
3027 		break;
3028 	case X86_INS_PSUBB:
3029 	case X86_INS_PSUBW:
3030 	case X86_INS_PSUBD:
3031 	case X86_INS_PSUBQ:
3032 	case X86_INS_PSUBSB:
3033 	case X86_INS_PSUBSW:
3034 	case X86_INS_PSUBUSB:
3035 	case X86_INS_PSUBUSW:
3036 		op->type = R_ANAL_OP_TYPE_SUB;
3037 		break;
3038 	case X86_INS_SUB:
3039 		op->type = R_ANAL_OP_TYPE_SUB;
3040 		op_stackidx (op, insn, false);
3041 		op0_memimmhandle (op, insn, addr, regsz);
3042 		op1_memimmhandle (op, insn, addr, regsz);
3043 		break;
3044 	case X86_INS_SBB:
3045 		// dst = dst - (src + cf)
3046 		op->type = R_ANAL_OP_TYPE_SUB;
3047 		break;
3048 	case X86_INS_LIDT:
3049 		op->type = R_ANAL_OP_TYPE_LOAD;
3050 		op->family = R_ANAL_OP_FAMILY_PRIV;
3051 		break;
3052 	case X86_INS_SIDT:
3053 		op->type = R_ANAL_OP_TYPE_STORE;
3054 		op->family = R_ANAL_OP_FAMILY_PRIV;
3055 		break;
3056 	case X86_INS_RDRAND:
3057 	case X86_INS_RDSEED:
3058 	case X86_INS_RDMSR:
3059 	case X86_INS_RDPMC:
3060 	case X86_INS_RDTSC:
3061 	case X86_INS_RDTSCP:
3062 	case X86_INS_CRC32:
3063 	case X86_INS_SHA1MSG1:
3064 	case X86_INS_SHA1MSG2:
3065 	case X86_INS_SHA1NEXTE:
3066 	case X86_INS_SHA1RNDS4:
3067 	case X86_INS_SHA256MSG1:
3068 	case X86_INS_SHA256MSG2:
3069 	case X86_INS_SHA256RNDS2:
3070 	case X86_INS_AESDECLAST:
3071 	case X86_INS_AESDEC:
3072 	case X86_INS_AESENCLAST:
3073 	case X86_INS_AESENC:
3074 	case X86_INS_AESIMC:
3075 	case X86_INS_AESKEYGENASSIST:
3076 		// AES instructions
3077 		op->family = R_ANAL_OP_FAMILY_CRYPTO;
3078 		op->type = R_ANAL_OP_TYPE_MOV; // XXX
3079 		break;
3080 	case X86_INS_ANDN:
3081 	case X86_INS_ANDPD:
3082 	case X86_INS_ANDPS:
3083 	case X86_INS_ANDNPD:
3084 	case X86_INS_ANDNPS:
3085 		op->type = R_ANAL_OP_TYPE_AND;
3086 		break;
3087 	case X86_INS_AND:
3088 		op->type = R_ANAL_OP_TYPE_AND;
3089 		// TODO: Add stack register change operation
3090 		op0_memimmhandle (op, insn, addr, regsz);
3091 		op1_memimmhandle (op, insn, addr, regsz);
3092 		break;
3093 	case X86_INS_IDIV:
3094 		op->type = R_ANAL_OP_TYPE_DIV;
3095 		break;
3096 	case X86_INS_DIV:
3097 		op->type = R_ANAL_OP_TYPE_DIV;
3098 		break;
3099 	case X86_INS_IMUL:
3100 		op->type = R_ANAL_OP_TYPE_MUL;
3101 		op->sign = true;
3102 		break;
3103 	case X86_INS_AAM:
3104 	case X86_INS_MUL:
3105 	case X86_INS_MULX:
3106 	case X86_INS_MULPD:
3107 	case X86_INS_MULPS:
3108 	case X86_INS_MULSD:
3109 	case X86_INS_MULSS:
3110 		op->type = R_ANAL_OP_TYPE_MUL;
3111 		break;
3112 	case X86_INS_PACKSSDW:
3113 	case X86_INS_PACKSSWB:
3114 	case X86_INS_PACKUSWB:
3115 		op->type = R_ANAL_OP_TYPE_MOV;
3116 		op->family = R_ANAL_OP_FAMILY_MMX;
3117 		break;
3118 	case X86_INS_PADDB:
3119 	case X86_INS_PADDD:
3120 	case X86_INS_PADDW:
3121 	case X86_INS_PADDSB:
3122 	case X86_INS_PADDSW:
3123 	case X86_INS_PADDUSB:
3124 	case X86_INS_PADDUSW:
3125 		op->type = R_ANAL_OP_TYPE_ADD;
3126 		op->family = R_ANAL_OP_FAMILY_MMX;
3127 		break;
3128 	case X86_INS_XCHG:
3129 		op->type = R_ANAL_OP_TYPE_MOV;
3130 		op->family = R_ANAL_OP_FAMILY_CPU;
3131 		break;
3132 	case X86_INS_XADD: /* xchg + add */
3133 		op->type = R_ANAL_OP_TYPE_ADD;
3134 		op->family = R_ANAL_OP_FAMILY_CPU;
3135 		break;
3136 	case X86_INS_FADD:
3137 #if CS_API_MAJOR == 4
3138 	case X86_INS_FADDP:
3139 #endif
3140 		op->family = R_ANAL_OP_FAMILY_FPU;
3141 		op->type = R_ANAL_OP_TYPE_ADD;
3142 		break;
3143 	case X86_INS_ADDPS:
3144 	case X86_INS_ADDSD:
3145 	case X86_INS_ADDSS:
3146 	case X86_INS_ADDSUBPD:
3147 	case X86_INS_ADDSUBPS:
3148 	case X86_INS_ADDPD:
3149 		// The OF, SF, ZF, AF, CF, and PF flags are set according to the
3150 		// result.
3151 		op->type = R_ANAL_OP_TYPE_ADD;
3152 		op_stackidx (op, insn, true);
3153 		op->val = INSOP(1).imm;
3154 		break;
3155 	case X86_INS_ADD:
3156 		// The OF, SF, ZF, AF, CF, and PF flags are set according to the
3157 		// result.
3158 		op->type = R_ANAL_OP_TYPE_ADD;
3159 		op_stackidx (op, insn, true);
3160 		op0_memimmhandle (op, insn, addr, regsz);
3161 		op1_memimmhandle (op, insn, addr, regsz);
3162 		break;
3163 	case X86_INS_ADC:
3164 		op->type = R_ANAL_OP_TYPE_ADD;
3165 		break;
3166 		/* Direction flag */
3167 	case X86_INS_CLD:
3168 		op->type = R_ANAL_OP_TYPE_MOV;
3169 		break;
3170 	case X86_INS_STD:
3171 		op->type = R_ANAL_OP_TYPE_MOV;
3172 		break;
3173 	case X86_INS_SUBSD:    //cvtss2sd
3174 	case X86_INS_CVTSS2SD: //cvtss2sd
3175 		break;
3176 	}
3177 	if (cs_insn_group (*handle, insn, X86_GRP_MMX)) {
3178 		op->family = R_ANAL_OP_FAMILY_MMX;
3179 	}
3180 	// TODO: add SSE* families?
3181 	if (cs_insn_group (*handle, insn, X86_GRP_SSE1)) {
3182 		op->family = R_ANAL_OP_FAMILY_SSE;
3183 	}
3184 	if (cs_insn_group (*handle, insn, X86_GRP_SSE2)) {
3185 		op->family = R_ANAL_OP_FAMILY_SSE;
3186 	}
3187 	if (cs_insn_group (*handle, insn, X86_GRP_SSE3)) {
3188 		op->family = R_ANAL_OP_FAMILY_SSE;
3189 	}
3190 }
3191 
cs_len_prefix_opcode(uint8_t * item)3192 static int cs_len_prefix_opcode(uint8_t *item) {
3193 	int i, len = 0;
3194 	for (i = 0; i < 4; i++) {
3195 		len += (item[i] != 0) ? 1 : 0;
3196 	}
3197 	return len;
3198 }
3199 
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)3200 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
3201 	static int omode = 0;
3202 #if USE_ITER_API
3203 	static
3204 #endif
3205 	cs_insn *insn = NULL;
3206 	int mode = (a->bits==64)? CS_MODE_64:
3207 		(a->bits==32)? CS_MODE_32:
3208 		(a->bits==16)? CS_MODE_16: 0;
3209 	int n, ret;
3210 
3211 	if (handle && mode != omode) {
3212 		if (handle != 0) {
3213 			cs_close (&handle);
3214 			handle = 0;
3215 		}
3216 	}
3217 	omode = mode;
3218 	if (handle == 0) {
3219 		ret = cs_open (CS_ARCH_X86, mode, &handle);
3220 		if (ret != CS_ERR_OK) {
3221 			handle = 0;
3222 			return 0;
3223 		}
3224 	}
3225 	op->cycles = 1; // aprox
3226 	cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
3227 	// capstone-next
3228 #if USE_ITER_API
3229 	{
3230 		ut64 naddr = addr;
3231 		size_t size = len;
3232 		if (!insn) {
3233 			insn = cs_malloc (handle);
3234 		}
3235 		n = cs_disasm_iter (handle, (const uint8_t**)&buf,
3236 			&size, (uint64_t*)&naddr, insn);
3237 	}
3238 #else
3239 	n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn);
3240 #endif
3241 	if (n < 1) {
3242 		op->type = R_ANAL_OP_TYPE_ILL;
3243 		if (mask & R_ANAL_OP_MASK_DISASM) {
3244 			op->mnemonic = strdup ("invalid");
3245 		}
3246 	} else {
3247 		if (mask & R_ANAL_OP_MASK_DISASM) {
3248 			op->mnemonic = r_str_newf ("%s%s%s",
3249 				insn->mnemonic,
3250 				insn->op_str[0]?" ":"",
3251 				insn->op_str);
3252 		}
3253 		// int rs = a->bits / 8;
3254 		//const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip";
3255 		//const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp";
3256 		//const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp";
3257 		op->nopcode = cs_len_prefix_opcode (insn->detail->x86.prefix)
3258 			+ cs_len_prefix_opcode (insn->detail->x86.opcode);
3259 		op->size = insn->size;
3260 		op->id = insn->id;
3261 		op->family = R_ANAL_OP_FAMILY_CPU; // almost everything is CPU
3262 		op->prefix = 0;
3263 		op->cond = cond_x862r2 (insn->id);
3264 		switch (insn->detail->x86.prefix[0]) {
3265 		case X86_PREFIX_REPNE:
3266 			op->prefix |= R_ANAL_OP_PREFIX_REPNE;
3267 			break;
3268 		case X86_PREFIX_REP:
3269 			op->prefix |= R_ANAL_OP_PREFIX_REP;
3270 			break;
3271 		case X86_PREFIX_LOCK:
3272 			op->prefix |= R_ANAL_OP_PREFIX_LOCK;
3273 			op->family = R_ANAL_OP_FAMILY_THREAD; // XXX ?
3274 			break;
3275 		}
3276 		anop (a, op, addr, buf, len, &handle, insn);
3277 		set_opdir (op, insn);
3278 		if (mask & R_ANAL_OP_MASK_ESIL) {
3279 			anop_esil (a, op, addr, buf, len, &handle, insn);
3280 		}
3281 		if (mask & R_ANAL_OP_MASK_OPEX) {
3282 			opex (&op->opex, insn, mode);
3283 		}
3284 		if (mask & R_ANAL_OP_MASK_VAL) {
3285 			op_fillval (a, op, &handle, insn, mode);
3286 		}
3287 	}
3288 //#if X86_GRP_PRIVILEGE>0
3289 	if (insn) {
3290 #if HAVE_CSGRP_PRIVILEGE
3291 		if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) {
3292 			op->family = R_ANAL_OP_FAMILY_PRIV;
3293 		}
3294 #endif
3295 #if !USE_ITER_API
3296 		cs_free (insn, n);
3297 #endif
3298 	}
3299 	//cs_close (&handle);
3300 	return op->size;
3301 }
3302 
3303 #if 0
3304 static int x86_int_0x80(RAnalEsil *esil, int interrupt) {
3305 	int syscall;
3306 	ut64 eax, ebx, ecx, edx;
3307 	if (!esil || (interrupt != 0x80))
3308 		return false;
3309 	r_anal_esil_reg_read (esil, "eax", &eax, NULL);
3310 	r_anal_esil_reg_read (esil, "ebx", &ebx, NULL);
3311 	r_anal_esil_reg_read (esil, "ecx", &ecx, NULL);
3312 	r_anal_esil_reg_read (esil, "edx", &edx, NULL);
3313 	syscall = (int) eax;
3314 	switch (syscall) {
3315 	case 3:
3316 		{
3317 			char *dst = calloc (1, (size_t)edx);
3318 			(void)read ((ut32)ebx, dst, (size_t)edx);
3319 			r_anal_esil_mem_write (esil, ecx, (ut8 *)dst, (int)edx);
3320 			free (dst);
3321 			return true;
3322 		}
3323 	case 4:
3324 		{
3325 			char *src = malloc ((size_t)edx);
3326 			r_anal_esil_mem_read (esil, ecx, (ut8 *)src, (int)edx);
3327 			write ((ut32)ebx, src, (size_t)edx);
3328 			free (src);
3329 			return true;
3330 		}
3331 	}
3332 	eprintf ("syscall %d not implemented yet\n", syscall);
3333 	return false;
3334 }
3335 #endif
3336 
3337 #if 0
3338 static int esil_x86_cs_intr(RAnalEsil *esil, int intr) {
3339 	if (!esil) return false;
3340 	eprintf ("INTERRUPT 0x%02x HAPPENS\n", intr);
3341 	return true;
3342 }
3343 #endif
3344 
esil_x86_cs_init(RAnalEsil * esil)3345 static int esil_x86_cs_init(RAnalEsil *esil) {
3346 	if (!esil) {
3347 		return false;
3348 	}
3349 	// XXX. this depends on kernel
3350 	// r_anal_esil_set_interrupt (esil, 0x80, x86_int_0x80);
3351 	/* disable by default */
3352 //	r_anal_esil_set_interrupt (esil, 0x80, NULL);	// this is stupid, don't do this
3353 	return true;
3354 }
3355 
init(void * p)3356 static int init(void *p) {
3357 	handle = 0;
3358 	return true;
3359 }
3360 
fini(void * p)3361 static int fini(void *p) {
3362 	if (handle != 0) {
3363 		// SEGFAULTS RANDOMLY, better leak on exit.. lets try it out again
3364 		cs_close (&handle);
3365 		handle = 0;
3366 	}
3367 	return true;
3368 }
3369 
esil_x86_cs_fini(RAnalEsil * esil)3370 static int esil_x86_cs_fini(RAnalEsil *esil) {
3371 	return true;
3372 }
3373 
get_reg_profile(RAnal * anal)3374 static char *get_reg_profile(RAnal *anal) {
3375 	const char *p = NULL;
3376 	switch (anal->bits) {
3377 	case 16: p =
3378 		"=PC	ip\n"
3379 		"=SP	sp\n"
3380 		"=BP	bp\n"
3381 		"=A0	ax\n"
3382 		"=A1	bx\n"
3383 		"=A2	cx\n"
3384 		"=A3	dx\n"
3385 		"=A4	si\n"
3386 		"=A5	di\n"
3387 		"=SN	ah\n"
3388 		"gpr	ip	.16	48	0\n"
3389 		"gpr	ax	.16	24	0\n"
3390 		"gpr	ah	.8	25	0\n"
3391 		"gpr	al	.8	24	0\n"
3392 		"gpr	bx	.16	0	0\n"
3393 		"gpr	bh	.8	1	0\n"
3394 		"gpr	bl	.8	0	0\n"
3395 		"gpr	cx	.16	4	0\n"
3396 		"gpr	ch	.8	5	0\n"
3397 		"gpr	cl	.8	4	0\n"
3398 		"gpr	dx	.16	8	0\n"
3399 		"gpr	dh	.8	9	0\n"
3400 		"gpr	dl	.8	8	0\n"
3401 		"gpr	sp	.16	60	0\n"
3402 		"gpr	bp	.16	20	0\n"
3403 		"gpr	si	.16	12	0\n"
3404 		"gpr	di	.16	16	0\n"
3405 		"seg	cs	.16	52	0\n"
3406 		"seg	ss	.16	54	0\n"
3407 		"seg	ds	.16	56	0\n"
3408 		"seg	es	.16	58	0\n"
3409 		"gpr	flags	.16	56	0\n"
3410 		"flg	cf	.1	.448	0\n"
3411 		"flg	pf	.1	.449	0\n"
3412 		"flg	af	.1	.450	0\n"
3413 		"flg	zf	.1	.451	0\n"
3414 		"flg	sf	.1	.452	0\n"
3415 		"flg	tf	.1	.453	0\n"
3416 		"flg	if	.1	.454	0\n"
3417 		"flg	df	.1	.455	0\n"
3418 		"flg	of	.1	.456	0\n"
3419 		"flg	rf	.1	.457	0\n";
3420 #if 0
3421 		"drx	dr0	.32	0	0\n"
3422 		"drx	dr1	.32	4	0\n"
3423 		"drx	dr2	.32	8	0\n"
3424 		"drx	dr3	.32	12	0\n"
3425 		//"drx	dr4	.32	16	0\n"
3426 		//"drx	dr5	.32	20	0\n"
3427 		"drx	dr6	.32	24	0\n"
3428 		"drx	dr7	.32	28	0\n"
3429 #endif
3430 		break;
3431 	case 32: p =
3432 		"=PC	eip\n"
3433 		"=SP	esp\n"
3434 		"=BP	ebp\n"
3435 		"=A0	eax\n"
3436 		"=A1	ebx\n"
3437 		"=A2	ecx\n"
3438 		"=A3	edx\n"
3439 		"=A4	esi\n"
3440 		"=A5	edi\n"
3441 		"=SN	eax\n"
3442 		"gpr	oeax	.32	44	0\n"
3443 		"gpr	eax	.32	24	0\n"
3444 		"gpr	ax	.16	24	0\n"
3445 		"gpr	ah	.8	25	0\n"
3446 		"gpr	al	.8	24	0\n"
3447 		"gpr	ebx	.32	0	0\n"
3448 		"gpr	bx	.16	0	0\n"
3449 		"gpr	bh	.8	1	0\n"
3450 		"gpr	bl	.8	0	0\n"
3451 		"gpr	ecx	.32	4	0\n"
3452 		"gpr	cx	.16	4	0\n"
3453 		"gpr	ch	.8	5	0\n"
3454 		"gpr	cl	.8	4	0\n"
3455 		"gpr	edx	.32	8	0\n"
3456 		"gpr	dx	.16	8	0\n"
3457 		"gpr	dh	.8	9	0\n"
3458 		"gpr	dl	.8	8	0\n"
3459 		"gpr	esi	.32	12	0\n"
3460 		"gpr	si	.16	12	0\n"
3461 		"gpr	edi	.32	16	0\n"
3462 		"gpr	di	.16	16	0\n"
3463 		"gpr	esp	.32	60	0\n"
3464 		"gpr	sp	.16	60	0\n"
3465 		"gpr	ebp	.32	20	0\n"
3466 		"gpr	bp	.16	20	0\n"
3467 		"gpr	eip	.32	48	0\n"
3468 		"gpr	ip	.16	48	0\n"
3469 		"seg	xfs	.32	36	0\n"
3470 		"seg	xgs	.32	40	0\n"
3471 		"seg	xcs	.32	52	0\n"
3472 		"seg	cs	.16	52	0\n"
3473 		"seg	xss	.32	52	0\n"
3474 		"flg	eflags	.32	.448	0	c1p.a.zstido.n.rv\n"
3475 		"flg	flags	.16	.448	0\n"
3476 		"flg	cf	.1	.448	0\n"
3477 		"flg	pf	.1	.450	0\n"
3478 		"flg	af	.1	.452	0\n"
3479 		"flg	zf	.1	.454	0\n"
3480 		"flg	sf	.1	.455	0\n"
3481 		"flg	tf	.1	.456	0\n"
3482 		"flg	if	.1	.457	0\n"
3483 		"flg	df	.1	.458	0\n"
3484 		"flg	of	.1	.459	0\n"
3485 		"flg	nt	.1	.462	0\n"
3486 		"flg	rf	.1	.464	0\n"
3487 		"flg	vm	.1	.465	0\n"
3488 		"drx	dr0	.32	0	0\n"
3489 		"drx	dr1	.32	4	0\n"
3490 		"drx	dr2	.32	8	0\n"
3491 		"drx	dr3	.32	12	0\n"
3492 		//"drx	dr4	.32	16	0\n"
3493 		//"drx	dr5	.32	20	0\n"
3494 		"drx	dr6	.32	24	0\n"
3495 		"drx	dr7	.32	28	0\n";
3496 		 break;
3497 	case 64:
3498 	{
3499 		const char *cc = r_anal_cc_default (anal);
3500 		const char *args_prof = cc && !strcmp (cc, "ms")
3501 		? // Microsoft x64 CC
3502 		"# RAX     return value\n"
3503 		"# RCX     argument 1\n"
3504 		"# RDX     argument 2\n"
3505 		"# R8      argument 3\n"
3506 		"# R9      argument 4\n"
3507 		"# R10-R11 syscall/sysret\n"
3508 		"# R12-R15 GP preserved\n"
3509 		"# RSI     preserved source\n"
3510 		"# RDI     preserved destination\n"
3511 		"# RSP     stack pointer\n"
3512 		 "=PC	rip\n"
3513 		 "=SP	rsp\n"
3514 		 "=BP	rbp\n"
3515 		 "=A0	rcx\n"
3516 		 "=A1	rdx\n"
3517 		 "=A2	r8\n"
3518 		 "=A3	r9\n"
3519 		 "=SN	rax\n"
3520 		 : // System V AMD64 ABI
3521 		 "=PC	rip\n"
3522 		 "=SP	rsp\n"
3523 		 "=BP	rbp\n"
3524 		 "=A0	rdi\n"
3525 		 "=A1	rsi\n"
3526 		 "=A2	rdx\n"
3527 		 "=A3	rcx\n"
3528 		 "=A4	r8\n"
3529 		 "=A5	r9\n"
3530 		 "=A6	r10\n"
3531 		 "=A7	r11\n"
3532 		 "=SN	rax\n";
3533 		char *prof = r_str_newf ("%s%s", args_prof,
3534 		 "gpr	rax	.64	80	0\n"
3535 		 "gpr	eax	.32	80	0\n"
3536 		 "gpr	ax	.16	80	0\n"
3537 		 "gpr	al	.8	80	0\n"
3538 		 "gpr	ah	.8	81	0\n"
3539 		 "gpr	rbx	.64	40	0\n"
3540 		 "gpr	ebx	.32	40	0\n"
3541 		 "gpr	bx	.16	40	0\n"
3542 		 "gpr	bl	.8	40	0\n"
3543 		 "gpr	bh	.8	41	0\n"
3544 		 "gpr	rcx	.64	88	0\n"
3545 		 "gpr	ecx	.32	88	0\n"
3546 		 "gpr	cx	.16	88	0\n"
3547 		 "gpr	cl	.8	88	0\n"
3548 		 "gpr	ch	.8	89	0\n"
3549 		 "gpr	rdx	.64	96	0\n"
3550 		 "gpr	edx	.32	96	0\n"
3551 		 "gpr	dx	.16	96	0\n"
3552 		 "gpr	dl	.8	96	0\n"
3553 		 "gpr	dh	.8	97	0\n"
3554 		 "gpr	rsi	.64	104	0\n"
3555 		 "gpr	esi	.32	104	0\n"
3556 		 "gpr	si	.16	104	0\n"
3557 		 "gpr	sil	.8	104	0\n"
3558 		 "gpr	rdi	.64	112	0\n"
3559 		 "gpr	edi	.32	112	0\n"
3560 		 "gpr	di	.16	112	0\n"
3561 		 "gpr	dil	.8	112	0\n"
3562 		 "gpr	r8	.64	72	0\n"
3563 		 "gpr	r8d	.32	72	0\n"
3564 		 "gpr	r8w	.16	72	0\n"
3565 		 "gpr	r8b	.8	72	0\n"
3566 		 "gpr	r9	.64	64	0\n"
3567 		 "gpr	r9d	.32	64	0\n"
3568 		 "gpr	r9w	.16	64	0\n"
3569 		 "gpr	r9b	.8	64	0\n"
3570 		 "gpr	r10	.64	56	0\n"
3571 		 "gpr	r10d	.32	56	0\n"
3572 		 "gpr	r10w	.16	56	0\n"
3573 		 "gpr	r10b	.8	56	0\n"
3574 		 "gpr	r11	.64	48	0\n"
3575 		 "gpr	r11d	.32	48	0\n"
3576 		 "gpr	r11w	.16	48	0\n"
3577 		 "gpr	r11b	.8	48	0\n"
3578 		 "gpr	r12	.64	24	0\n"
3579 		 "gpr	r12d	.32	24	0\n"
3580 		 "gpr	r12w	.16	24	0\n"
3581 		 "gpr	r12b	.8	24	0\n"
3582 		 "gpr	r13	.64	16	0\n"
3583 		 "gpr	r13d	.32	16	0\n"
3584 		 "gpr	r13w	.16	16	0\n"
3585 		 "gpr	r13b	.8	16	0\n"
3586 		 "gpr	r14	.64	8	0\n"
3587 		 "gpr	r14d	.32	8	0\n"
3588 		 "gpr	r14w	.16	8	0\n"
3589 		 "gpr	r14b	.8	8	0\n"
3590 		 "gpr	r15	.64	0	0\n"
3591 		 "gpr	r15d	.32	0	0\n"
3592 		 "gpr	r15w	.16	0	0\n"
3593 		 "gpr	r15b	.8	0	0\n"
3594 		 "gpr	rip	.64	128	0\n"
3595 		 "gpr	rbp	.64	32	0\n"
3596 		 "gpr	ebp	.32	32	0\n"
3597 		 "gpr	bp	.16	32	0\n"
3598 		 "gpr	bpl	.8	32	0\n"
3599 		 "seg	cs	.64	136	0\n"
3600 		 "flg	rflags	.64	144	0	c1p.a.zstido.n.rv\n"
3601 		 "flg	eflags	.32	144	0	c1p.a.zstido.n.rv\n"
3602 		 "flg	cf	.1	144.0	0	carry\n"
3603 		 "flg	pf	.1	144.2	0	parity\n"
3604 		 //"gpr	cf	.1	.1152	0	carry\n"
3605 		 //"gpr	pf	.1	.1154	0	parity\n"
3606 		 "flg	af	.1	144.4	0	adjust\n"
3607 		 "flg	zf	.1	144.6	0	zero\n"
3608 		 "flg	sf	.1	144.7	0	sign\n"
3609 		 "flg	tf	.1	.1160	0	trap\n"
3610 		 "flg	if	.1	.1161	0	interrupt\n"
3611 		 "flg	df	.1	.1162	0	direction\n"
3612 		 "flg	of	.1	.1163	0	overflow\n"
3613 
3614 		 "gpr	rsp	.64	152	0\n"
3615 		 "gpr	esp	.32	152	0\n"
3616 		 "gpr	sp	.16	152	0\n"
3617 		 "gpr	spl	.8	152	0\n"
3618 		 "seg	ss	.64	160	0\n"
3619 		 "seg	fs_base	.64	168	0\n"
3620 		 "seg	gs_base	.64	176	0\n"
3621 		 "seg	ds	.64	184	0\n"
3622 		 "seg	es	.64	192	0\n"
3623 		 "seg	fs	.64	200	0\n"
3624 		 "seg	gs	.64	208	0\n"
3625 		 "drx	dr0	.64	0	0\n"
3626 		 "drx	dr1	.64	8	0\n"
3627 		 "drx	dr2	.64	16	0\n"
3628 		 "drx	dr3	.64	24	0\n"
3629 		 // dr4 32
3630 		 // dr5 40
3631 		 "drx	dr6	.64	48	0\n"
3632 		 "drx	dr7	.64	56	0\n"
3633 
3634 		 /*0030 struct user_fpregs_struct
3635 		   0031 {
3636 		   0032   __uint16_t        cwd;
3637 		   0033   __uint16_t        swd;
3638 		   0034   __uint16_t        ftw;
3639 		   0035   __uint16_t        fop;
3640 		   0036   __uint64_t        rip;
3641 		   0037   __uint64_t        rdp;
3642 		   0038   __uint32_t        mxcsr;
3643 		   0039   __uint32_t        mxcr_mask;
3644 		   0040   __uint32_t        st_space[32];   // 8*16 bytes for each FP-reg = 128 bytes
3645 		   0041   __uint32_t        xmm_space[64];  // 16*16 bytes for each XMM-reg = 256 bytes
3646 		   0042   __uint32_t        padding[24];
3647 		   0043 };
3648 		  */
3649 		 "fpu    cwd .16 0   0\n"
3650 		 "fpu    swd .16 2   0\n"
3651 		 "fpu    ftw .16 4   0\n"
3652 		 "fpu    fop .16 6   0\n"
3653 		 "fpu    frip .64 8   0\n"
3654 		 "fpu    frdp .64 16  0\n"
3655 		 "fpu    mxcsr .32 24  0\n"
3656 		 "fpu    mxcr_mask .32 28  0\n"
3657 
3658 		 "fpu    st0 .64 32  0\n"
3659 		 "fpu    st1 .64 48  0\n"
3660 		 "fpu    st2 .64 64  0\n"
3661 		 "fpu    st3 .64 80  0\n"
3662 		 "fpu    st4 .64 96  0\n"
3663 		 "fpu    st5 .64 112  0\n"
3664 		 "fpu    st6 .64 128  0\n"
3665 		 "fpu    st7 .64 144  0\n"
3666 
3667 		 "xmm@fpu    xmm0  .128 160  4\n"
3668 		 "fpu    xmm0h .64 160  0\n"
3669 		 "fpu    xmm0l .64 168  0\n"
3670 
3671 		 "xmm@fpu    xmm1  .128 176  4\n"
3672 		 "fpu    xmm1h .64 176  0\n"
3673 		 "fpu    xmm1l .64 184  0\n"
3674 
3675 		 "xmm@fpu    xmm2  .128 192  4\n"
3676 		 "fpu    xmm2h .64 192  0\n"
3677 		 "fpu    xmm2l .64 200  0\n"
3678 
3679 		 "xmm@fpu    xmm3  .128 208  4\n"
3680 		 "fpu    xmm3h .64 208  0\n"
3681 		 "fpu    xmm3l .64 216  0\n"
3682 
3683 		 "xmm@fpu    xmm4  .128 224  4\n"
3684 		 "fpu    xmm4h .64 224  0\n"
3685 		 "fpu    xmm4l .64 232  0\n"
3686 
3687 		 "xmm@fpu    xmm5  .128 240  4\n"
3688 		 "fpu    xmm5h .64 240  0\n"
3689 		 "fpu    xmm5l .64 248  0\n"
3690 
3691 		 "xmm@fpu    xmm6  .128 256  4\n"
3692 		 "fpu    xmm6h .64 256  0\n"
3693 		 "fpu    xmm6l .64 264  0\n"
3694 
3695 		 "xmm@fpu    xmm7  .128 272  4\n"
3696 		 "fpu    xmm7h .64 272  0\n"
3697 		 "fpu    xmm7l .64 280  0\n"
3698 		 "fpu    x64   .64 288  0\n");
3699 		return prof;
3700 	}
3701 #if 0
3702 	default: p= /* XXX */
3703 		 "=PC	rip\n"
3704 		 "=SP	rsp\n"
3705 		 "=BP	rbp\n"
3706 		 "=A0	rax\n"
3707 		 "=A1	rbx\n"
3708 		 "=A2	rcx\n"
3709 		 "=A3	rdx\n"
3710 		 "# no profile defined for x86-64\n"
3711 		 "gpr	r15	.64	0	0\n"
3712 		 "gpr	r14	.64	8	0\n"
3713 		 "gpr	r13	.64	16	0\n"
3714 		 "gpr	r12	.64	24	0\n"
3715 		 "gpr	rbp	.64	32	0\n"
3716 		 "gpr	ebp	.32	32	0\n"
3717 		 "gpr	rbx	.64	40	0\n"
3718 		 "gpr	ebx	.32	40	0\n"
3719 		 "gpr	bx	.16	40	0\n"
3720 		 "gpr	bh	.8	41	0\n"
3721 		 "gpr	bl	.8	40	0\n"
3722 		 "gpr	r11	.64	48	0\n"
3723 		 "gpr	r10	.64	56	0\n"
3724 		 "gpr	r9	.64	64	0\n"
3725 		 "gpr	r8	.64	72	0\n"
3726 		 "gpr	rax	.64	80	0\n"
3727 		 "gpr	eax	.32	80	0\n"
3728 		 "gpr	rcx	.64	88	0\n"
3729 		 "gpr	ecx	.32	88	0\n"
3730 		 "gpr	rdx	.64	96	0\n"
3731 		 "gpr	edx	.32	96	0\n"
3732 		 "gpr	rsi	.64	104	0\n"
3733 		 "gpr	esi	.32	104	0\n"
3734 		 "gpr	rdi	.64	112	0\n"
3735 		 "gpr	edi	.32	112	0\n"
3736 		 "gpr	oeax	.64	120	0\n"
3737 		 "gpr	rip	.64	128	0\n"
3738 		 "seg	cs	.64	136	0\n"
3739 		 //"flg	eflags	.64	144	0\n"
3740 		 "gpr	eflags	.32	144	0	c1p.a.zstido.n.rv\n"
3741 		 "flg	cf	.1	.1152	0\n"
3742 		 "flg	pf	.1	.1153	0\n"
3743 		 "flg	af	.1	.1154	0\n"
3744 		 "flg	zf	.1	.1155	0\n"
3745 		 "flg	sf	.1	.1156	0\n"
3746 		 "flg	tf	.1	.1157	0\n"
3747 		 "flg	if	.1	.1158	0\n"
3748 		 "flg	df	.1	.1159	0\n"
3749 		 "flg	of	.1	.1160	0\n"
3750 		 "flg	rf	.1	.1161	0\n"
3751 		 "gpr	rsp	.64	152	0\n"
3752 		 "seg	ss	.64	160	0\n"
3753 		 "seg	fs_base	.64	168	0\n"
3754 		 "seg	gs_base	.64	176	0\n"
3755 		 "seg	ds	.64	184	0\n"
3756 		 "seg	es	.64	192	0\n"
3757 		 "seg	fs	.64	200	0\n"
3758 		 "seg	gs	.64	208	0\n"
3759 		 "drx	dr0	.32	0	0\n"
3760 		 "drx	dr1	.32	4	0\n"
3761 		 "drx	dr2	.32	8	0\n"
3762 		 "drx	dr3	.32	12	0\n"
3763 		 "drx	dr6	.32	24	0\n"
3764 		 "drx	dr7	.32	28	0\n";
3765 		 break;
3766 #endif
3767 	}
3768 	return (p && *p)? strdup (p): NULL;
3769 }
3770 
archinfo(RAnal * anal,int q)3771 static int archinfo(RAnal *anal, int q) {
3772 	switch (q) {
3773 	case R_ANAL_ARCHINFO_ALIGN:
3774 		return 0;
3775 	case R_ANAL_ARCHINFO_MAX_OP_SIZE:
3776 		return 16;
3777 	case R_ANAL_ARCHINFO_MIN_OP_SIZE:
3778 		return 1;
3779 	}
3780 	return 0;
3781 }
3782 
anal_preludes(RAnal * anal)3783 static RList *anal_preludes(RAnal *anal) {
3784 #define KW(d,ds,m,ms) r_list_append (l, r_search_keyword_new((const ut8*)d,ds,(const ut8*)m, ms, NULL))
3785 	RList *l = r_list_newf ((RListFree)r_search_keyword_free);
3786 	switch (anal->bits) {
3787 	case 32:
3788 		KW ("\x8b\xff\x55\x8b\xec", 5, NULL, 0);
3789 		KW ("\x55\x89\xe5", 3, NULL, 0);
3790 		KW ("\x55\x8b\xec", 3, NULL, 0);
3791 		KW ("\xf3\x0f\x1e\xfb", 4, NULL, 0); // endbr32
3792 		break;
3793 	case 64:
3794 		KW ("\x55\x48\x89\xe5", 4, NULL, 0);
3795 		KW ("\x55\x48\x8b\xec", 4, NULL, 0);
3796 		KW ("\xf3\x0f\x1e\xfa", 4, NULL, 0); // endbr64
3797 		break;
3798 	default:
3799 		r_list_free (l);
3800 		l = NULL;
3801 		break;
3802 	}
3803 	return l;
3804 }
3805 
3806 RAnalPlugin r_anal_plugin_x86_cs = {
3807 	.name = "x86",
3808 	.desc = "Capstone X86 analysis",
3809 	.esil = true,
3810 	.license = "BSD",
3811 	.arch = "x86",
3812 	.bits = 16|32|64,
3813 	.op = &analop,
3814 	.preludes = anal_preludes,
3815 	.archinfo = archinfo,
3816 	.get_reg_profile = &get_reg_profile,
3817 	.init = init,
3818 	.fini = fini,
3819 	.esil_init = esil_x86_cs_init,
3820 	.esil_fini = esil_x86_cs_fini,
3821 //	.esil_intr = esil_x86_cs_intr,
3822 };
3823 
3824 #ifndef R2_PLUGIN_INCORE
3825 R_API RLibStruct radare_plugin = {
3826 	.type = R_LIB_TYPE_ANAL,
3827 	.data = &r_anal_plugin_x86_cs,
3828 	.version = R2_VERSION
3829 };
3830 #endif
3831