//===-- XCoreInstPrinter.cpp - Convert XCore MCInst to assembly syntax --------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This class prints an XCore MCInst to a .s file. // //===----------------------------------------------------------------------===// /* Capstone Disassembly Engine */ /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */ #ifdef CAPSTONE_HAS_XCORE #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64) #pragma warning(disable : 4996) // disable MSVC's warning on strcpy() #pragma warning(disable : 28719) // disable MSVC's warning on strcpy() #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <platform.h> #include "XCoreInstPrinter.h" #include "../../MCInst.h" #include "../../utils.h" #include "../../SStream.h" #include "../../MCRegisterInfo.h" #include "../../MathExtras.h" #include "XCoreMapping.h" static char *getRegisterName(unsigned RegNo); void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci) { /* if (((cs_struct *)ud)->detail != CS_OPT_ON) return; */ } // stw sed, sp[3] void XCore_insn_extract(MCInst *MI, const char *code) { int id; char *p, *p2; char tmp[128]; strcpy(tmp, code); // safe because code is way shorter than 128 bytes // find the first space p = strchr(tmp, ' '); if (p) { p++; // find the next ',' p2 = strchr(p, ','); if (p2) { *p2 = '\0'; id = XCore_reg_id(p); if (id) { // register if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id; MI->flat_insn->detail->xcore.op_count++; } } // next should be register, or memory? // skip space p2++; while(*p2 && *p2 == ' ') p2++; if (*p2) { // find '[' p = p2; while(*p && *p != '[') p++; if (*p) { // this is '[' *p = '\0'; id = XCore_reg_id(p2); if (id) { // base register if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1; } p++; p2 = p; // until ']' while(*p && *p != ']') p++; if (*p) { *p = '\0'; // p2 is either index, or disp id = XCore_reg_id(p2); if (id) { // index register if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id; } } else { // a number means disp if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = atoi(p2); } } } if (MI->csh->detail) { MI->flat_insn->detail->xcore.op_count++; } } } else { // a register? id = XCore_reg_id(p2); if (id) { // register if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id; MI->flat_insn->detail->xcore.op_count++; } } } } } else { id = XCore_reg_id(p); if (id) { // register if (MI->csh->detail) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id; MI->flat_insn->detail->xcore.op_count++; } } } } } static void set_mem_access(MCInst *MI, bool status, int reg) { if (MI->csh->detail != CS_OPT_ON) return; MI->csh->doing_mem = status; if (status) { if (reg != 0xffff && reg != -0xffff) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM; if (reg) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg; } else { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID; } MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1; } else { // the last op should be the memory base MI->flat_insn->detail->xcore.op_count--; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM; 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; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0; if (reg > 0) MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1; else MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1; } } else { if (reg) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg; // done, create the next operand slot MI->flat_insn->detail->xcore.op_count++; } } } static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O) { if (MCOperand_isReg(MO)) { unsigned reg; reg = MCOperand_getReg(MO); SStream_concat0(O, getRegisterName(reg)); if (MI->csh->detail) { if (MI->csh->doing_mem) { if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID) MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg; else MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg; } else { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = reg; MI->flat_insn->detail->xcore.op_count++; } } } else if (MCOperand_isImm(MO)) { int32_t Imm = (int32_t)MCOperand_getImm(MO); if (Imm >= 0) { if (Imm > HEX_THRESHOLD) SStream_concat(O, "0x%x", Imm); else SStream_concat(O, "%u", Imm); } else { if (Imm < -HEX_THRESHOLD) SStream_concat(O, "-0x%x", -Imm); else SStream_concat(O, "-%u", -Imm); } if (MI->csh->detail) { if (MI->csh->doing_mem) { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm; } else { MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM; MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm; MI->flat_insn->detail->xcore.op_count++; } } } } static void printOperand(MCInst *MI, int OpNum, SStream *O) { if (OpNum >= MI->size) return; _printOperand(MI, MCInst_getOperand(MI, OpNum), O); } static void printInlineJT(MCInst *MI, int OpNum, SStream *O) { } static void printInlineJT32(MCInst *MI, int OpNum, SStream *O) { } #define PRINT_ALIAS_INSTR #include "XCoreGenAsmWriter.inc" void XCore_printInst(MCInst *MI, SStream *O, void *Info) { printInstruction(MI, O, Info); set_mem_access(MI, false, 0); } #endif