blob: c050c581ea279c1d16c1273f48e644f80f7af5a2 [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 */
Nguyen Anh Quynhbfcaba52015-03-04 17:45:23 +080015/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +080016
17#ifdef CAPSTONE_HAS_XCORE
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
tandasat45e5eab2016-05-11 21:48:32 -070022#include <capstone/platform.h>
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +080023
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
Nguyen Anh Quynh88fca422014-06-16 14:30:19 +080032static char *getRegisterName(unsigned RegNo);
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +080033
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]
Nguyen Anh Quynh3a5965e2014-05-28 15:14:28 +080043void XCore_insn_extract(MCInst *MI, const char *code)
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080044{
45 int id;
46 char *p, *p2;
47 char tmp[128];
48
Nguyen Anh Quynhb2e566a2014-05-28 11:35:19 +080049// make MSVC shut up on strcpy()
Nguyen Anh Quynh2a33afe2014-05-28 00:24:33 +080050#ifdef _MSC_VER
51#pragma warning(push)
52#pragma warning(disable : 4996)
53#endif
Nguyen Anh Quynhb2e566a2014-05-28 11:35:19 +080054 strcpy(tmp, code); // safe because code is way shorter than 128 bytes
Nguyen Anh Quynh2a33afe2014-05-28 00:24:33 +080055#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
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +070070 if (MI->csh->detail) {
71 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
72 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
73 MI->flat_insn->detail->xcore.op_count++;
74 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080075 }
76 // next should be register, or memory?
77 // skip space
78 p2++;
79 while(*p2 && *p2 == ' ')
80 p2++;
81 if (*p2) {
82 // find '['
83 p = p2;
84 while(*p && *p != '[')
85 p++;
86 if (*p) {
87 // this is '['
88 *p = '\0';
89 id = XCore_reg_id(p2);
90 if (id) {
91 // base register
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +070092 if (MI->csh->detail) {
93 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
tandasat45e5eab2016-05-11 21:48:32 -070094 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id;
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +070095 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
96 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
97 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
98 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +080099
100 p++;
101 p2 = p;
102 // until ']'
103 while(*p && *p != ']')
104 p++;
105 if (*p) {
106 *p = '\0';
107 // p2 is either index, or disp
108 id = XCore_reg_id(p2);
109 if (id) {
110 // index register
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700111 if (MI->csh->detail) {
tandasat45e5eab2016-05-11 21:48:32 -0700112 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id;
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700113 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800114 } else {
115 // a number means disp
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700116 if (MI->csh->detail) {
117 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = atoi(p2);
118 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800119 }
120 }
121
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700122 if (MI->csh->detail) {
123 MI->flat_insn->detail->xcore.op_count++;
124 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800125 }
126 } else {
127 // a register?
128 id = XCore_reg_id(p2);
129 if (id) {
130 // register
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700131 if (MI->csh->detail) {
132 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
133 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
134 MI->flat_insn->detail->xcore.op_count++;
135 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800136 }
137 }
138 }
139 } else {
140 id = XCore_reg_id(p);
141 if (id) {
142 // register
Nguyen Anh Quynhb95647d2014-06-09 18:49:37 +0700143 if (MI->csh->detail) {
144 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
145 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
146 MI->flat_insn->detail->xcore.op_count++;
147 }
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800148 }
149 }
150 }
151}
152
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800153static void set_mem_access(MCInst *MI, bool status, int reg)
154{
155 if (MI->csh->detail != CS_OPT_ON)
156 return;
157
158 MI->csh->doing_mem = status;
159 if (status) {
160 if (reg != 0xffff && reg != -0xffff) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700161 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800162 if (reg) {
tandasat45e5eab2016-05-11 21:48:32 -0700163 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800164 } else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700165 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800166 }
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700167 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
168 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
169 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800170 } else {
171 // the last op should be the memory base
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700172 MI->flat_insn->detail->xcore.op_count--;
173 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
tandasat45e5eab2016-05-11 21:48:32 -0700174 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;
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700175 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
176 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800177 if (reg > 0)
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700178 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800179 else
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700180 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800181 }
182 } else {
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800183 if (reg) {
tandasat45e5eab2016-05-11 21:48:32 -0700184 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
Nguyen Anh Quynh22bc86f2015-06-06 12:30:14 +0800185 // done, create the next operand slot
186 MI->flat_insn->detail->xcore.op_count++;
Nguyen Anh Quynhbe2b7882014-05-27 23:34:03 +0800187 }
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800188 }
189}
190
191static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
192{
193 if (MCOperand_isReg(MO)) {
194 unsigned reg;
195
196 reg = MCOperand_getReg(MO);
Nguyen Anh Quynh88fca422014-06-16 14:30:19 +0800197 SStream_concat0(O, getRegisterName(reg));
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800198
199 if (MI->csh->detail) {
200 if (MI->csh->doing_mem) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700201 if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID)
tandasat45e5eab2016-05-11 21:48:32 -0700202 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800203 else
tandasat45e5eab2016-05-11 21:48:32 -0700204 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800205 } else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700206 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
207 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = reg;
208 MI->flat_insn->detail->xcore.op_count++;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800209 }
210 }
211 } else if (MCOperand_isImm(MO)) {
212 int32_t Imm = (int32_t)MCOperand_getImm(MO);
213
214 if (Imm >= 0) {
215 if (Imm > HEX_THRESHOLD)
216 SStream_concat(O, "0x%x", Imm);
217 else
218 SStream_concat(O, "%u", Imm);
219 } else {
220 if (Imm < -HEX_THRESHOLD)
221 SStream_concat(O, "-0x%x", -Imm);
222 else
223 SStream_concat(O, "-%u", -Imm);
224 }
225
226 if (MI->csh->detail) {
227 if (MI->csh->doing_mem) {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700228 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800229 } else {
Nguyen Anh Quynh29fd0f62014-06-09 08:00:18 +0700230 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM;
231 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm;
232 MI->flat_insn->detail->xcore.op_count++;
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800233 }
234 }
235 }
236}
237
238static void printOperand(MCInst *MI, int OpNum, SStream *O)
239{
Nguyen Anh Quynh22278ec2014-11-17 22:59:24 +0800240 if (OpNum >= MI->size)
241 return;
242
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800243 _printOperand(MI, MCInst_getOperand(MI, OpNum), O);
244}
245
246static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
247{
248}
249
250static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
251{
252}
253
254#define PRINT_ALIAS_INSTR
255#include "XCoreGenAsmWriter.inc"
256
257void XCore_printInst(MCInst *MI, SStream *O, void *Info)
258{
259 printInstruction(MI, O, Info);
Nguyen Anh Quynhf16c9bd2015-06-05 18:06:22 +0800260 set_mem_access(MI, false, 0);
Nguyen Anh Quynhc80d8402014-05-26 23:02:48 +0800261}
262
263#endif