blob: 0fec099babcdde40c61ca17e1aecaf1d7b7d3696 [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
19#if defined(CAPSTONE_HAS_X86) && !defined(CAPSTONE_DIET)
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 Quynh0b690382014-08-13 13:01:50 +080032#include "X86BaseInfo.h"
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080033
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080034
Nguyen Anh Quynhe93179b2014-04-25 11:18:40 +080035#define GET_INSTRINFO_ENUM
36#ifdef CAPSTONE_X86_REDUCE
37#include "X86GenInstrInfo_reduce.inc"
38#else
39#include "X86GenInstrInfo.inc"
40#endif
41
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080042static void printMemReference(MCInst *MI, unsigned Op, SStream *O);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +080043static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080044
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080045
46static void set_mem_access(MCInst *MI, bool status)
47{
48 if (MI->csh->detail != CS_OPT_ON)
49 return;
50
51 MI->csh->doing_mem = status;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +080052 if (!status)
53 // done, create the next operand slot
54 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080055}
56
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080057static void printopaquemem(MCInst *MI, unsigned OpNo, SStream *O)
58{
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080059 printMemReference(MI, OpNo, O);
60}
61
62static void printi8mem(MCInst *MI, unsigned OpNo, SStream *O)
63{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080064 MI->x86opsize = 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080065 printMemReference(MI, OpNo, O);
66}
67
68static void printi16mem(MCInst *MI, unsigned OpNo, SStream *O)
69{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080070 if (MI->Opcode == X86_BOUNDS16rm)
71 MI->x86opsize = 4;
72 else
73 MI->x86opsize = 2;
74
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080075 printMemReference(MI, OpNo, O);
76}
77
78static void printi32mem(MCInst *MI, unsigned OpNo, SStream *O)
79{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080080 if (MI->Opcode == X86_BOUNDS32rm)
81 MI->x86opsize = 8;
82 else
83 MI->x86opsize = 4;
84
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080085 printMemReference(MI, OpNo, O);
86}
87
88static void printi64mem(MCInst *MI, unsigned OpNo, SStream *O)
89{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080090 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080091 printMemReference(MI, OpNo, O);
92}
93
94static void printi128mem(MCInst *MI, unsigned OpNo, SStream *O)
95{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +080096 MI->x86opsize = 16;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080097 printMemReference(MI, OpNo, O);
98}
99
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800100#ifndef CAPSTONE_X86_REDUCE
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800101static void printi256mem(MCInst *MI, unsigned OpNo, SStream *O)
102{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800103 MI->x86opsize = 32;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800104 printMemReference(MI, OpNo, O);
105}
106
107static void printi512mem(MCInst *MI, unsigned OpNo, SStream *O)
108{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800109 MI->x86opsize = 64;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800110 printMemReference(MI, OpNo, O);
111}
112
113static void printf32mem(MCInst *MI, unsigned OpNo, SStream *O)
114{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800115 MI->x86opsize = 4;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800116 printMemReference(MI, OpNo, O);
117}
118
119static void printf64mem(MCInst *MI, unsigned OpNo, SStream *O)
120{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800121 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800122 printMemReference(MI, OpNo, O);
123}
124
125static void printf80mem(MCInst *MI, unsigned OpNo, SStream *O)
126{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800127 MI->x86opsize = 10;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800128 printMemReference(MI, OpNo, O);
129}
130
131static void printf128mem(MCInst *MI, unsigned OpNo, SStream *O)
132{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800133 MI->x86opsize = 16;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800134 printMemReference(MI, OpNo, O);
135}
136
137static void printf256mem(MCInst *MI, unsigned OpNo, SStream *O)
138{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800139 MI->x86opsize = 32;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800140 printMemReference(MI, OpNo, O);
141}
142
143static void printf512mem(MCInst *MI, unsigned OpNo, SStream *O)
144{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800145 MI->x86opsize = 64;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800146 printMemReference(MI, OpNo, O);
147}
148
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800149static void printSSECC(MCInst *MI, unsigned Op, SStream *OS)
150{
151 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0xf;
152 switch (Imm) {
153 default: break; // never reach
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700154 case 0: SStream_concat0(OS, "eq"); break;
155 case 1: SStream_concat0(OS, "lt"); break;
156 case 2: SStream_concat0(OS, "le"); break;
157 case 3: SStream_concat0(OS, "unord"); break;
158 case 4: SStream_concat0(OS, "neq"); break;
159 case 5: SStream_concat0(OS, "nlt"); break;
160 case 6: SStream_concat0(OS, "nle"); break;
161 case 7: SStream_concat0(OS, "ord"); break;
162 case 8: SStream_concat0(OS, "eq_uq"); break;
163 case 9: SStream_concat0(OS, "nge"); break;
164 case 0xa: SStream_concat0(OS, "ngt"); break;
165 case 0xb: SStream_concat0(OS, "false"); break;
166 case 0xc: SStream_concat0(OS, "neq_oq"); break;
167 case 0xd: SStream_concat0(OS, "ge"); break;
168 case 0xe: SStream_concat0(OS, "gt"); break;
169 case 0xf: SStream_concat0(OS, "true"); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800170 }
171}
172
173static void printAVXCC(MCInst *MI, unsigned Op, SStream *O)
174{
175 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x1f;
176 switch (Imm) {
177 default: break;//printf("Invalid avxcc argument!\n"); break;
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700178 case 0: SStream_concat0(O, "eq"); break;
179 case 1: SStream_concat0(O, "lt"); break;
180 case 2: SStream_concat0(O, "le"); break;
181 case 3: SStream_concat0(O, "unord"); break;
182 case 4: SStream_concat0(O, "neq"); break;
183 case 5: SStream_concat0(O, "nlt"); break;
184 case 6: SStream_concat0(O, "nle"); break;
185 case 7: SStream_concat0(O, "ord"); break;
186 case 8: SStream_concat0(O, "eq_uq"); break;
187 case 9: SStream_concat0(O, "nge"); break;
188 case 0xa: SStream_concat0(O, "ngt"); break;
189 case 0xb: SStream_concat0(O, "false"); break;
190 case 0xc: SStream_concat0(O, "neq_oq"); break;
191 case 0xd: SStream_concat0(O, "ge"); break;
192 case 0xe: SStream_concat0(O, "gt"); break;
193 case 0xf: SStream_concat0(O, "true"); break;
194 case 0x10: SStream_concat0(O, "eq_os"); break;
195 case 0x11: SStream_concat0(O, "lt_oq"); break;
196 case 0x12: SStream_concat0(O, "le_oq"); break;
197 case 0x13: SStream_concat0(O, "unord_s"); break;
198 case 0x14: SStream_concat0(O, "neq_us"); break;
199 case 0x15: SStream_concat0(O, "nlt_uq"); break;
200 case 0x16: SStream_concat0(O, "nle_uq"); break;
201 case 0x17: SStream_concat0(O, "ord_s"); break;
202 case 0x18: SStream_concat0(O, "eq_us"); break;
203 case 0x19: SStream_concat0(O, "nge_uq"); break;
204 case 0x1a: SStream_concat0(O, "ngt_uq"); break;
205 case 0x1b: SStream_concat0(O, "false_os"); break;
206 case 0x1c: SStream_concat0(O, "neq_os"); break;
207 case 0x1d: SStream_concat0(O, "ge_oq"); break;
208 case 0x1e: SStream_concat0(O, "gt_oq"); break;
209 case 0x1f: SStream_concat0(O, "true_us"); break;
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800210 }
211}
212
213static void printRoundingControl(MCInst *MI, unsigned Op, SStream *O)
214{
215 int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, Op)) & 0x3;
216 switch (Imm) {
Nguyen Anh Quynh1a66fec2014-06-26 12:09:15 +0800217 case 0: SStream_concat0(O, "{rn-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RN); break;
218 case 1: SStream_concat0(O, "{rd-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RD); break;
219 case 2: SStream_concat0(O, "{ru-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RU); break;
220 case 3: SStream_concat0(O, "{rz-sae}"); op_addAvxSae(MI); op_addAvxRoundingMode(MI, X86_AVX_RM_RZ); break;
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700221 default: break; // nev0er reach
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800222 }
223}
224
225#endif
226
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800227static void printRegName(SStream *OS, unsigned RegNo);
228
229// local printOperand, without updating public operands
230static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
231{
232 MCOperand *Op = MCInst_getOperand(MI, OpNo);
233 if (MCOperand_isReg(Op)) {
234 printRegName(O, MCOperand_getReg(Op));
235 } else if (MCOperand_isImm(Op)) {
236 // Print X86 immediates as signed values.
237 int64_t imm = MCOperand_getImm(Op);
238 if (imm < 0) {
239 if (imm < -HEX_THRESHOLD)
240 SStream_concat(O, "$-0x%"PRIx64, -imm);
241 else
242 SStream_concat(O, "$-%"PRIu64, -imm);
243 } else {
244 if (imm > HEX_THRESHOLD)
245 SStream_concat(O, "$0x%"PRIx64, imm);
246 else
247 SStream_concat(O, "$%"PRIu64, imm);
248 }
249 }
250}
251
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800252static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
253{
254 MCOperand *SegReg;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800255 int reg;
256
257 if (MI->csh->detail) {
258 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
259 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
260 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
261 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
262 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
263 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
264 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
265 }
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800266
267 SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800268 reg = MCOperand_getReg(SegReg);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800269
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800270 // If this has a segment register, print it.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800271 if (reg) {
272 _printOperand(MI, Op+1, O);
273 if (MI->csh->detail) {
274 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
275 }
276
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700277 SStream_concat0(O, ":");
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800278 }
279
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700280 SStream_concat0(O, "(");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800281 set_mem_access(MI, true);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800282
283 printOperand(MI, Op, O);
284
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800285 SStream_concat0(O, ")");
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800286 set_mem_access(MI, false);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800287}
288
289static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
290{
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800291 if (MI->csh->detail) {
292 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
293 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
294 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
295 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
296 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
297 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
298 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
299 }
300
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800301 // DI accesses are always ES-based on non-64bit mode
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800302 if (MI->csh->mode != CS_MODE_64) {
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800303 SStream_concat0(O, "%es:(");
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800304 if (MI->csh->detail) {
305 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_ES;
306 }
307 } else
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800308 SStream_concat0(O, "(");
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800309
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800310 set_mem_access(MI, true);
311
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800312 printOperand(MI, Op, O);
313
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +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 printSrcIdx8(MCInst *MI, unsigned OpNo, SStream *O)
319{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800320 MI->x86opsize = 1;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800321 printSrcIdx(MI, OpNo, O);
322}
323
324static void printSrcIdx16(MCInst *MI, unsigned OpNo, SStream *O)
325{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800326 MI->x86opsize = 2;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800327 printSrcIdx(MI, OpNo, O);
328}
329
330static void printSrcIdx32(MCInst *MI, unsigned OpNo, SStream *O)
331{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800332 MI->x86opsize = 4;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800333 printSrcIdx(MI, OpNo, O);
334}
335
336static void printSrcIdx64(MCInst *MI, unsigned OpNo, SStream *O)
337{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800338 MI->x86opsize = 8;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800339 printSrcIdx(MI, OpNo, O);
340}
341
342static void printDstIdx8(MCInst *MI, unsigned OpNo, SStream *O)
343{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800344 MI->x86opsize = 1;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800345 printDstIdx(MI, OpNo, O);
346}
347
348static void printDstIdx16(MCInst *MI, unsigned OpNo, SStream *O)
349{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800350 MI->x86opsize = 2;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800351 printDstIdx(MI, OpNo, O);
352}
353
354static void printDstIdx32(MCInst *MI, unsigned OpNo, SStream *O)
355{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800356 MI->x86opsize = 4;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800357 printDstIdx(MI, OpNo, O);
358}
359
360static void printDstIdx64(MCInst *MI, unsigned OpNo, SStream *O)
361{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800362 MI->x86opsize = 8;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800363 printDstIdx(MI, OpNo, O);
364}
365
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800366static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
367{
368 MCOperand *DispSpec = MCInst_getOperand(MI, Op);
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800369 MCOperand *SegReg = MCInst_getOperand(MI, Op+1);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800370 int reg;
Nguyen Anh Quynh13f40d22014-02-07 22:06:33 +0800371
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800372 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700373 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 +0800374 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800375 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 +0700376 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = X86_REG_INVALID;
377 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
378 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
379 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800380 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800381
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800382 // If this has a segment register, print it.
383 reg = MCOperand_getReg(SegReg);
384 if (reg) {
385 _printOperand(MI, Op + 1, O);
386 SStream_concat0(O, ":");
387 if (MI->csh->detail) {
388 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
389 }
390 }
391
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800392 if (MCOperand_isImm(DispSpec)) {
393 int64_t imm = MCOperand_getImm(DispSpec);
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800394 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700395 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800396 if (imm < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800397 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & imm);
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800398 } else {
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 Quynh26ee41a2013-11-27 12:11:31 +0800404 }
405
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800406 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700407 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800408}
409
410static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
411{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800412 MI->x86opsize = 1;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800413 printMemOffset(MI, OpNo, O);
414}
415
416static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
417{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800418 MI->x86opsize = 2;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800419 printMemOffset(MI, OpNo, O);
420}
421
422static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
423{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800424 MI->x86opsize = 4;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800425 printMemOffset(MI, OpNo, O);
426}
427
428static void printMemOffs64(MCInst *MI, unsigned OpNo, SStream *O)
429{
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800430 MI->x86opsize = 8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800431 printMemOffset(MI, OpNo, O);
432}
433
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800434/// printPCRelImm - This is used to print an immediate value that ends up
435/// being encoded as a pc-relative value (e.g. for jumps and calls). These
436/// print slightly differently than normal immediates. For example, a $ is not
437/// emitted.
438static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
439{
440 MCOperand *Op = MCInst_getOperand(MI, OpNo);
441 if (MCOperand_isImm(Op)) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700442 int64_t imm = MCOperand_getImm(Op) + MI->flat_insn->size + MI->address;
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800443 if (imm < 0) {
Nguyen Anh Quynh017df602014-03-20 15:38:51 +0800444 if (imm < -HEX_THRESHOLD)
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800445 SStream_concat(O, "-0x%"PRIx64, -imm);
446 else
447 SStream_concat(O, "-%"PRIu64, -imm);
448 } else {
Nguyen Anh Quynh2d342512014-05-11 15:33:11 +0800449 // handle 16bit segment bound
450 if (MI->csh->mode == CS_MODE_16 && imm > 0x100000)
451 imm -= 0x10000;
452
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800453 if (imm > HEX_THRESHOLD)
454 SStream_concat(O, "0x%"PRIx64, imm);
455 else
456 SStream_concat(O, "%"PRIu64, imm);
457 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800458 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700459 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 +0800460 MI->has_imm = 1;
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700461 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
462 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800463 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800464 }
465}
466
467static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
468{
469 MCOperand *Op = MCInst_getOperand(MI, OpNo);
470 if (MCOperand_isReg(Op)) {
471 printRegName(O, MCOperand_getReg(Op));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800472 if (MI->csh->detail) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800473 unsigned int reg = MCOperand_getReg(Op);
474 if (MI->csh->doing_mem) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800475 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800476 } else {
477 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
478 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
479 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
480 MI->flat_insn->detail->x86.op_count++;
481 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800482 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800483 } else if (MCOperand_isImm(Op)) {
484 // Print X86 immediates as signed values.
485 int64_t imm = MCOperand_getImm(Op);
Nguyen Anh Quynh94990c92013-12-13 15:56:08 +0800486 if (imm >= 0) {
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800487 if (imm > HEX_THRESHOLD)
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800488 SStream_concat(O, "$0x%"PRIx64, imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800489 else
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800490 SStream_concat(O, "$%"PRIu64, imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800491 } else {
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800492 if (imm < -HEX_THRESHOLD)
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800493 SStream_concat(O, "$-0x%"PRIx64, -imm);
Nguyen Anh Quynh81a6df42014-04-01 07:23:39 +0800494 else
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800495 SStream_concat(O, "$-%"PRIu64, -imm);
Nguyen Anh Quynhbe906392013-12-13 15:37:57 +0800496 }
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800497 if (MI->csh->detail) {
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800498 if (MI->csh->doing_mem) {
499 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 +0800500 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800501 } else {
502 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 +0800503 MI->has_imm = 1;
Nguyen Anh Quynh10850732014-06-18 12:16:24 +0800504 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
505 MI->flat_insn->detail->x86.op_count++;
506 }
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800507 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800508 }
509}
510
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800511static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
512{
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800513 MCOperand *BaseReg = MCInst_getOperand(MI, Op + X86_AddrBaseReg);
514 MCOperand *IndexReg = MCInst_getOperand(MI, Op + X86_AddrIndexReg);
515 MCOperand *DispSpec = MCInst_getOperand(MI, Op + X86_AddrDisp);
516 MCOperand *SegReg = MCInst_getOperand(MI, Op + X86_AddrSegmentReg);
Nguyen Anh Quynhbb0744d2014-05-12 13:41:49 +0800517 uint64_t ScaleVal;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800518 int reg;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800519
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800520 if (MI->csh->detail) {
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700521 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 +0800522 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800523 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 +0700524 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = MCOperand_getReg(BaseReg);
525 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
526 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
527 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
Nguyen Anh Quynha209e672013-12-14 00:23:41 +0800528 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800529
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800530 // If this has a segment register, print it.
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800531 reg = MCOperand_getReg(SegReg);
532 if (reg) {
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800533 _printOperand(MI, Op + X86_AddrSegmentReg, O);
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800534 if (MI->csh->detail) {
535 MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = reg;
536 }
537
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700538 SStream_concat0(O, ":");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800539 }
540
541 if (MCOperand_isImm(DispSpec)) {
542 int64_t DispVal = MCOperand_getImm(DispSpec);
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].mem.disp = DispVal;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800545 if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800546 if (DispVal < 0) {
Nguyen Anh Quynh6d3d8002014-03-29 17:26:51 +0800547 SStream_concat(O, "0x%"PRIx64, arch_masks[MI->csh->mode] & DispVal);
Nguyen Anh Quynh4fe42812013-12-13 12:26:26 +0800548 } else {
Nguyen Anh Quynhf22557b2013-12-13 09:37:52 +0800549 if (DispVal > HEX_THRESHOLD)
550 SStream_concat(O, "0x%"PRIx64, DispVal);
551 else
552 SStream_concat(O, "%"PRIu64, DispVal);
553 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800554 }
555 }
556
557 if (MCOperand_getReg(IndexReg) || MCOperand_getReg(BaseReg)) {
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700558 SStream_concat0(O, "(");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800559
560 if (MCOperand_getReg(BaseReg))
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800561 _printOperand(MI, Op + X86_AddrBaseReg, O);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800562
563 if (MCOperand_getReg(IndexReg)) {
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700564 SStream_concat0(O, ", ");
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800565 _printOperand(MI, Op + X86_AddrIndexReg, O);
566 ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op + X86_AddrScaleAmt));
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800567 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700568 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 +0800569 if (ScaleVal != 1) {
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800570 SStream_concat(O, ", %u", ScaleVal);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800571 }
572 }
Nguyen Anh Quynha62b9a02014-06-04 22:25:48 +0700573 SStream_concat0(O, ")");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800574 }
575
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800576 if (MI->csh->detail)
Nguyen Anh Quynh5329a6f2014-06-08 23:35:52 +0700577 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800578}
579
580#include "X86InstPrinter.h"
581
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800582#define GET_REGINFO_ENUM
583#include "X86GenRegisterInfo.inc"
584
585// Include the auto-generated portion of the assembly writer.
586#define PRINT_ALIAS_INSTR
Nguyen Anh Quynh59b54892014-03-27 10:54:44 +0800587#ifdef CAPSTONE_X86_REDUCE
588#include "X86GenAsmWriter_reduce.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800589#else
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800590#include "X86GenAsmWriter.inc"
Nguyen Anh Quynh95181482014-03-25 23:20:41 +0800591#endif
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800592
593static void printRegName(SStream *OS, unsigned RegNo)
594{
Nguyen Anh Quynh1e688d42014-06-18 14:28:55 +0800595 SStream_concat(OS, "%%%s", getRegisterName(RegNo));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800596}
597
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800598void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
599{
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800600 char *mnem;
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800601 x86_reg reg;
Nguyen Anh Quynhf1ec5262014-06-25 22:03:18 +0800602 int i;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800603
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800604 // Try to print any aliases first.
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800605 mnem = printAliasInstr(MI, OS, info);
Nguyen Anh Quynh27b9a962014-02-19 10:13:47 +0800606 if (mnem)
607 cs_mem_free(mnem);
608 else
Nguyen Anh Quynh0b690382014-08-13 13:01:50 +0800609 printInstruction(MI, OS, info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800610
Nguyen Anh Quynhf1ec5262014-06-25 22:03:18 +0800611 if (MI->has_imm) {
612 // if op_count > 1, then this operand's size is taken from the destination op
613 if (MI->flat_insn->detail->x86.op_count > 1) {
614 for (i = 0; i < MI->flat_insn->detail->x86.op_count; i++) {
615 if (MI->flat_insn->detail->x86.operands[i].type == X86_OP_IMM)
616 MI->flat_insn->detail->x86.operands[i].size = MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count - 1].size;
617 }
618 } else
619 MI->flat_insn->detail->x86.operands[0].size = MI->imm_size;
620 }
621
Nguyen Anh Quynh42c6b1a2013-12-30 00:15:25 +0800622 if (MI->csh->detail) {
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800623 // special instruction needs to supply register op
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800624 // first op can be embedded in the asm by llvm.
625 // so we have to add the missing register as the first operand
626 reg = X86_insn_reg_att(MCInst_getOpcode(MI));
Nguyen Anh Quynh85cddef2014-02-18 11:59:36 +0800627 if (reg) {
Nguyen Anh Quynh14ba46b2014-06-24 14:32:01 +0800628 // shift all the ops right to leave 1st slot for this new register op
629 memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
630 sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
631 MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
632 MI->flat_insn->detail->x86.operands[0].reg = reg;
633 MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
634 MI->flat_insn->detail->x86.op_count++;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800635 }
636 }
637}
638
Nguyen Anh Quynh8598a212014-05-14 11:26:41 +0800639#endif