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 (at) gmail.com>, 2013-2014 */ 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 <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 char *getRegisterName(unsigned RegNo); 38 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] 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 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 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 if (Imm >= 0) { 212 if (Imm > HEX_THRESHOLD) 213 SStream_concat(O, "0x%x", Imm); 214 else 215 SStream_concat(O, "%u", Imm); 216 } else { 217 if (Imm < -HEX_THRESHOLD) 218 SStream_concat(O, "-0x%x", -Imm); 219 else 220 SStream_concat(O, "-%u", -Imm); 221 } 222 223 if (MI->csh->detail) { 224 if (MI->csh->doing_mem) { 225 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm; 226 } else { 227 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM; 228 MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm; 229 MI->flat_insn->detail->xcore.op_count++; 230 } 231 } 232 } 233 } 234 235 static void printOperand(MCInst *MI, int OpNum, SStream *O) 236 { 237 if (OpNum >= MI->size) 238 return; 239 240 _printOperand(MI, MCInst_getOperand(MI, OpNum), O); 241 } 242 243 static void printInlineJT(MCInst *MI, int OpNum, SStream *O) 244 { 245 } 246 247 static void printInlineJT32(MCInst *MI, int OpNum, SStream *O) 248 { 249 } 250 251 #define PRINT_ALIAS_INSTR 252 #include "XCoreGenAsmWriter.inc" 253 254 void XCore_printInst(MCInst *MI, SStream *O, void *Info) 255 { 256 printInstruction(MI, O, Info); 257 set_mem_access(MI, false, 0); 258 } 259 260 #endif 261