blob: 85373b1e7b830a4e598bbe32e90ab279b7eaf67a [file] [log] [blame]
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001//===-- X86IntelInstPrinter.cpp - Intel assembly instruction printing -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file includes code for rendering MCInst instances as Intel-style
11// assembly.
12//
13//===----------------------------------------------------------------------===//
14
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +080015/* Capstone Disassembly Engine */
16/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080017
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +080018#ifdef CAPSTONE_HAS_X86
19
reverserbcf09f42015-04-09 18:28:19 +010020#if !defined(CAPSTONE_HAS_OSXKERNEL)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080021#include <ctype.h>
reverserbcf09f42015-04-09 18:28:19 +010022#endif
Cr4sh9d606072015-03-29 18:29:06 +080023#include "../../myinttypes.h"
reverserbcf09f42015-04-09 18:28:19 +010024#if defined(CAPSTONE_HAS_OSXKERNEL)
25#include <libkern/libkern.h>
26#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080027#include <stdio.h>
28#include <stdlib.h>
reverserbcf09f42015-04-09 18:28:19 +010029#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080030#include <string.h>
31
32#include "../../utils.h"
33#include "../../MCInst.h"
34#include "../../SStream.h"
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +080035#include "../../MCRegisterInfo.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080036
Nguyen Anh Quynhf328f302014-01-20 09:47:21 +080037#include "X86Mapping.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080038
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080039#define GET_INSTRINFO_ENUM
40#ifdef CAPSTONE_X86_REDUCE
41#include "X86GenInstrInfo_reduce.inc"
42#else
43#include "X86GenInstrInfo.inc"
44#endif
45
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +080046#include "X86BaseInfo.h"
47
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080048static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +080049static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080050
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080051
52static void set_mem_access(MCInst *MI, bool status)
53{
54 if (MI->csh->detail != CS_OPT_ON)
55 return;
56
57 MI->csh->doing_mem = status;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +080058 if (!status)
59 // done, create the next operand slot
60 MI->flat_insn->detail->x86.op_count++;
61
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080062}
63
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080064static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
65{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +080066 SStream_concat0(O, "ptr ");
Nguyen Anh Quynhe10b53f2015-02-10 00:21:00 +080067
68 switch(MI->csh->mode) {
69 case CS_MODE_16:
70 MI->x86opsize = 2;
71 break;
72 case CS_MODE_32:
73 MI->x86opsize = 4;
74 break;
75 case CS_MODE_64:
76 MI->x86opsize = 8;
77 break;
78 default: // never reach
79 break;
80 }
81
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080082 printMemReference(MI, OpNo, O);
83}
84
85static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
86{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +080087 SStream_concat0(O, "byte ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080088 MI->x86opsize = 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080089 printMemReference(MI, OpNo, O);
90}
91
92static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
93{
Nguyen Anh Quynhd319c112014-12-26 16:49:10 +080094 MI->x86opsize = 2;
95 SStream_concat0(O, "word ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080096 printMemReference(MI, OpNo, O);
97}
98
99static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
100{
Nguyen Anh Quynhd319c112014-12-26 16:49:10 +0800101 MI->x86opsize = 4;
102 SStream_concat0(O, "dword ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800103 printMemReference(MI, OpNo, O);
104}
105
106static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
107{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800108 SStream_concat0(O, "qword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800109 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800110 printMemReference(MI, OpNo, O);
111}
112
113static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
114{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800115 SStream_concat0(O, "xmmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800116 MI->x86opsize = 16;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800117 printMemReference(MI, OpNo, O);
118}
119
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800120#ifndef CAPSTONE_X86_REDUCE
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800121static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
122{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800123 SStream_concat0(O, "ymmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800124 MI->x86opsize = 32;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800125 printMemReference(MI, OpNo, O);
126}
127
128static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
129{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800130 SStream_concat0(O, "zmmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800131 MI->x86opsize = 64;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800132 printMemReference(MI, OpNo, O);
133}
134
135static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
136{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800137 SStream_concat0(O, "dword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800138 MI->x86opsize = 4;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800139 printMemReference(MI, OpNo, O);
140}
141
142static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
143{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800144 SStream_concat0(O, "qword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800145 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800146 printMemReference(MI, OpNo, O);
147}
148
149static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
150{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800151 SStream_concat0(O, "xword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800152 MI->x86opsize = 10;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800153 printMemReference(MI, OpNo, O);
154}
155
156static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
157{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800158 SStream_concat0(O, "xmmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800159 MI->x86opsize = 16;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800160 printMemReference(MI, OpNo, O);
161}
162
163static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
164{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800165 SStream_concat0(O, "ymmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800166 MI->x86opsize = 32;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800167 printMemReference(MI, OpNo, O);
168}
169
170static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
171{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800172 SStream_concat0(O, "zmmword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800173 MI->x86opsize = 64;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800174 printMemReference(MI, OpNo, O);
175}
176
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800177static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
178{
Nguyen Anh Quynh9f694cc2014-12-26 17:54:11 +0800179 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 7;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800180 switch (Imm) {
181 default: break; // never reach
Nguyen Anh Quynh4c5eabc2014-06-24 23:50:41 +0800182 case 0: SStream_concat0(OS, "eq"); op_addSseCC(MI, X86_SSE_CC_EQ); break;
183 case 1: SStream_concat0(OS, "lt"); op_addSseCC(MI, X86_SSE_CC_LT); break;
184 case 2: SStream_concat0(OS, "le"); op_addSseCC(MI, X86_SSE_CC_LE); break;
185 case 3: SStream_concat0(OS, "unord"); op_addSseCC(MI, X86_SSE_CC_UNORD); break;
186 case 4: SStream_concat0(OS, "neq"); op_addSseCC(MI, X86_SSE_CC_NEQ); break;
187 case 5: SStream_concat0(OS, "nlt"); op_addSseCC(MI, X86_SSE_CC_NLT); break;
188 case 6: SStream_concat0(OS, "nle"); op_addSseCC(MI, X86_SSE_CC_NLE); break;
189 case 7: SStream_concat0(OS, "ord"); op_addSseCC(MI, X86_SSE_CC_ORD); break;
190 case 8: SStream_concat0(OS, "eq_uq"); op_addSseCC(MI, X86_SSE_CC_EQ_UQ); break;
191 case 9: SStream_concat0(OS, "nge"); op_addSseCC(MI, X86_SSE_CC_NGE); break;
192 case 0xa: SStream_concat0(OS, "ngt"); op_addSseCC(MI, X86_SSE_CC_NGT); break;
193 case 0xb: SStream_concat0(OS, "false"); op_addSseCC(MI, X86_SSE_CC_FALSE); break;
194 case 0xc: SStream_concat0(OS, "neq_oq"); op_addSseCC(MI, X86_SSE_CC_NEQ_OQ); break;
195 case 0xd: SStream_concat0(OS, "ge"); op_addSseCC(MI, X86_SSE_CC_GE); break;
196 case 0xe: SStream_concat0(OS, "gt"); op_addSseCC(MI, X86_SSE_CC_GT); break;
197 case 0xf: SStream_concat0(OS, "true"); op_addSseCC(MI, X86_SSE_CC_TRUE); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800198 }
199}
200
201static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
202{
203 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
204 switch (Imm) {
205 default: break;//printf("Invalid avxcc argument!\n"); break;
Nguyen Anh Quynh4c5eabc2014-06-24 23:50:41 +0800206 case 0: SStream_concat0(O, "eq"); op_addAvxCC(MI, X86_AVX_CC_EQ); break;
207 case 1: SStream_concat0(O, "lt"); op_addAvxCC(MI, X86_AVX_CC_LT); break;
208 case 2: SStream_concat0(O, "le"); op_addAvxCC(MI, X86_AVX_CC_LE); break;
209 case 3: SStream_concat0(O, "unord"); op_addAvxCC(MI, X86_AVX_CC_UNORD); break;
210 case 4: SStream_concat0(O, "neq"); op_addAvxCC(MI, X86_AVX_CC_NEQ); break;
211 case 5: SStream_concat0(O, "nlt"); op_addAvxCC(MI, X86_AVX_CC_NLT); break;
212 case 6: SStream_concat0(O, "nle"); op_addAvxCC(MI, X86_AVX_CC_NLE); break;
213 case 7: SStream_concat0(O, "ord"); op_addAvxCC(MI, X86_AVX_CC_ORD); break;
214 case 8: SStream_concat0(O, "eq_uq"); op_addAvxCC(MI, X86_AVX_CC_EQ_UQ); break;
215 case 9: SStream_concat0(O, "nge"); op_addAvxCC(MI, X86_AVX_CC_NGE); break;
216 case 0xa: SStream_concat0(O, "ngt"); op_addAvxCC(MI, X86_AVX_CC_NGT); break;
217 case 0xb: SStream_concat0(O, "false"); op_addAvxCC(MI, X86_AVX_CC_FALSE); break;
218 case 0xc: SStream_concat0(O, "neq_oq"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OQ); break;
219 case 0xd: SStream_concat0(O, "ge"); op_addAvxCC(MI, X86_AVX_CC_GE); break;
220 case 0xe: SStream_concat0(O, "gt"); op_addAvxCC(MI, X86_AVX_CC_GT); break;
221 case 0xf: SStream_concat0(O, "true"); op_addAvxCC(MI, X86_AVX_CC_TRUE); break;
222 case 0x10: SStream_concat0(O, "eq_os"); op_addAvxCC(MI, X86_AVX_CC_EQ_OS); break;
223 case 0x11: SStream_concat0(O, "lt_oq"); op_addAvxCC(MI, X86_AVX_CC_LT_OQ); break;
224 case 0x12: SStream_concat0(O, "le_oq"); op_addAvxCC(MI, X86_AVX_CC_LE_OQ); break;
225 case 0x13: SStream_concat0(O, "unord_s"); op_addAvxCC(MI, X86_AVX_CC_UNORD_S); break;
226 case 0x14: SStream_concat0(O, "neq_us"); op_addAvxCC(MI, X86_AVX_CC_NEQ_US); break;
227 case 0x15: SStream_concat0(O, "nlt_uq"); op_addAvxCC(MI, X86_AVX_CC_NLT_UQ); break;
228 case 0x16: SStream_concat0(O, "nle_uq"); op_addAvxCC(MI, X86_AVX_CC_NLE_UQ); break;
229 case 0x17: SStream_concat0(O, "ord_s"); op_addAvxCC(MI, X86_AVX_CC_ORD_S); break;
230 case 0x18: SStream_concat0(O, "eq_us"); op_addAvxCC(MI, X86_AVX_CC_EQ_US); break;
231 case 0x19: SStream_concat0(O, "nge_uq"); op_addAvxCC(MI, X86_AVX_CC_NGE_UQ); break;
232 case 0x1a: SStream_concat0(O, "ngt_uq"); op_addAvxCC(MI, X86_AVX_CC_NGT_UQ); break;
233 case 0x1b: SStream_concat0(O, "false_os"); op_addAvxCC(MI, X86_AVX_CC_FALSE_OS); break;
234 case 0x1c: SStream_concat0(O, "neq_os"); op_addAvxCC(MI, X86_AVX_CC_NEQ_OS); break;
235 case 0x1d: SStream_concat0(O, "ge_oq"); op_addAvxCC(MI, X86_AVX_CC_GE_OQ); break;
236 case 0x1e: SStream_concat0(O, "gt_oq"); op_addAvxCC(MI, X86_AVX_CC_GT_OQ); break;
237 case 0x1f: SStream_concat0(O, "true_us"); op_addAvxCC(MI, X86_AVX_CC_TRUE_US); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800238 }
239}
240
241static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
242{
243 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
244 switch (Imm) {
Nguyen Anh Quynh1a66fec2014-06-26 12:09:15 +0800245 case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break;
246 case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break;
247 case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break;
248 case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800249 default: break; // never reach
250 }
251}
252
253#endif
254
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800255static char *getRegisterName(unsigned RegNo);
256static void printRegName(SStream *OS, unsigned RegNo)
257{
258 SStream_concat0(OS, getRegisterName(RegNo));
259}
260
261// local printOperand, without updating public operands
262static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
263{
264 MCOperand *Op = MCInst_getOperand(MI, OpNo);
265 if (MCOperand_isReg(Op)) {
266 printRegName(O, MCOperand_getReg(Op));
267 } else if (MCOperand_isImm(Op)) {
268 int64_t imm = MCOperand_getImm(Op);
269 if (imm < 0) {
270 if (imm < -HEX_THRESHOLD)
271 SStream_concat(O, "-0x%"PRIx64, -imm);
272 else
273 SStream_concat(O, "-%"PRIu64, -imm);
274
275 } else {
276 if (imm > HEX_THRESHOLD)
277 SStream_concat(O, "0x%"PRIx64, imm);
278 else
279 SStream_concat(O, "%"PRIu64, imm);
280 }
281 }
282}
283
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800284static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
285{
286 MCOperand *SegReg;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800287 int reg;
288
289 if (MI->csh->detail) {
290 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
291 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
292 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
293 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
294 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
295 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
296 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
297 }
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800298
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800299 SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800300 reg = MCOperand_getReg(SegReg);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800301
302 // If this has a segment register, print it.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800303 if (reg) {
304 _printOperand(MI, Op+1, O);
305 if (MI->csh->detail) {
306 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
307 }
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800308 SStream_concat0(O, ":");
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800309 }
310
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800311 SStream_concat0(O, "[");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800312 set_mem_access(MI, true);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800313 printOperand(MI, Op, O);
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800314 SStream_concat0(O, "]");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800315 set_mem_access(MI, false);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800316}
317
318static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
319{
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800320 if (MI->csh->detail) {
321 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
322 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
323 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
324 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
325 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
326 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
327 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
328 }
329
Nguyen Anh Quynh0e534bf2014-06-05 17:05:16 +0700330 // DI accesses are always ES-based on non-64bit mode
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800331 if (MI->csh->mode != CS_MODE_64) {
Nguyen Anh Quynh9417ad62014-06-05 17:03:52 +0700332 SStream_concat(O, "es:[");
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800333 if (MI->csh->detail) {
334 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES;
335 }
336 } else
Nguyen Anh Quynh9417ad62014-06-05 17:03:52 +0700337 SStream_concat(O, "[");
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800338
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800339 set_mem_access(MI, true);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800340 printOperand(MI, Op, O);
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800341 SStream_concat0(O, "]");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800342 set_mem_access(MI, false);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800343}
344
345void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
346{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800347 SStream_concat0(O, "byte ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800348 MI->x86opsize = 1;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800349 printSrcIdx(MI, OpNo, O);
350}
351
352void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
353{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800354 SStream_concat0(O, "word ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800355 MI->x86opsize = 2;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800356 printSrcIdx(MI, OpNo, O);
357}
358
359void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
360{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800361 SStream_concat0(O, "dword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800362 MI->x86opsize = 4;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800363 printSrcIdx(MI, OpNo, O);
364}
365
366void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
367{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800368 SStream_concat0(O, "qword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800369 MI->x86opsize = 8;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800370 printSrcIdx(MI, OpNo, O);
371}
372
373void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
374{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800375 SStream_concat0(O, "byte ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800376 MI->x86opsize = 1;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800377 printDstIdx(MI, OpNo, O);
378}
379
380void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
381{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800382 SStream_concat0(O, "word ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800383 MI->x86opsize = 2;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800384 printDstIdx(MI, OpNo, O);
385}
386
387void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
388{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800389 SStream_concat0(O, "dword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800390 MI->x86opsize = 4;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800391 printDstIdx(MI, OpNo, O);
392}
393
394void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
395{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800396 SStream_concat0(O, "qword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800397 MI->x86opsize = 8;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800398 printDstIdx(MI, OpNo, O);
399}
400
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800401static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
402{
403 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800404 MCOperand *SegReg = MCInst_getOperand(MI, Op + 1);
405 int reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800406
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800407 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700408 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800409 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800410 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700411 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
412 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
413 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
414 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800415 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800416
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800417 // If this has a segment register, print it.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800418 reg = MCOperand_getReg(SegReg);
419 if (reg) {
420 _printOperand(MI, Op + 1, O);
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800421 SStream_concat0(O, ":");
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800422 if (MI->csh->detail) {
423 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
424 }
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800425 }
426
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800427 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800428
429 if (MCOperand_isImm(DispSpec)) {
430 int64_t imm = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800431 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700432 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800433 if (imm < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800434 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800435 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800436 if (imm > HEX_THRESHOLD)
437 SStream_concat(O, "0x%"PRIx64, imm);
438 else
439 SStream_concat(O, "%"PRIu64, imm);
440 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800441 }
442
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800443 SStream_concat0(O, "]");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800444
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800445 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700446 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800447
448 if (MI->op1_size == 0)
449 MI->op1_size = MI->x86opsize;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800450}
451
452static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
453{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800454 SStream_concat0(O, "byte ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800455 MI->x86opsize = 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800456 printMemOffset(MI, OpNo, O);
457}
458
459static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
460{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800461 SStream_concat0(O, "word ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800462 MI->x86opsize = 2;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800463 printMemOffset(MI, OpNo, O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800464}
465
466static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
467{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800468 SStream_concat0(O, "dword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800469 MI->x86opsize = 4;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800470 printMemOffset(MI, OpNo, O);
471}
472
473static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
474{
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800475 SStream_concat0(O, "qword ptr ");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800476 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800477 printMemOffset(MI, OpNo, O);
478}
479
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800480static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +0800481static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800482void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
483{
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800484 char *mnem;
Nguyen Anh Quynh95781852014-12-12 11:25:12 +0800485 x86_reg reg, reg2;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800486
Nguyen Anh Quynh005c5142014-02-18 11:11:46 +0800487 // Try to print any aliases first.
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800488 mnem = printAliasInstr(MI, O, Info);
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800489 if (mnem)
490 cs_mem_free(mnem);
491 else
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800492 printInstruction(MI, O, Info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800493
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800494 reg = X86_insn_reg_intel(MCInst_getOpcode(MI));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800495 if (MI->csh->detail) {
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800496 // first op can be embedded in the asm by llvm.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800497 // so we have to add the missing register as the first operand
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800498 if (reg) {
499 // shift all the ops right to leave 1st slot for this new register op
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700500 memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
501 sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
502 MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
503 MI->flat_insn->detail->x86.operands[0].reg = reg;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800504 MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
Nguyen Anh Quynh2cdd4222015-03-14 10:17:17 +0800505 MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg];
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700506 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh95781852014-12-12 11:25:12 +0800507 } else {
508 if (X86_insn_reg_intel2(MCInst_getOpcode(MI), &reg, &reg2)) {
509 MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
510 MI->flat_insn->detail->x86.operands[0].reg = reg;
511 MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
512 MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
513 MI->flat_insn->detail->x86.operands[1].reg = reg2;
514 MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
515 MI->flat_insn->detail->x86.op_count = 2;
516 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800517 }
518 }
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800519
520 if (MI->op1_size == 0 && reg)
521 MI->op1_size = MI->csh->regsize_map[reg];
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800522}
523
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800524/// printPCRelImm - This is used to print an immediate value that ends up
525/// being encoded as a pc-relative value.
526static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
527{
528 MCOperand *Op = MCInst_getOperand(MI, OpNo);
529 if (MCOperand_isImm(Op)) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700530 int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800531 if (imm < 0) {
Nguyen Anh Quynha90b0472014-10-02 12:04:35 +0800532 SStream_concat(O, "0x%"PRIx64, imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800533 } else {
Nguyen Anh Quynh2d342512014-05-11 15:33:11 +0800534 // handle 16bit segment bound
535 if (MI->csh->mode == CS_MODE_16 && imm > 0x100000)
536 imm -= 0x10000;
537
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800538 if (imm > HEX_THRESHOLD)
539 SStream_concat(O, "0x%"PRIx64, imm);
540 else
541 SStream_concat(O, "%"PRIu64, imm);
542 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800543 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700544 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
Nguyen Anh Quynhf1ec5262014-06-25 22:03:18 +0800545 // if op_count > 0, then this operand's size is taken from the destination op
546 if (MI->flat_insn->detail->x86.op_count > 0)
547 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
548 else
549 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700550 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
551 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800552 }
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800553
554 if (MI->op1_size == 0)
555 MI->op1_size = MI->imm_size;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800556 }
557}
558
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800559static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
560{
Nguyen Anh Quynh3f00a722015-06-06 00:04:03 +0800561 int opsize = 0;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800562 MCOperand *Op = MCInst_getOperand(MI, OpNo);
Nguyen Anh Quynh3f00a722015-06-06 00:04:03 +0800563
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800564 if (MCOperand_isReg(Op)) {
Nguyen Anh Quynhea3c0892014-10-02 10:17:55 +0800565 unsigned int reg = MCOperand_getReg(Op);
566
567 printRegName(O, reg);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800568 if (MI->csh->detail) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800569 if (MI->csh->doing_mem) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800570 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800571 } else {
572 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
573 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
574 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
575 MI->flat_insn->detail->x86.op_count++;
576 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800577 }
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800578
579 if (MI->op1_size == 0)
580 MI->op1_size = MI->csh->regsize_map[reg];
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800581 } else if (MCOperand_isImm(Op)) {
582 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800583
Nguyen Anh Quynh3f00a722015-06-06 00:04:03 +0800584 switch(MCInst_getOpcode(MI)) {
585 default:
586 break;
587
588 case X86_AAD8i8:
589 case X86_AAM8i8:
590 case X86_ADC8i8:
591 case X86_ADD8i8:
592 case X86_AND8i8:
593 case X86_CMP8i8:
594 case X86_OR8i8:
595 case X86_SBB8i8:
596 case X86_SUB8i8:
597 case X86_TEST8i8:
598 case X86_XOR8i8:
599 case X86_ROL8ri:
600 case X86_ADC8ri:
601 case X86_ADD8ri:
602 case X86_ADD8ri8:
603 case X86_AND8ri:
604 case X86_AND8ri8:
605 case X86_CMP8ri:
606 case X86_MOV8ri:
607 case X86_MOV8ri_alt:
608 case X86_OR8ri:
609 case X86_OR8ri8:
610 case X86_RCL8ri:
611 case X86_RCR8ri:
612 case X86_ROR8ri:
613 case X86_SAL8ri:
614 case X86_SAR8ri:
615 case X86_SBB8ri:
616 case X86_SHL8ri:
617 case X86_SHR8ri:
618 case X86_SUB8ri:
619 case X86_SUB8ri8:
620 case X86_TEST8ri:
621 case X86_TEST8ri_NOREX:
622 case X86_TEST8ri_alt:
623 case X86_XOR8ri:
624 case X86_XOR8ri8:
625 case X86_OUT8ir:
626
627 case X86_ADC8mi:
628 case X86_ADD8mi:
629 case X86_AND8mi:
630 case X86_CMP8mi:
631 case X86_LOCK_ADD8mi:
632 case X86_LOCK_AND8mi:
633 case X86_LOCK_OR8mi:
634 case X86_LOCK_SUB8mi:
635 case X86_LOCK_XOR8mi:
636 case X86_MOV8mi:
637 case X86_OR8mi:
638 case X86_RCL8mi:
639 case X86_RCR8mi:
640 case X86_ROL8mi:
641 case X86_ROR8mi:
642 case X86_SAL8mi:
643 case X86_SAR8mi:
644 case X86_SBB8mi:
645 case X86_SHL8mi:
646 case X86_SHR8mi:
647 case X86_SUB8mi:
648 case X86_TEST8mi:
649 case X86_TEST8mi_alt:
650 case X86_XOR8mi:
651 case X86_PUSH64i8:
652 case X86_CMP32ri8:
653 case X86_CMP64ri8:
654
655 imm = imm & 0xff;
656 opsize = 1; // immediate of 1 byte
657 break;
658 }
659
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800660 switch(MI->flat_insn->id) {
661 default:
662 if (imm >= 0) {
663 if (imm > HEX_THRESHOLD)
664 SStream_concat(O, "0x%"PRIx64, imm);
665 else
666 SStream_concat(O, "%"PRIu64, imm);
667 } else {
668 if (imm < -HEX_THRESHOLD)
669 SStream_concat(O, "-0x%"PRIx64, -imm);
670 else
671 SStream_concat(O, "-%"PRIu64, -imm);
672 }
673
674 break;
675
676 case X86_INS_AND:
677 case X86_INS_OR:
678 case X86_INS_XOR:
679 // do not print number in negative form
Nguyen Anh Quynh9cc87872014-11-04 11:04:16 +0800680 if (imm >= 0 && imm <= HEX_THRESHOLD)
681 SStream_concat(O, "%u", imm);
Nguyen Anh Quynh36d05942015-06-20 10:56:54 +0800682 else {
683 imm = arch_masks[MI->op1_size? MI->op1_size : MI->imm_size] & imm;
684 SStream_concat(O, "0x%"PRIx64, imm);
685 }
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800686 break;
Nguyen Anh Quynh9cc87872014-11-04 11:04:16 +0800687 case X86_INS_RET:
688 // RET imm16
689 if (imm >= 0 && imm <= HEX_THRESHOLD)
690 SStream_concat(O, "%u", imm);
691 else {
692 imm = 0xffff & imm;
693 SStream_concat(O, "0x%x", 0xffff & imm);
694 }
695 break;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800696 }
697
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800698 if (MI->csh->detail) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800699 if (MI->csh->doing_mem) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800700 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800701 } else {
702 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
Nguyen Anh Quynh3f00a722015-06-06 00:04:03 +0800703 if (opsize > 0)
704 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = opsize;
705 else if (MI->flat_insn->detail->x86.op_count > 0)
Nguyen Anh Quynhf1ec5262014-06-25 22:03:18 +0800706 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
707 else
708 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800709 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
710 MI->flat_insn->detail->x86.op_count++;
711 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800712 }
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800713
714 //if (MI->op1_size == 0)
715 // MI->op1_size = MI->imm_size;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800716 }
717}
718
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800719static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800720{
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800721 bool NeedPlus = false;
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800722 MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
723 uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
724 MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
725 MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
726 MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800727 int reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800728
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800729 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700730 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800731 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800732 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700733 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
734 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
735 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
736 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800737 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800738
739 // If this has a segment register, print it.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800740 reg = MCOperand_getReg(SegReg);
741 if (reg) {
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800742 _printOperand(MI, Op + X86_AddrSegmentReg, O);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800743 if (MI->csh->detail) {
744 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
745 }
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800746 SStream_concat0(O, ":");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800747 }
748
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800749 SStream_concat0(O, "[");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800750
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800751 if (MCOperand_getReg(BaseReg)) {
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800752 _printOperand(MI, Op + X86_AddrBaseReg, O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800753 NeedPlus = true;
754 }
755
756 if (MCOperand_getReg(IndexReg)) {
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800757 if (NeedPlus) SStream_concat0(O, " + ");
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800758 _printOperand(MI, Op + X86_AddrIndexReg, O);
Nguyen Anh Quynhf9e32162013-12-05 21:58:31 +0800759 if (ScaleVal != 1)
760 SStream_concat(O, "*%u", ScaleVal);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800761 NeedPlus = true;
762 }
763
Nguyen Anh Quynhb87f8552014-11-02 23:38:35 +0800764 if (MCOperand_isImm(DispSpec)) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800765 int64_t DispVal = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800766 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700767 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
Nguyen Anh Quynhb87f8552014-11-02 23:38:35 +0800768 if (DispVal) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800769 if (NeedPlus) {
Nguyen Anh Quynhb87f8552014-11-02 23:38:35 +0800770 if (DispVal < 0) {
771 if (DispVal < -HEX_THRESHOLD)
772 SStream_concat(O, " - 0x%"PRIx64, -DispVal);
773 else
774 SStream_concat(O, " - %"PRIu64, -DispVal);
775 } else {
776 if (DispVal > HEX_THRESHOLD)
777 SStream_concat(O, " + 0x%"PRIx64, DispVal);
778 else
779 SStream_concat(O, " + %"PRIu64, DispVal);
780 }
781 } else {
782 // memory reference to an immediate address
783 if (DispVal < 0) {
784 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
785 } else {
786 if (DispVal > HEX_THRESHOLD)
787 SStream_concat(O, "0x%"PRIx64, DispVal);
788 else
789 SStream_concat(O, "%"PRIu64, DispVal);
790 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800791 }
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800792
Nguyen Anh Quynhb87f8552014-11-02 23:38:35 +0800793 } else {
794 // DispVal = 0
795 if (!NeedPlus) // [0]
796 SStream_concat0(O, "0");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800797 }
798 }
799
Nguyen Anh Quynhb76233c2014-06-04 18:31:02 +0800800 SStream_concat0(O, "]");
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800801
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800802 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700803 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynhff7bba32014-11-03 16:32:06 +0800804
805 if (MI->op1_size == 0)
806 MI->op1_size = MI->x86opsize;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800807}
808
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800809#define GET_REGINFO_ENUM
810#include "X86GenRegisterInfo.inc"
811
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800812#define PRINT_ALIAS_INSTR
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800813#ifdef CAPSTONE_X86_REDUCE
814#include "X86GenAsmWriter1_reduce.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800815#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800816#include "X86GenAsmWriter1.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800817#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800818
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +0800819#endif