blob: 0ebc41d264b5865e8fc05407eba0edd2866c0247 [file] [log] [blame]
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001//===-- X86ATTInstPrinter.cpp - AT&T 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 AT&T-style
11// assembly.
12//
13//===----------------------------------------------------------------------===//
14
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +080015/* Capstone Disassembly Engine */
16/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
17
Nguyen Anh Quynhf7850262014-05-14 22:03:06 +080018// this code is only relevant when DIET mode is disable
baguette86e84502014-08-17 20:59:05 +020019#if defined(CAPSTONE_HAS_X86) && !defined(CAPSTONE_DIET) && !defined(CAPSTONE_X86_ATT_DISABLE)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080020
21#include <ctype.h>
22#include <inttypes.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include "../../utils.h"
28#include "../../MCInst.h"
29#include "../../SStream.h"
30#include "../../MCRegisterInfo.h"
Nguyen Anh Quynhf328f302014-01-20 09:47:21 +080031#include "X86Mapping.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080032
33#define markup(x) ""
34
35
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080036#define GET_INSTRINFO_ENUM
37#ifdef CAPSTONE_X86_REDUCE
38#include "X86GenInstrInfo_reduce.inc"
39#else
40#include "X86GenInstrInfo.inc"
41#endif
42
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080043static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +080044static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080045
46static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
47{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080048 printMemReference(MI, OpNo, O);
49}
50
51static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
52{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080053 printMemReference(MI, OpNo, O);
54}
55
56static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
57{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080058 printMemReference(MI, OpNo, O);
59}
60
61static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
62{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080063 printMemReference(MI, OpNo, O);
64}
65
66static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
67{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080068 printMemReference(MI, OpNo, O);
69}
70
71static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
72{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080073 printMemReference(MI, OpNo, O);
74}
75
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +080076#ifndef CAPSTONE_X86_REDUCE
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080077static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
78{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080079 printMemReference(MI, OpNo, O);
80}
81
82static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
83{
84 printMemReference(MI, OpNo, O);
85}
86
87static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
88{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080089 printMemReference(MI, OpNo, O);
90}
91
92static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
93{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080094 printMemReference(MI, OpNo, O);
95}
96
97static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
98{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080099 printMemReference(MI, OpNo, O);
100}
101
102static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
103{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800104 printMemReference(MI, OpNo, O);
105}
106
107static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
108{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800109 printMemReference(MI, OpNo, O);
110}
111
112static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
113{
114 printMemReference(MI, OpNo, O);
115}
116
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800117static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
118{
119 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
120 switch (Imm) {
121 default: break; // never reach
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700122 case 0: SStream_concat0(OS, "eq"); break;
123 case 1: SStream_concat0(OS, "lt"); break;
124 case 2: SStream_concat0(OS, "le"); break;
125 case 3: SStream_concat0(OS, "unord"); break;
126 case 4: SStream_concat0(OS, "neq"); break;
127 case 5: SStream_concat0(OS, "nlt"); break;
128 case 6: SStream_concat0(OS, "nle"); break;
129 case 7: SStream_concat0(OS, "ord"); break;
130 case 8: SStream_concat0(OS, "eq_uq"); break;
131 case 9: SStream_concat0(OS, "nge"); break;
132 case 0xa: SStream_concat0(OS, "ngt"); break;
133 case 0xb: SStream_concat0(OS, "false"); break;
134 case 0xc: SStream_concat0(OS, "neq_oq"); break;
135 case 0xd: SStream_concat0(OS, "ge"); break;
136 case 0xe: SStream_concat0(OS, "gt"); break;
137 case 0xf: SStream_concat0(OS, "true"); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800138 }
139}
140
141static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
142{
143 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
144 switch (Imm) {
145 default: break;//printf("Invalid avxcc argument!\n"); break;
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700146 case 0: SStream_concat0(O, "eq"); break;
147 case 1: SStream_concat0(O, "lt"); break;
148 case 2: SStream_concat0(O, "le"); break;
149 case 3: SStream_concat0(O, "unord"); break;
150 case 4: SStream_concat0(O, "neq"); break;
151 case 5: SStream_concat0(O, "nlt"); break;
152 case 6: SStream_concat0(O, "nle"); break;
153 case 7: SStream_concat0(O, "ord"); break;
154 case 8: SStream_concat0(O, "eq_uq"); break;
155 case 9: SStream_concat0(O, "nge"); break;
156 case 0xa: SStream_concat0(O, "ngt"); break;
157 case 0xb: SStream_concat0(O, "false"); break;
158 case 0xc: SStream_concat0(O, "neq_oq"); break;
159 case 0xd: SStream_concat0(O, "ge"); break;
160 case 0xe: SStream_concat0(O, "gt"); break;
161 case 0xf: SStream_concat0(O, "true"); break;
162 case 0x10: SStream_concat0(O, "eq_os"); break;
163 case 0x11: SStream_concat0(O, "lt_oq"); break;
164 case 0x12: SStream_concat0(O, "le_oq"); break;
165 case 0x13: SStream_concat0(O, "unord_s"); break;
166 case 0x14: SStream_concat0(O, "neq_us"); break;
167 case 0x15: SStream_concat0(O, "nlt_uq"); break;
168 case 0x16: SStream_concat0(O, "nle_uq"); break;
169 case 0x17: SStream_concat0(O, "ord_s"); break;
170 case 0x18: SStream_concat0(O, "eq_us"); break;
171 case 0x19: SStream_concat0(O, "nge_uq"); break;
172 case 0x1a: SStream_concat0(O, "ngt_uq"); break;
173 case 0x1b: SStream_concat0(O, "false_os"); break;
174 case 0x1c: SStream_concat0(O, "neq_os"); break;
175 case 0x1d: SStream_concat0(O, "ge_oq"); break;
176 case 0x1e: SStream_concat0(O, "gt_oq"); break;
177 case 0x1f: SStream_concat0(O, "true_us"); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800178 }
179}
180
181static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
182{
183 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
184 switch (Imm) {
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700185 case 0: SStream_concat0(O, "{rn-sae}"); break;
186 case 1: SStream_concat0(O, "{rd-sae}"); break;
187 case 2: SStream_concat0(O, "{ru-sae}"); break;
188 case 3: SStream_concat0(O, "{rz-sae}"); break;
189 default: break; // nev0er reach
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800190 }
191}
192
193#endif
194
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800195static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
196{
197 MCOperand *SegReg;
198
199 SegReg = MCInst_getOperand(MI, Op+1);
200
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700201 SStream_concat0(O, markup("<mem:"));
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800202
203 // If this has a segment register, print it.
204 if (MCOperand_getReg(SegReg)) {
205 printOperand(MI, Op+1, O);
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700206 SStream_concat0(O, ":");
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800207 }
208
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700209 SStream_concat0(O, "(");
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800210
211 printOperand(MI, Op, O);
212
213 SStream_concat(O, ")%s", markup(">"));
214}
215
216static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
217{
218 SStream_concat(O, "%s%s", markup("<mem:"), "%es:(");
219 printOperand(MI, Op, O);
220
221 SStream_concat(O, ")%s", markup(">"));
222}
223
224static void printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
225{
226 printSrcIdx(MI, OpNo, O);
227}
228
229static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
230{
231 printSrcIdx(MI, OpNo, O);
232}
233
234static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
235{
236 printSrcIdx(MI, OpNo, O);
237}
238
239static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
240{
241 printSrcIdx(MI, OpNo, O);
242}
243
244static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
245{
246 printDstIdx(MI, OpNo, O);
247}
248
249static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
250{
251 printDstIdx(MI, OpNo, O);
252}
253
254static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
255{
256 printDstIdx(MI, OpNo, O);
257}
258
259static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
260{
261 printDstIdx(MI, OpNo, O);
262}
263
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800264static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
265{
266 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800267 MCOperand *SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800268
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700269 SStream_concat0(O, markup("<mem:"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800270
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800271 // If this has a segment register, print it.
272 if (MCOperand_getReg(SegReg)) {
273 printOperand(MI, Op+1, O);
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700274 SStream_concat0(O, ":");
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800275 }
276
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800277 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700278 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
279 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
280 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
281 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
282 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800283 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800284
285 if (MCOperand_isImm(DispSpec)) {
286 int64_t imm = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800287 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700288 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800289 if (imm < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800290 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800291 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800292 if (imm > HEX_THRESHOLD)
293 SStream_concat(O, "0x%"PRIx64, imm);
294 else
295 SStream_concat(O, "%"PRIu64, imm);
296 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800297 }
298
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700299 SStream_concat0(O, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800300
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800301 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700302 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800303}
304
305static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
306{
307 printMemOffset(MI, OpNo, O);
308}
309
310static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
311{
312 printMemOffset(MI, OpNo, O);
313}
314
315static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
316{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800317 printMemOffset(MI, OpNo, O);
318}
319
320static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
321{
322 printMemOffset(MI, OpNo, O);
323}
324
325static void printRegName(SStream *OS, unsigned RegNo);
326
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800327/// printPCRelImm - This is used to print an immediate value that ends up
328/// being encoded as a pc-relative value (e.g. for jumps and calls). These
329/// print slightly differently than normal immediates. For example, a $ is not
330/// emitted.
331static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
332{
333 MCOperand *Op = MCInst_getOperand(MI, OpNo);
334 if (MCOperand_isImm(Op)) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700335 int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address;
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800336 if (imm < 0) {
Nguyen Anh Quynh017df602014-03-20 15:38:51 +0800337 if (imm < -HEX_THRESHOLD)
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800338 SStream_concat(O, "-0x%"PRIx64, -imm);
339 else
340 SStream_concat(O, "-%"PRIu64, -imm);
341 } else {
Nguyen Anh Quynh2d342512014-05-11 15:33:11 +0800342 // handle 16bit segment bound
343 if (MI->csh->mode == CS_MODE_16 && imm > 0x100000)
344 imm -= 0x10000;
345
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800346 if (imm > HEX_THRESHOLD)
347 SStream_concat(O, "0x%"PRIx64, imm);
348 else
349 SStream_concat(O, "%"PRIu64, imm);
350 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800351 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700352 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
353 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
354 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800355 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800356 }
357}
358
359static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
360{
361 MCOperand *Op = MCInst_getOperand(MI, OpNo);
362 if (MCOperand_isReg(Op)) {
363 printRegName(O, MCOperand_getReg(Op));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800364 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700365 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
366 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = MCOperand_getReg(Op);
367 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800368 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800369 } else if (MCOperand_isImm(Op)) {
370 // Print X86 immediates as signed values.
371 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynh94990c92013-12-13 15:56:08 +0800372 if (imm >= 0) {
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800373 if (imm > HEX_THRESHOLD)
374 SStream_concat(O, "%s$0x%"PRIx64"%s", markup("<imm:"), imm, markup(">"));
375 else
376 SStream_concat(O, "%s$%"PRIu64"%s", markup("<imm:"), imm, markup(">"));
377 } else {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800378 if (imm < -HEX_THRESHOLD)
379 SStream_concat(O, "%s$-0x%"PRIx64"%s", markup("<imm:"), -imm, markup(">"));
380 else
381 SStream_concat(O, "%s$-%"PRIu64"%s", markup("<imm:"), -imm, markup(">"));
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800382 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800383 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700384 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
385 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
386 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800387 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800388 }
389}
390
391// local printOperand, without updating public operands
392static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
393{
394 MCOperand *Op = MCInst_getOperand(MI, OpNo);
395 if (MCOperand_isReg(Op)) {
396 printRegName(O, MCOperand_getReg(Op));
397 } else if (MCOperand_isImm(Op)) {
398 // Print X86 immediates as signed values.
399 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800400 if (imm < 0) {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800401 if (imm < -HEX_THRESHOLD)
402 SStream_concat(O, "%s$-0x%"PRIx64"%s", markup("<imm:"), -imm, markup(">"));
403 else
404 SStream_concat(O, "%s$-%"PRIu64"%s", markup("<imm:"), -imm, markup(">"));
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800405 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800406 if (imm > HEX_THRESHOLD)
407 SStream_concat(O, "%s$0x%"PRIx64"%s", markup("<imm:"), imm, markup(">"));
408 else
409 SStream_concat(O, "%s$%"PRIu64"%s", markup("<imm:"), imm, markup(">"));
410 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800411 }
412}
413
414static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
415{
416 MCOperand *BaseReg = MCInst_getOperand(MI, Op);
417 MCOperand *IndexReg = MCInst_getOperand(MI, Op+2);
418 MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
419 MCOperand *SegReg = MCInst_getOperand(MI, Op+4);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +0800420 uint64_t ScaleVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800421
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800422 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700423 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
424 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
425 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
426 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
427 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800428 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800429
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700430 SStream_concat0(O, markup("<mem:"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800431
432 // If this has a segment register, print it.
433 if (MCOperand_getReg(SegReg)) {
434 _printOperand(MI, Op+4, O);
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700435 SStream_concat0(O, ":");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800436 }
437
438 if (MCOperand_isImm(DispSpec)) {
439 int64_t DispVal = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800440 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700441 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = DispVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800442 if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800443 if (DispVal < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800444 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800445 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800446 if (DispVal > HEX_THRESHOLD)
447 SStream_concat(O, "0x%"PRIx64, DispVal);
448 else
449 SStream_concat(O, "%"PRIu64, DispVal);
450 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800451 }
452 }
453
454 if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700455 SStream_concat0(O, "(");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800456
457 if (MCOperand_getReg(BaseReg))
458 _printOperand(MI, Op, O);
459
460 if (MCOperand_getReg(IndexReg)) {
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700461 SStream_concat0(O, ", ");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800462 _printOperand(MI, Op+2, O);
Axel 0vercl0k Souchet779d4c72014-05-08 23:44:49 +0100463 ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800464 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700465 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800466 if (ScaleVal != 1) {
467 SStream_concat(O, ", %s%u%s", markup("<imm:"), ScaleVal, markup(">"));
468 }
469 }
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700470 SStream_concat0(O, ")");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800471 }
472
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700473 SStream_concat0(O, markup(">"));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800474
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800475 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700476 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800477}
478
479#include "X86InstPrinter.h"
480
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800481#define GET_REGINFO_ENUM
482#include "X86GenRegisterInfo.inc"
483
484// Include the auto-generated portion of the assembly writer.
485#define PRINT_ALIAS_INSTR
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800486#ifdef CAPSTONE_X86_REDUCE
487#include "X86GenAsmWriter_reduce.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800488#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800489#include "X86GenAsmWriter.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800490#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800491
492static void printRegName(SStream *OS, unsigned RegNo)
493{
494 SStream_concat(OS, "%s%%%s%s", markup("<reg:"), getRegisterName(RegNo), markup(">"));
495}
496
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800497void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
498{
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800499 char *mnem;
500 unsigned int i;
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800501 x86_reg reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800502
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800503 // Try to print any aliases first.
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800504 mnem = printAliasInstr(MI, OS, NULL);
505 if (mnem)
506 cs_mem_free(mnem);
507 else
Nguyen Anh Quynh005c5142014-02-18 11:11:46 +0800508 printInstruction(MI, OS, NULL);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800509
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800510 if (MI->csh->detail) {
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800511 // special instruction needs to supply register op
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800512 reg = X86_insn_reg(MCInst_getOpcode(MI));
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800513 if (reg) {
514 // add register operand
515 for (i = 0;; i++) {
516 // find the first empty slot to put it there
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700517 if (MI->flat_insn->detail->x86.operands[i].type == 0) {
518 MI->flat_insn->detail->x86.operands[i].type = X86_OP_REG;
519 MI->flat_insn->detail->x86.operands[i].reg = reg;
520 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800521 break;
522 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800523 }
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800524
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800525 }
526 }
527}
528
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +0800529#endif