blob: b71ae8e203d2e6442b3f6cc14c4ca98695294e5e [file] [log] [blame]
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +08001//===-- XCoreInstPrinter.cpp - Convert XCore MCInst to assembly syntax --------===//
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 class prints an XCore MCInst to a .s file.
11//
12//===----------------------------------------------------------------------===//
13
14/* Capstone Disassembly Engine */
15/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
16
17#ifdef CAPSTONE_HAS_XCORE
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <inttypes.h>
23
24#include "XCoreInstPrinter.h"
25#include "../../MCInst.h"
26#include "../../utils.h"
27#include "../../SStream.h"
28#include "../../MCRegisterInfo.h"
29#include "../../MathExtras.h"
30#include "XCoreMapping.h"
31
32static const char *getRegisterName(unsigned RegNo);
33
34void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
35{
36 /*
37 if (((cs_struct *)ud)->detail != CS_OPT_ON)
38 return;
39 */
40}
41
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080042// stw sed, sp[3]
43void XCore_insn_extract(MCInst *MI, char *code)
44{
45 int id;
46 char *p, *p2;
47 char tmp[128];
48
Nguyen Anh Quynh2a33afe2014-05-28 00:24:33 +080049// make MSVC shutup on strncpy()
50#ifdef _MSC_VER
51#pragma warning(push)
52#pragma warning(disable : 4996)
53#endif
54 strncpy(tmp, code, strlen(code)); // safe because code is way shorter than 128 bytes
55#ifdef _MSC_VER
56#pragma warning(pop)
57#endif
58
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080059 // find the first space
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080060 p = strchr(tmp, ' ');
61 if (p) {
62 p++;
63 // find the next ','
64 p2 = strchr(p, ',');
65 if (p2) {
66 *p2 = '\0';
67 id = XCore_reg_id(p);
68 if (id) {
69 // register
70 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
71 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
72 MI->flat_insn.xcore.op_count++;
73 }
74 // next should be register, or memory?
75 // skip space
76 p2++;
77 while(*p2 && *p2 == ' ')
78 p2++;
79 if (*p2) {
80 // find '['
81 p = p2;
82 while(*p && *p != '[')
83 p++;
84 if (*p) {
85 // this is '['
86 *p = '\0';
87 id = XCore_reg_id(p2);
88 if (id) {
89 // base register
90 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
91 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = id;
92 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
93 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
94 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = 1;
95
96 p++;
97 p2 = p;
98 // until ']'
99 while(*p && *p != ']')
100 p++;
101 if (*p) {
102 *p = '\0';
103 // p2 is either index, or disp
104 id = XCore_reg_id(p2);
105 if (id) {
106 // index register
107 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = id;
108 } else {
109 // a number means disp
110 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = atoi(p2);
111 }
112 }
113
114 MI->flat_insn.xcore.op_count++;
115 }
116 } else {
117 // a register?
118 id = XCore_reg_id(p2);
119 if (id) {
120 // register
121 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
122 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
123 MI->flat_insn.xcore.op_count++;
124 }
125 }
126 }
127 } else {
128 id = XCore_reg_id(p);
129 if (id) {
130 // register
131 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
132 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
133 MI->flat_insn.xcore.op_count++;
134 }
135 }
136 }
137}
138
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800139static void set_mem_access(MCInst *MI, bool status, int reg)
140{
141 if (MI->csh->detail != CS_OPT_ON)
142 return;
143
144 MI->csh->doing_mem = status;
145 if (status) {
146 if (reg != 0xffff && reg != -0xffff) {
147 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
148 if (reg) {
149 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = reg;
150 } else {
151 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = XCORE_REG_INVALID;
152 }
153 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
154 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
Nguyen Anh Quynh553bb482014-05-26 23:47:04 +0800155 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = 1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800156 } else {
157 // the last op should be the memory base
158 MI->flat_insn.xcore.op_count--;
159 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
160 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg;
161 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
162 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
163 if (reg > 0)
Nguyen Anh Quynh553bb482014-05-26 23:47:04 +0800164 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = 1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800165 else
Nguyen Anh Quynh553bb482014-05-26 23:47:04 +0800166 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = -1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800167 }
168 } else {
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800169 if (reg) {
170 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = reg;
171 }
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800172 // done, create the next operand slot
173 MI->flat_insn.xcore.op_count++;
174 }
175}
176
177static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
178{
179 if (MCOperand_isReg(MO)) {
180 unsigned reg;
181
182 reg = MCOperand_getReg(MO);
183 SStream_concat(O, "%s", getRegisterName(reg));
184
185 if (MI->csh->detail) {
186 if (MI->csh->doing_mem) {
187 if (MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base == ARM_REG_INVALID)
188 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = reg;
189 else
190 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = reg;
191 } else {
192 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
193 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = reg;
194 MI->flat_insn.xcore.op_count++;
195 }
196 }
197 } else if (MCOperand_isImm(MO)) {
198 int32_t Imm = (int32_t)MCOperand_getImm(MO);
199
200 if (Imm >= 0) {
201 if (Imm > HEX_THRESHOLD)
202 SStream_concat(O, "0x%x", Imm);
203 else
204 SStream_concat(O, "%u", Imm);
205 } else {
206 if (Imm < -HEX_THRESHOLD)
207 SStream_concat(O, "-0x%x", -Imm);
208 else
209 SStream_concat(O, "-%u", -Imm);
210 }
211
212 if (MI->csh->detail) {
213 if (MI->csh->doing_mem) {
214 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = Imm;
215 } else {
216 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_IMM;
217 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].imm = Imm;
218 MI->flat_insn.xcore.op_count++;
219 }
220 }
221 }
222}
223
224static void printOperand(MCInst *MI, int OpNum, SStream *O)
225{
226 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
227}
228
229static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
230{
231}
232
233static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
234{
235}
236
237#define PRINT_ALIAS_INSTR
238#include "XCoreGenAsmWriter.inc"
239
240void XCore_printInst(MCInst *MI, SStream *O, void *Info)
241{
242 printInstruction(MI, O, Info);
243}
244
245#endif