1 //===-- 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-2015 */
16
17 #ifdef CAPSTONE_HAS_XCORE
18
19 #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
20 #pragma warning(disable : 4996) // disable MSVC's warning on strcpy()
21 #pragma warning(disable : 28719) // disable MSVC's warning on strcpy()
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <capstone/platform.h>
28
29 #include "XCoreInstPrinter.h"
30 #include "../../MCInst.h"
31 #include "../../utils.h"
32 #include "../../SStream.h"
33 #include "../../MCRegisterInfo.h"
34 #include "../../MathExtras.h"
35 #include "XCoreMapping.h"
36
37 static const char *getRegisterName(unsigned RegNo);
38
XCore_post_printer(csh ud,cs_insn * insn,char * insn_asm,MCInst * mci)39 void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
40 {
41 /*
42 if (((cs_struct *)ud)->detail != CS_OPT_ON)
43 return;
44 */
45 }
46
47 // stw sed, sp[3]
XCore_insn_extract(MCInst * MI,const char * code)48 void XCore_insn_extract(MCInst *MI, const char *code)
49 {
50 int id;
51 char *p, *p2;
52 char tmp[128];
53
54 strcpy(tmp, code); // safe because code is way shorter than 128 bytes
55
56 // find the first space
57 p = strchr(tmp, ' ');
58 if (p) {
59 p++;
60 // find the next ','
61 p2 = strchr(p, ',');
62 if (p2) {
63 *p2 = '\0';
64 id = XCore_reg_id(p);
65 if (id) {
66 // register
67 if (MI->csh->detail) {
68 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
69 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
70 MI->flat_insn->detail->xcore.op_count++;
71 }
72 }
73 // next should be register, or memory?
74 // skip space
75 p2++;
76 while(*p2 && *p2 == ' ')
77 p2++;
78 if (*p2) {
79 // find '['
80 p = p2;
81 while(*p && *p != '[')
82 p++;
83 if (*p) {
84 // this is '['
85 *p = '\0';
86 id = XCore_reg_id(p2);
87 if (id) {
88 // base register
89 if (MI->csh->detail) {
90 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
91 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id;
92 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
93 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
94 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
95 }
96
97 p++;
98 p2 = p;
99 // until ']'
100 while(*p && *p != ']')
101 p++;
102 if (*p) {
103 *p = '\0';
104 // p2 is either index, or disp
105 id = XCore_reg_id(p2);
106 if (id) {
107 // index register
108 if (MI->csh->detail) {
109 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id;
110 }
111 } else {
112 // a number means disp
113 if (MI->csh->detail) {
114 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = atoi(p2);
115 }
116 }
117 }
118
119 if (MI->csh->detail) {
120 MI->flat_insn->detail->xcore.op_count++;
121 }
122 }
123 } else {
124 // a register?
125 id = XCore_reg_id(p2);
126 if (id) {
127 // register
128 if (MI->csh->detail) {
129 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
130 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
131 MI->flat_insn->detail->xcore.op_count++;
132 }
133 }
134 }
135 }
136 } else {
137 id = XCore_reg_id(p);
138 if (id) {
139 // register
140 if (MI->csh->detail) {
141 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
142 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
143 MI->flat_insn->detail->xcore.op_count++;
144 }
145 }
146 }
147 }
148 }
149
set_mem_access(MCInst * MI,bool status,int reg)150 static void set_mem_access(MCInst *MI, bool status, int reg)
151 {
152 if (MI->csh->detail != CS_OPT_ON)
153 return;
154
155 MI->csh->doing_mem = status;
156 if (status) {
157 if (reg != 0xffff && reg != -0xffff) {
158 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
159 if (reg) {
160 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
161 } else {
162 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID;
163 }
164 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
165 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
166 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
167 } else {
168 // the last op should be the memory base
169 MI->flat_insn->detail->xcore.op_count--;
170 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
171 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg;
172 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
173 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
174 if (reg > 0)
175 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
176 else
177 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1;
178 }
179 } else {
180 if (reg) {
181 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
182 // done, create the next operand slot
183 MI->flat_insn->detail->xcore.op_count++;
184 }
185 }
186 }
187
_printOperand(MCInst * MI,MCOperand * MO,SStream * O)188 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
189 {
190 if (MCOperand_isReg(MO)) {
191 unsigned reg;
192
193 reg = MCOperand_getReg(MO);
194 SStream_concat0(O, getRegisterName(reg));
195
196 if (MI->csh->detail) {
197 if (MI->csh->doing_mem) {
198 if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID)
199 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
200 else
201 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
202 } else {
203 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
204 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = reg;
205 MI->flat_insn->detail->xcore.op_count++;
206 }
207 }
208 } else if (MCOperand_isImm(MO)) {
209 int32_t Imm = (int32_t)MCOperand_getImm(MO);
210
211 printInt32(O, Imm);
212
213 if (MI->csh->detail) {
214 if (MI->csh->doing_mem) {
215 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm;
216 } else {
217 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM;
218 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm;
219 MI->flat_insn->detail->xcore.op_count++;
220 }
221 }
222 }
223 }
224
printOperand(MCInst * MI,int OpNum,SStream * O)225 static void printOperand(MCInst *MI, int OpNum, SStream *O)
226 {
227 if (OpNum >= MI->size)
228 return;
229
230 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
231 }
232
printInlineJT(MCInst * MI,int OpNum,SStream * O)233 static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
234 {
235 }
236
printInlineJT32(MCInst * MI,int OpNum,SStream * O)237 static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
238 {
239 }
240
241 #define PRINT_ALIAS_INSTR
242 #include "XCoreGenAsmWriter.inc"
243
XCore_printInst(MCInst * MI,SStream * O,void * Info)244 void XCore_printInst(MCInst *MI, SStream *O, void *Info)
245 {
246 printInstruction(MI, O, Info);
247 set_mem_access(MI, false, 0);
248 }
249
250 #endif
251