Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 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 */ |
Nguyen Anh Quynh | bfcaba5 | 2015-03-04 17:45:23 +0800 | [diff] [blame] | 15 | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */ |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 16 | |
| 17 | #ifdef CAPSTONE_HAS_XCORE |
| 18 | |
| 19 | #include <stdio.h> |
| 20 | #include <stdlib.h> |
| 21 | #include <string.h> |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 22 | #include <capstone/platform.h> |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 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 | |
Nguyen Anh Quynh | 88fca42 | 2014-06-16 14:30:19 +0800 | [diff] [blame] | 32 | static char *getRegisterName(unsigned RegNo); |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 33 | |
| 34 | void 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 42 | // stw sed, sp[3] |
Nguyen Anh Quynh | 3a5965e | 2014-05-28 15:14:28 +0800 | [diff] [blame] | 43 | void XCore_insn_extract(MCInst *MI, const char *code) |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 44 | { |
| 45 | int id; |
| 46 | char *p, *p2; |
| 47 | char tmp[128]; |
| 48 | |
Nguyen Anh Quynh | b2e566a | 2014-05-28 11:35:19 +0800 | [diff] [blame] | 49 | // make MSVC shut up on strcpy() |
Nguyen Anh Quynh | 2a33afe | 2014-05-28 00:24:33 +0800 | [diff] [blame] | 50 | #ifdef _MSC_VER |
| 51 | #pragma warning(push) |
| 52 | #pragma warning(disable : 4996) |
| 53 | #endif |
Nguyen Anh Quynh | b2e566a | 2014-05-28 11:35:19 +0800 | [diff] [blame] | 54 | strcpy(tmp, code); // safe because code is way shorter than 128 bytes |
Nguyen Anh Quynh | 2a33afe | 2014-05-28 00:24:33 +0800 | [diff] [blame] | 55 | #ifdef _MSC_VER |
| 56 | #pragma warning(pop) |
| 57 | #endif |
| 58 | |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 59 | // find the first space |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 60 | 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 Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 70 | 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 75 | } |
| 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 Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 92 | if (MI->csh->detail) { |
| 93 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM; |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 94 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id; |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 95 | 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 99 | |
| 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 Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 111 | if (MI->csh->detail) { |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 112 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id; |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 113 | } |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 114 | } else { |
| 115 | // a number means disp |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 116 | 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 122 | if (MI->csh->detail) { |
| 123 | MI->flat_insn->detail->xcore.op_count++; |
| 124 | } |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 125 | } |
| 126 | } else { |
| 127 | // a register? |
| 128 | id = XCore_reg_id(p2); |
| 129 | if (id) { |
| 130 | // register |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 131 | 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 136 | } |
| 137 | } |
| 138 | } |
| 139 | } else { |
| 140 | id = XCore_reg_id(p); |
| 141 | if (id) { |
| 142 | // register |
Nguyen Anh Quynh | b95647d | 2014-06-09 18:49:37 +0700 | [diff] [blame] | 143 | 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 Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 148 | } |
| 149 | } |
| 150 | } |
| 151 | } |
| 152 | |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 153 | static 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 Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 161 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 162 | if (reg) { |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 163 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 164 | } else { |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 165 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 166 | } |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 167 | 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 Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 170 | } else { |
| 171 | // the last op should be the memory base |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 172 | 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; |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 174 | 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 Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 175 | 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 Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 177 | if (reg > 0) |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 178 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 179 | else |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 180 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 181 | } |
| 182 | } else { |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 183 | if (reg) { |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 184 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg; |
Nguyen Anh Quynh | 22bc86f | 2015-06-06 12:30:14 +0800 | [diff] [blame] | 185 | // done, create the next operand slot |
| 186 | MI->flat_insn->detail->xcore.op_count++; |
Nguyen Anh Quynh | be2b788 | 2014-05-27 23:34:03 +0800 | [diff] [blame] | 187 | } |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 188 | } |
| 189 | } |
| 190 | |
| 191 | static 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 Quynh | 88fca42 | 2014-06-16 14:30:19 +0800 | [diff] [blame] | 197 | SStream_concat0(O, getRegisterName(reg)); |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 198 | |
| 199 | if (MI->csh->detail) { |
| 200 | if (MI->csh->doing_mem) { |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 201 | if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID) |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 202 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 203 | else |
tandasat | 45e5eab | 2016-05-11 21:48:32 -0700 | [diff] [blame^] | 204 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 205 | } else { |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 206 | 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 Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 209 | } |
| 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 Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 228 | MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm; |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 229 | } else { |
Nguyen Anh Quynh | 29fd0f6 | 2014-06-09 08:00:18 +0700 | [diff] [blame] | 230 | 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 Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 233 | } |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | static void printOperand(MCInst *MI, int OpNum, SStream *O) |
| 239 | { |
Nguyen Anh Quynh | 22278ec | 2014-11-17 22:59:24 +0800 | [diff] [blame] | 240 | if (OpNum >= MI->size) |
| 241 | return; |
| 242 | |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 243 | _printOperand(MI, MCInst_getOperand(MI, OpNum), O); |
| 244 | } |
| 245 | |
| 246 | static void printInlineJT(MCInst *MI, int OpNum, SStream *O) |
| 247 | { |
| 248 | } |
| 249 | |
| 250 | static void printInlineJT32(MCInst *MI, int OpNum, SStream *O) |
| 251 | { |
| 252 | } |
| 253 | |
| 254 | #define PRINT_ALIAS_INSTR |
| 255 | #include "XCoreGenAsmWriter.inc" |
| 256 | |
| 257 | void XCore_printInst(MCInst *MI, SStream *O, void *Info) |
| 258 | { |
| 259 | printInstruction(MI, O, Info); |
Nguyen Anh Quynh | f16c9bd | 2015-06-05 18:06:22 +0800 | [diff] [blame] | 260 | set_mem_access(MI, false, 0); |
Nguyen Anh Quynh | c80d840 | 2014-05-26 23:02:48 +0800 | [diff] [blame] | 261 | } |
| 262 | |
| 263 | #endif |