blob: 09b5670b601215cf55a0239a085154d72f1f03b7 [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 Quynh2d342512014-05-11 15:33:11 +080015/* Capstone Disassembly Engine */
16/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080017
18#include <ctype.h>
19#include <inttypes.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "../../utils.h"
25#include "../../MCInst.h"
26#include "../../SStream.h"
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +080027#include "../../MCRegisterInfo.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080028
Nguyen Anh Quynhf328f302014-01-20 09:47:21 +080029#include "X86Mapping.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080030
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080031#define GET_INSTRINFO_ENUM
32#ifdef CAPSTONE_X86_REDUCE
33#include "X86GenInstrInfo_reduce.inc"
34#else
35#include "X86GenInstrInfo.inc"
36#endif
37
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080038static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +080039static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080040
41static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
42{
Nguyen Anh Quynh38c13222014-01-19 17:23:08 +080043 SStream_concat(O, "ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080044 printMemReference(MI, OpNo, O);
45}
46
47static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
48{
49 SStream_concat(O, "byte ptr ");
50 printMemReference(MI, OpNo, O);
51}
52
53static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
54{
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080055 if (MI->Opcode == X86_BOUNDS16rm)
56 SStream_concat(O, "dword ptr ");
57 else
58 SStream_concat(O, "word ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080059 printMemReference(MI, OpNo, O);
60}
61
62static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
63{
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080064 if (MI->Opcode == X86_BOUNDS32rm)
65 SStream_concat(O, "qword ptr ");
66 else
67 SStream_concat(O, "dword ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080068 printMemReference(MI, OpNo, O);
69}
70
71static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
72{
73 SStream_concat(O, "qword ptr ");
74 printMemReference(MI, OpNo, O);
75}
76
77static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
78{
79 SStream_concat(O, "xmmword ptr ");
80 printMemReference(MI, OpNo, O);
81}
82
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +080083#ifndef CAPSTONE_X86_REDUCE
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080084static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
85{
86 SStream_concat(O, "ymmword ptr ");
87 printMemReference(MI, OpNo, O);
88}
89
90static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
91{
92 SStream_concat(O, "zmmword ptr ");
93 printMemReference(MI, OpNo, O);
94}
95
96static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
97{
98 SStream_concat(O, "dword ptr ");
99 printMemReference(MI, OpNo, O);
100}
101
102static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
103{
104 SStream_concat(O, "qword ptr ");
105 printMemReference(MI, OpNo, O);
106}
107
108static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
109{
110 SStream_concat(O, "xword ptr ");
111 printMemReference(MI, OpNo, O);
112}
113
114static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
115{
116 SStream_concat(O, "xmmword ptr ");
117 printMemReference(MI, OpNo, O);
118}
119
120static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
121{
122 SStream_concat(O, "ymmword ptr ");
123 printMemReference(MI, OpNo, O);
124}
125
126static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
127{
128 SStream_concat(O, "zmmword ptr ");
129 printMemReference(MI, OpNo, O);
130}
131
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800132static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
133{
134 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
135 switch (Imm) {
136 default: break; // never reach
137 case 0: SStream_concat(OS, "eq"); break;
138 case 1: SStream_concat(OS, "lt"); break;
139 case 2: SStream_concat(OS, "le"); break;
140 case 3: SStream_concat(OS, "unord"); break;
141 case 4: SStream_concat(OS, "neq"); break;
142 case 5: SStream_concat(OS, "nlt"); break;
143 case 6: SStream_concat(OS, "nle"); break;
144 case 7: SStream_concat(OS, "ord"); break;
145 case 8: SStream_concat(OS, "eq_uq"); break;
146 case 9: SStream_concat(OS, "nge"); break;
147 case 0xa: SStream_concat(OS, "ngt"); break;
148 case 0xb: SStream_concat(OS, "false"); break;
149 case 0xc: SStream_concat(OS, "neq_oq"); break;
150 case 0xd: SStream_concat(OS, "ge"); break;
151 case 0xe: SStream_concat(OS, "gt"); break;
152 case 0xf: SStream_concat(OS, "true"); break;
153 }
154}
155
156static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
157{
158 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
159 switch (Imm) {
160 default: break;//printf("Invalid avxcc argument!\n"); break;
161 case 0: SStream_concat(O, "eq"); break;
162 case 1: SStream_concat(O, "lt"); break;
163 case 2: SStream_concat(O, "le"); break;
164 case 3: SStream_concat(O, "unord"); break;
165 case 4: SStream_concat(O, "neq"); break;
166 case 5: SStream_concat(O, "nlt"); break;
167 case 6: SStream_concat(O, "nle"); break;
168 case 7: SStream_concat(O, "ord"); break;
169 case 8: SStream_concat(O, "eq_uq"); break;
170 case 9: SStream_concat(O, "nge"); break;
171 case 0xa: SStream_concat(O, "ngt"); break;
172 case 0xb: SStream_concat(O, "false"); break;
173 case 0xc: SStream_concat(O, "neq_oq"); break;
174 case 0xd: SStream_concat(O, "ge"); break;
175 case 0xe: SStream_concat(O, "gt"); break;
176 case 0xf: SStream_concat(O, "true"); break;
177 case 0x10: SStream_concat(O, "eq_os"); break;
178 case 0x11: SStream_concat(O, "lt_oq"); break;
179 case 0x12: SStream_concat(O, "le_oq"); break;
180 case 0x13: SStream_concat(O, "unord_s"); break;
181 case 0x14: SStream_concat(O, "neq_us"); break;
182 case 0x15: SStream_concat(O, "nlt_uq"); break;
183 case 0x16: SStream_concat(O, "nle_uq"); break;
184 case 0x17: SStream_concat(O, "ord_s"); break;
185 case 0x18: SStream_concat(O, "eq_us"); break;
186 case 0x19: SStream_concat(O, "nge_uq"); break;
187 case 0x1a: SStream_concat(O, "ngt_uq"); break;
188 case 0x1b: SStream_concat(O, "false_os"); break;
189 case 0x1c: SStream_concat(O, "neq_os"); break;
190 case 0x1d: SStream_concat(O, "ge_oq"); break;
191 case 0x1e: SStream_concat(O, "gt_oq"); break;
192 case 0x1f: SStream_concat(O, "true_us"); break;
193 }
194}
195
196static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
197{
198 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
199 switch (Imm) {
200 case 0: SStream_concat(O, "{rn-sae}"); break;
201 case 1: SStream_concat(O, "{rd-sae}"); break;
202 case 2: SStream_concat(O, "{ru-sae}"); break;
203 case 3: SStream_concat(O, "{rz-sae}"); break;
204 default: break; // never reach
205 }
206}
207
208#endif
209
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800210static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
211{
212 MCOperand *SegReg;
213
214 SegReg = MCInst_getOperand(MI, Op+1);
215
216 // If this has a segment register, print it.
217 if (MCOperand_getReg(SegReg)) {
218 printOperand(MI, Op+1, O);
219 SStream_concat(O, ":");
220 }
221
222 SStream_concat(O, "[");
223 printOperand(MI, Op, O);
224 SStream_concat(O, "]");
225}
226
227static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
228{
229 // DI accesses are always ES-based.
230 SStream_concat(O, "es:[");
231 printOperand(MI, Op, O);
232 SStream_concat(O, "]");
233}
234
235void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
236{
237 SStream_concat(O, "byte ptr ");
238 printSrcIdx(MI, OpNo, O);
239}
240
241void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
242{
243 SStream_concat(O, "word ptr ");
244 printSrcIdx(MI, OpNo, O);
245}
246
247void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
248{
249 SStream_concat(O, "dword ptr ");
250 printSrcIdx(MI, OpNo, O);
251}
252
253void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
254{
255 SStream_concat(O, "qword ptr ");
256 printSrcIdx(MI, OpNo, O);
257}
258
259void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
260{
261 SStream_concat(O, "byte ptr ");
262 printDstIdx(MI, OpNo, O);
263}
264
265void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
266{
267 SStream_concat(O, "word ptr ");
268 printDstIdx(MI, OpNo, O);
269}
270
271void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
272{
273 SStream_concat(O, "dword ptr ");
274 printDstIdx(MI, OpNo, O);
275}
276
277void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
278{
279 SStream_concat(O, "qword ptr ");
280 printDstIdx(MI, OpNo, O);
281}
282
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800283static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
284{
285 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800286 MCOperand *SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800287
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800288 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800289 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_MEM;
290 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.base = X86_REG_INVALID;
291 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.index = X86_REG_INVALID;
292 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.scale = 1;
293 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800294 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800295
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800296 // If this has a segment register, print it.
297 if (MCOperand_getReg(SegReg)) {
298 printOperand(MI, Op+1, O);
299 SStream_concat(O, ":");
300 }
301
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800302 SStream_concat(O, "[");
303
304 if (MCOperand_isImm(DispSpec)) {
305 int64_t imm = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800306 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800307 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = imm;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800308 if (imm < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800309 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800310 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800311 if (imm > HEX_THRESHOLD)
312 SStream_concat(O, "0x%"PRIx64, imm);
313 else
314 SStream_concat(O, "%"PRIu64, imm);
315 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800316 }
317
318 SStream_concat(O, "]");
319
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800320 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800321 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800322}
323
324static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
325{
326 SStream_concat(O, "byte ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800327
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800328 printMemOffset(MI, OpNo, O);
329}
330
331static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
332{
333 SStream_concat(O, "word ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800334
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800335 printMemOffset(MI, OpNo, O);
336
337}
338
339static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
340{
341 SStream_concat(O, "dword ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800342
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800343 printMemOffset(MI, OpNo, O);
344}
345
346static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
347{
348 SStream_concat(O, "qword ptr ");
349 printMemOffset(MI, OpNo, O);
350}
351
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800352static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +0800353static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800354void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
355{
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800356 char *mnem;
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800357 x86_reg reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800358
Nguyen Anh Quynh005c5142014-02-18 11:11:46 +0800359 // Try to print any aliases first.
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800360 mnem = printAliasInstr(MI, O, NULL);
361 if (mnem)
362 cs_mem_free(mnem);
363 else
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +0800364 printInstruction(MI, O, NULL);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800365
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800366 if (MI->csh->detail) {
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800367 // first op can be embedded in the asm by llvm.
368 // so we have to handle that case to not miss the first op.
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800369 reg = X86_insn_reg(MCInst_getOpcode(MI));
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800370 if (reg) {
371 // shift all the ops right to leave 1st slot for this new register op
372 memmove(&(MI->flat_insn.x86.operands[1]), &(MI->flat_insn.x86.operands[0]),
373 sizeof(MI->flat_insn.x86.operands[0]) * (ARR_SIZE(MI->flat_insn.x86.operands) - 1));
374 MI->flat_insn.x86.operands[0].type = X86_OP_REG;
375 MI->flat_insn.x86.operands[0].reg = reg;
376 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800377 }
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800378
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800379 }
380}
381
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800382/// printPCRelImm - This is used to print an immediate value that ends up
383/// being encoded as a pc-relative value.
384static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
385{
386 MCOperand *Op = MCInst_getOperand(MI, OpNo);
387 if (MCOperand_isImm(Op)) {
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800388 int64_t imm = MCOperand_getImm(Op) + MI->insn_size + MI->address;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800389 if (imm < 0) {
Nguyen Anh Quynh017df602014-03-20 15:38:51 +0800390 if (imm < -HEX_THRESHOLD)
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800391 SStream_concat(O, "-0x%"PRIx64, -imm);
392 else
393 SStream_concat(O, "-%"PRIu64, -imm);
394 } else {
Nguyen Anh Quynh2d342512014-05-11 15:33:11 +0800395 // handle 16bit segment bound
396 if (MI->csh->mode == CS_MODE_16 && imm > 0x100000)
397 imm -= 0x10000;
398
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800399 if (imm > HEX_THRESHOLD)
400 SStream_concat(O, "0x%"PRIx64, imm);
401 else
402 SStream_concat(O, "%"PRIu64, imm);
403 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800404 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800405 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_IMM;
406 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].imm = imm;
407 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800408 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800409 }
410}
411
Nguyen Anh Quynh9dfdae62014-01-19 22:40:31 +0800412static char *getRegisterName(unsigned RegNo);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800413static void printRegName(SStream *OS, unsigned RegNo)
414{
415 SStream_concat(OS, getRegisterName(RegNo));
416}
417
418static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
419{
420 MCOperand *Op = MCInst_getOperand(MI, OpNo);
421 if (MCOperand_isReg(Op)) {
422 printRegName(O, MCOperand_getReg(Op));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800423 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800424 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_REG;
425 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].reg = MCOperand_getReg(Op);
426 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800427 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800428 } else if (MCOperand_isImm(Op)) {
429 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynh94990c92013-12-13 15:56:08 +0800430 if (imm >= 0) {
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800431 if (imm > HEX_THRESHOLD)
432 SStream_concat(O, "0x%"PRIx64, imm);
433 else
434 SStream_concat(O, "%"PRIu64, imm);
435 } else {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800436 if (imm < -HEX_THRESHOLD)
437 SStream_concat(O, "-0x%"PRIx64, -imm);
438 else
439 SStream_concat(O, "-%"PRIu64, -imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800440 }
441
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800442 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800443 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_IMM;
444 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].imm = imm;
445 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800446 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800447 }
448}
449
450// local printOperand, without updating public operands
451static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
452{
453 MCOperand *Op = MCInst_getOperand(MI, OpNo);
454 if (MCOperand_isReg(Op)) {
455 printRegName(O, MCOperand_getReg(Op));
456 } else if (MCOperand_isImm(Op)) {
457 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800458 if (imm < 0) {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800459 if (imm < -HEX_THRESHOLD)
460 SStream_concat(O, "-0x%"PRIx64, -imm);
461 else
462 SStream_concat(O, "-%"PRIu64, -imm);
463
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800464 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800465 if (imm > HEX_THRESHOLD)
466 SStream_concat(O, "0x%"PRIx64, imm);
467 else
468 SStream_concat(O, "%"PRIu64, imm);
469 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800470 }
471}
472
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800473static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800474{
475 MCOperand *BaseReg = MCInst_getOperand(MI, Op);
Alex Ionescu46018db2014-01-22 09:45:00 -0800476 uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800477 MCOperand *IndexReg = MCInst_getOperand(MI, Op+2);
478 MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
479 MCOperand *SegReg = MCInst_getOperand(MI, Op+4);
480
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800481 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800482 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_MEM;
483 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.base = MCOperand_getReg(BaseReg);
484 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.index = MCOperand_getReg(IndexReg);
Alex Ionescu46018db2014-01-22 09:45:00 -0800485 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.scale = (int)ScaleVal;
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800486 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800487 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800488
489 // If this has a segment register, print it.
490 if (MCOperand_getReg(SegReg)) {
491 _printOperand(MI, Op+4, O);
492 SStream_concat(O, ":");
493 }
494
495 SStream_concat(O, "[");
496
497 bool NeedPlus = false;
498 if (MCOperand_getReg(BaseReg)) {
499 _printOperand(MI, Op, O);
500 NeedPlus = true;
501 }
502
503 if (MCOperand_getReg(IndexReg)) {
504 if (NeedPlus) SStream_concat(O, " + ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800505 _printOperand(MI, Op+2, O);
Nguyen Anh Quynhf9e32162013-12-05 21:58:31 +0800506 if (ScaleVal != 1)
507 SStream_concat(O, "*%u", ScaleVal);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800508 NeedPlus = true;
509 }
510
511 if (!MCOperand_isImm(DispSpec)) {
512 if (NeedPlus) SStream_concat(O, " + ");
513 //assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
514 } else {
515 int64_t DispVal = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800516 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800517 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = DispVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800518 if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
519 if (NeedPlus) {
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800520 SStream_concat(O, " + ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800521 }
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800522
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800523 if (DispVal < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800524 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800525 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800526 if (DispVal > HEX_THRESHOLD)
527 SStream_concat(O, "0x%"PRIx64, DispVal);
528 else
529 SStream_concat(O, "%"PRIu64, DispVal);
530 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800531 }
532 }
533
534 SStream_concat(O, "]");
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800535
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800536 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800537 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800538}
539
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800540#define PRINT_ALIAS_INSTR
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800541#ifdef CAPSTONE_X86_REDUCE
542#include "X86GenAsmWriter1_reduce.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800543#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800544#include "X86GenAsmWriter1.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800545#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800546