blob: 9968eb0dc1985baa5a229c99a83217833393194f [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
15/* Capstone Disassembler Engine */
16/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
17
18#include <ctype.h>
19#include <inttypes.h>
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +010020#include <stdbool.h>
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "../../utils.h"
26#include "../../MCInst.h"
27#include "../../SStream.h"
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +080028#include "../../MCRegisterInfo.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080029
Nguyen Anh Quynhf328f302014-01-20 09:47:21 +080030#include "X86Mapping.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080031
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080032#define GET_INSTRINFO_ENUM
33#ifdef CAPSTONE_X86_REDUCE
34#include "X86GenInstrInfo_reduce.inc"
35#else
36#include "X86GenInstrInfo.inc"
37#endif
38
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080039static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +080040static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080041
42static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
43{
Nguyen Anh Quynh38c13222014-01-19 17:23:08 +080044 SStream_concat(O, "ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080045 printMemReference(MI, OpNo, O);
46}
47
48static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
49{
50 SStream_concat(O, "byte ptr ");
51 printMemReference(MI, OpNo, O);
52}
53
54static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
55{
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080056 if (MI->Opcode == X86_BOUNDS16rm)
57 SStream_concat(O, "dword ptr ");
58 else
59 SStream_concat(O, "word ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080060 printMemReference(MI, OpNo, O);
61}
62
63static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
64{
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080065 if (MI->Opcode == X86_BOUNDS32rm)
66 SStream_concat(O, "qword ptr ");
67 else
68 SStream_concat(O, "dword ptr ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080069 printMemReference(MI, OpNo, O);
70}
71
72static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
73{
74 SStream_concat(O, "qword ptr ");
75 printMemReference(MI, OpNo, O);
76}
77
78static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
79{
80 SStream_concat(O, "xmmword ptr ");
81 printMemReference(MI, OpNo, O);
82}
83
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +080084#ifndef CAPSTONE_X86_REDUCE
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080085static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
86{
87 SStream_concat(O, "ymmword ptr ");
88 printMemReference(MI, OpNo, O);
89}
90
91static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
92{
93 SStream_concat(O, "zmmword ptr ");
94 printMemReference(MI, OpNo, O);
95}
96
97static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
98{
99 SStream_concat(O, "dword ptr ");
100 printMemReference(MI, OpNo, O);
101}
102
103static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
104{
105 SStream_concat(O, "qword ptr ");
106 printMemReference(MI, OpNo, O);
107}
108
109static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
110{
111 SStream_concat(O, "xword ptr ");
112 printMemReference(MI, OpNo, O);
113}
114
115static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
116{
117 SStream_concat(O, "xmmword ptr ");
118 printMemReference(MI, OpNo, O);
119}
120
121static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
122{
123 SStream_concat(O, "ymmword ptr ");
124 printMemReference(MI, OpNo, O);
125}
126
127static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
128{
129 SStream_concat(O, "zmmword ptr ");
130 printMemReference(MI, OpNo, O);
131}
132
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800133static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
134{
135 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
136 switch (Imm) {
137 default: break; // never reach
138 case 0: SStream_concat(OS, "eq"); break;
139 case 1: SStream_concat(OS, "lt"); break;
140 case 2: SStream_concat(OS, "le"); break;
141 case 3: SStream_concat(OS, "unord"); break;
142 case 4: SStream_concat(OS, "neq"); break;
143 case 5: SStream_concat(OS, "nlt"); break;
144 case 6: SStream_concat(OS, "nle"); break;
145 case 7: SStream_concat(OS, "ord"); break;
146 case 8: SStream_concat(OS, "eq_uq"); break;
147 case 9: SStream_concat(OS, "nge"); break;
148 case 0xa: SStream_concat(OS, "ngt"); break;
149 case 0xb: SStream_concat(OS, "false"); break;
150 case 0xc: SStream_concat(OS, "neq_oq"); break;
151 case 0xd: SStream_concat(OS, "ge"); break;
152 case 0xe: SStream_concat(OS, "gt"); break;
153 case 0xf: SStream_concat(OS, "true"); break;
154 }
155}
156
157static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
158{
159 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
160 switch (Imm) {
161 default: break;//printf("Invalid avxcc argument!\n"); break;
162 case 0: SStream_concat(O, "eq"); break;
163 case 1: SStream_concat(O, "lt"); break;
164 case 2: SStream_concat(O, "le"); break;
165 case 3: SStream_concat(O, "unord"); break;
166 case 4: SStream_concat(O, "neq"); break;
167 case 5: SStream_concat(O, "nlt"); break;
168 case 6: SStream_concat(O, "nle"); break;
169 case 7: SStream_concat(O, "ord"); break;
170 case 8: SStream_concat(O, "eq_uq"); break;
171 case 9: SStream_concat(O, "nge"); break;
172 case 0xa: SStream_concat(O, "ngt"); break;
173 case 0xb: SStream_concat(O, "false"); break;
174 case 0xc: SStream_concat(O, "neq_oq"); break;
175 case 0xd: SStream_concat(O, "ge"); break;
176 case 0xe: SStream_concat(O, "gt"); break;
177 case 0xf: SStream_concat(O, "true"); break;
178 case 0x10: SStream_concat(O, "eq_os"); break;
179 case 0x11: SStream_concat(O, "lt_oq"); break;
180 case 0x12: SStream_concat(O, "le_oq"); break;
181 case 0x13: SStream_concat(O, "unord_s"); break;
182 case 0x14: SStream_concat(O, "neq_us"); break;
183 case 0x15: SStream_concat(O, "nlt_uq"); break;
184 case 0x16: SStream_concat(O, "nle_uq"); break;
185 case 0x17: SStream_concat(O, "ord_s"); break;
186 case 0x18: SStream_concat(O, "eq_us"); break;
187 case 0x19: SStream_concat(O, "nge_uq"); break;
188 case 0x1a: SStream_concat(O, "ngt_uq"); break;
189 case 0x1b: SStream_concat(O, "false_os"); break;
190 case 0x1c: SStream_concat(O, "neq_os"); break;
191 case 0x1d: SStream_concat(O, "ge_oq"); break;
192 case 0x1e: SStream_concat(O, "gt_oq"); break;
193 case 0x1f: SStream_concat(O, "true_us"); break;
194 }
195}
196
197static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
198{
199 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
200 switch (Imm) {
201 case 0: SStream_concat(O, "{rn-sae}"); break;
202 case 1: SStream_concat(O, "{rd-sae}"); break;
203 case 2: SStream_concat(O, "{ru-sae}"); break;
204 case 3: SStream_concat(O, "{rz-sae}"); break;
205 default: break; // never reach
206 }
207}
208
209#endif
210
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800211static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
212{
213 MCOperand *SegReg;
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800214
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800215 SegReg = MCInst_getOperand(MI, Op+1);
216
217 // If this has a segment register, print it.
218 if (MCOperand_getReg(SegReg)) {
219 printOperand(MI, Op+1, O);
220 SStream_concat(O, ":");
221 }
222
223 SStream_concat(O, "[");
224 printOperand(MI, Op, O);
225 SStream_concat(O, "]");
226}
227
228static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
229{
230 // DI accesses are always ES-based.
231 SStream_concat(O, "es:[");
232 printOperand(MI, Op, O);
233 SStream_concat(O, "]");
234}
235
236void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
237{
238 SStream_concat(O, "byte ptr ");
239 printSrcIdx(MI, OpNo, O);
240}
241
242void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
243{
244 SStream_concat(O, "word ptr ");
245 printSrcIdx(MI, OpNo, O);
246}
247
248void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
249{
250 SStream_concat(O, "dword ptr ");
251 printSrcIdx(MI, OpNo, O);
252}
253
254void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
255{
256 SStream_concat(O, "qword ptr ");
257 printSrcIdx(MI, OpNo, O);
258}
259
260void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
261{
262 SStream_concat(O, "byte ptr ");
263 printDstIdx(MI, OpNo, O);
264}
265
266void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
267{
268 SStream_concat(O, "word ptr ");
269 printDstIdx(MI, OpNo, O);
270}
271
272void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
273{
274 SStream_concat(O, "dword ptr ");
275 printDstIdx(MI, OpNo, O);
276}
277
278void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
279{
280 SStream_concat(O, "qword ptr ");
281 printDstIdx(MI, OpNo, O);
282}
283
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800284static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
285{
286 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800287 MCOperand *SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800288
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800289 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800290 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_MEM;
291 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.base = X86_REG_INVALID;
292 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.index = X86_REG_INVALID;
293 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.scale = 1;
294 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800295 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800296
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800297 // If this has a segment register, print it.
298 if (MCOperand_getReg(SegReg)) {
299 printOperand(MI, Op+1, O);
300 SStream_concat(O, ":");
301 }
302
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800303 SStream_concat(O, "[");
304
305 if (MCOperand_isImm(DispSpec)) {
306 int64_t imm = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800307 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800308 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = imm;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800309 if (imm < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800310 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800311 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800312 if (imm > HEX_THRESHOLD)
313 SStream_concat(O, "0x%"PRIx64, imm);
314 else
315 SStream_concat(O, "%"PRIu64, imm);
316 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800317 }
318
319 SStream_concat(O, "]");
320
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800321 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800322 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800323}
324
325static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
326{
327 SStream_concat(O, "byte ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800328
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800329 printMemOffset(MI, OpNo, O);
330}
331
332static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
333{
334 SStream_concat(O, "word ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800335
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800336 printMemOffset(MI, OpNo, O);
337
338}
339
340static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
341{
342 SStream_concat(O, "dword ptr ");
Nguyen Anh Quynhb9b3d292013-12-02 16:21:55 +0800343
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800344 printMemOffset(MI, OpNo, O);
345}
346
347static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
348{
349 SStream_concat(O, "qword ptr ");
350 printMemOffset(MI, OpNo, O);
351}
352
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800353static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +0800354static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800355void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
356{
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800357 char *mnem;
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800358 x86_reg reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800359
Nguyen Anh Quynh005c5142014-02-18 11:11:46 +0800360 // Try to print any aliases first.
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800361 mnem = printAliasInstr(MI, O, NULL);
362 if (mnem)
363 cs_mem_free(mnem);
364 else
Nguyen Anh Quynhe51e2272014-01-12 20:27:54 +0800365 printInstruction(MI, O, NULL);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800366
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800367 if (MI->csh->detail) {
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800368 // first op can be embedded in the asm by llvm.
369 // so we have to handle that case to not miss the first op.
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800370 reg = X86_insn_reg(MCInst_getOpcode(MI));
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800371 if (reg) {
372 // shift all the ops right to leave 1st slot for this new register op
373 memmove(&(MI->flat_insn.x86.operands[1]), &(MI->flat_insn.x86.operands[0]),
374 sizeof(MI->flat_insn.x86.operands[0]) * (ARR_SIZE(MI->flat_insn.x86.operands) - 1));
375 MI->flat_insn.x86.operands[0].type = X86_OP_REG;
376 MI->flat_insn.x86.operands[0].reg = reg;
377 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800378 }
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800379
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800380 }
381}
382
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800383/// printPCRelImm - This is used to print an immediate value that ends up
384/// being encoded as a pc-relative value.
385static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
386{
387 MCOperand *Op = MCInst_getOperand(MI, OpNo);
388 if (MCOperand_isImm(Op)) {
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800389 int64_t imm = MCOperand_getImm(Op) + MI->insn_size + MI->address;
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800390 if (imm < 0) {
Nguyen Anh Quynh017df602014-03-20 15:38:51 +0800391 if (imm < -HEX_THRESHOLD)
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800392 SStream_concat(O, "-0x%"PRIx64, -imm);
393 else
394 SStream_concat(O, "-%"PRIu64, -imm);
395 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800396 if (imm > HEX_THRESHOLD)
397 SStream_concat(O, "0x%"PRIx64, imm);
398 else
399 SStream_concat(O, "%"PRIu64, imm);
400 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800401 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800402 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_IMM;
403 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].imm = imm;
404 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800405 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800406 }
407}
408
Nguyen Anh Quynh9dfdae62014-01-19 22:40:31 +0800409static char *getRegisterName(unsigned RegNo);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800410static void printRegName(SStream *OS, unsigned RegNo)
411{
412 SStream_concat(OS, getRegisterName(RegNo));
413}
414
415static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
416{
417 MCOperand *Op = MCInst_getOperand(MI, OpNo);
418 if (MCOperand_isReg(Op)) {
419 printRegName(O, MCOperand_getReg(Op));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800420 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800421 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_REG;
422 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].reg = MCOperand_getReg(Op);
423 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800424 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800425 } else if (MCOperand_isImm(Op)) {
426 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynh94990c92013-12-13 15:56:08 +0800427 if (imm >= 0) {
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800428 if (imm > HEX_THRESHOLD)
429 SStream_concat(O, "0x%"PRIx64, imm);
430 else
431 SStream_concat(O, "%"PRIu64, imm);
432 } else {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800433 if (imm < -HEX_THRESHOLD)
434 SStream_concat(O, "-0x%"PRIx64, -imm);
435 else
436 SStream_concat(O, "-%"PRIu64, -imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800437 }
438
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800439 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800440 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_IMM;
441 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].imm = imm;
442 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800443 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800444 }
445}
446
447// local printOperand, without updating public operands
448static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
449{
450 MCOperand *Op = MCInst_getOperand(MI, OpNo);
451 if (MCOperand_isReg(Op)) {
452 printRegName(O, MCOperand_getReg(Op));
453 } else if (MCOperand_isImm(Op)) {
454 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800455 if (imm < 0) {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800456 if (imm < -HEX_THRESHOLD)
457 SStream_concat(O, "-0x%"PRIx64, -imm);
458 else
459 SStream_concat(O, "-%"PRIu64, -imm);
460
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800461 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800462 if (imm > HEX_THRESHOLD)
463 SStream_concat(O, "0x%"PRIx64, imm);
464 else
465 SStream_concat(O, "%"PRIu64, imm);
466 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800467 }
468}
469
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800470static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800471{
Nguyen Anh Quynh42706a32014-05-09 07:33:35 +0800472 bool NeedPlus = false;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800473 MCOperand *BaseReg = MCInst_getOperand(MI, Op);
Alex Ionescu46018db2014-01-22 09:45:00 -0800474 uint64_t ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800475 MCOperand *IndexReg = MCInst_getOperand(MI, Op+2);
476 MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
477 MCOperand *SegReg = MCInst_getOperand(MI, Op+4);
478
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800479 if (MI->csh->detail) {
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800480 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].type = X86_OP_MEM;
481 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.base = MCOperand_getReg(BaseReg);
482 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.index = MCOperand_getReg(IndexReg);
Alex Ionescu46018db2014-01-22 09:45:00 -0800483 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.scale = (int)ScaleVal;
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800484 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800485 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800486
487 // If this has a segment register, print it.
488 if (MCOperand_getReg(SegReg)) {
489 _printOperand(MI, Op+4, O);
490 SStream_concat(O, ":");
491 }
492
493 SStream_concat(O, "[");
494
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100495 NeedPlus = false;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800496 if (MCOperand_getReg(BaseReg)) {
497 _printOperand(MI, Op, O);
498 NeedPlus = true;
499 }
500
501 if (MCOperand_getReg(IndexReg)) {
502 if (NeedPlus) SStream_concat(O, " + ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800503 _printOperand(MI, Op+2, O);
Nguyen Anh Quynhf9e32162013-12-05 21:58:31 +0800504 if (ScaleVal != 1)
505 SStream_concat(O, "*%u", ScaleVal);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800506 NeedPlus = true;
507 }
508
509 if (!MCOperand_isImm(DispSpec)) {
510 if (NeedPlus) SStream_concat(O, " + ");
511 //assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
512 } else {
513 int64_t DispVal = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800514 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800515 MI->flat_insn.x86.operands[MI->flat_insn.x86.op_count].mem.disp = DispVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800516 if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
517 if (NeedPlus) {
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800518 SStream_concat(O, " + ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800519 }
Nguyen Anh Quynh125f5042014-03-29 12:02:21 +0800520
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800521 if (DispVal < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800522 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800523 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800524 if (DispVal > HEX_THRESHOLD)
525 SStream_concat(O, "0x%"PRIx64, DispVal);
526 else
527 SStream_concat(O, "%"PRIu64, DispVal);
528 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800529 }
530 }
531
532 SStream_concat(O, "]");
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800533
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800534 if (MI->csh->detail)
Nguyen Anh Quynh4fe224b2013-12-24 16:49:36 +0800535 MI->flat_insn.x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800536}
537
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800538#define PRINT_ALIAS_INSTR
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800539#ifdef CAPSTONE_X86_REDUCE
540#include "X86GenAsmWriter1_reduce.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800541#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800542#include "X86GenAsmWriter1.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800543#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800544