blob: f1d797f4e301f386135acf6eb2285c60ab13abad [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
49 // find the first space
50 strcpy(tmp, code);
51 p = strchr(tmp, ' ');
52 if (p) {
53 p++;
54 // find the next ','
55 p2 = strchr(p, ',');
56 if (p2) {
57 *p2 = '\0';
58 id = XCore_reg_id(p);
59 if (id) {
60 // register
61 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
62 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
63 MI->flat_insn.xcore.op_count++;
64 }
65 // next should be register, or memory?
66 // skip space
67 p2++;
68 while(*p2 && *p2 == ' ')
69 p2++;
70 if (*p2) {
71 // find '['
72 p = p2;
73 while(*p && *p != '[')
74 p++;
75 if (*p) {
76 // this is '['
77 *p = '\0';
78 id = XCore_reg_id(p2);
79 if (id) {
80 // base register
81 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
82 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = id;
83 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
84 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
85 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = 1;
86
87 p++;
88 p2 = p;
89 // until ']'
90 while(*p && *p != ']')
91 p++;
92 if (*p) {
93 *p = '\0';
94 // p2 is either index, or disp
95 id = XCore_reg_id(p2);
96 if (id) {
97 // index register
98 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = id;
99 } else {
100 // a number means disp
101 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = atoi(p2);
102 }
103 }
104
105 MI->flat_insn.xcore.op_count++;
106 }
107 } else {
108 // a register?
109 id = XCore_reg_id(p2);
110 if (id) {
111 // register
112 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
113 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
114 MI->flat_insn.xcore.op_count++;
115 }
116 }
117 }
118 } else {
119 id = XCore_reg_id(p);
120 if (id) {
121 // register
122 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
123 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
124 MI->flat_insn.xcore.op_count++;
125 }
126 }
127 }
128}
129
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800130static void set_mem_access(MCInst *MI, bool status, int reg)
131{
132 if (MI->csh->detail != CS_OPT_ON)
133 return;
134
135 MI->csh->doing_mem = status;
136 if (status) {
137 if (reg != 0xffff && reg != -0xffff) {
138 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
139 if (reg) {
140 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = reg;
141 } else {
142 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = XCORE_REG_INVALID;
143 }
144 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
145 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
Nguyen Anh Quynh553bb482014-05-26 23:47:04 +0800146 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = 1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800147 } else {
148 // the last op should be the memory base
149 MI->flat_insn.xcore.op_count--;
150 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
151 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;
152 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
153 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
154 if (reg > 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
Nguyen Anh Quynh553bb482014-05-26 23:47:04 +0800157 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = -1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800158 }
159 } else {
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800160 if (reg) {
161 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = reg;
162 }
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800163 // done, create the next operand slot
164 MI->flat_insn.xcore.op_count++;
165 }
166}
167
168static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
169{
170 if (MCOperand_isReg(MO)) {
171 unsigned reg;
172
173 reg = MCOperand_getReg(MO);
174 SStream_concat(O, "%s", getRegisterName(reg));
175
176 if (MI->csh->detail) {
177 if (MI->csh->doing_mem) {
178 if (MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base == ARM_REG_INVALID)
179 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = reg;
180 else
181 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = reg;
182 } else {
183 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
184 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = reg;
185 MI->flat_insn.xcore.op_count++;
186 }
187 }
188 } else if (MCOperand_isImm(MO)) {
189 int32_t Imm = (int32_t)MCOperand_getImm(MO);
190
191 if (Imm >= 0) {
192 if (Imm > HEX_THRESHOLD)
193 SStream_concat(O, "0x%x", Imm);
194 else
195 SStream_concat(O, "%u", Imm);
196 } else {
197 if (Imm < -HEX_THRESHOLD)
198 SStream_concat(O, "-0x%x", -Imm);
199 else
200 SStream_concat(O, "-%u", -Imm);
201 }
202
203 if (MI->csh->detail) {
204 if (MI->csh->doing_mem) {
205 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = Imm;
206 } else {
207 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_IMM;
208 MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].imm = Imm;
209 MI->flat_insn.xcore.op_count++;
210 }
211 }
212 }
213}
214
215static void printOperand(MCInst *MI, int OpNum, SStream *O)
216{
217 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
218}
219
220static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
221{
222}
223
224static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
225{
226}
227
228#define PRINT_ALIAS_INSTR
229#include "XCoreGenAsmWriter.inc"
230
231void XCore_printInst(MCInst *MI, SStream *O, void *Info)
232{
233 printInstruction(MI, O, Info);
234}
235
236#endif