You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.9 KiB
262 lines
7.9 KiB
//===-- 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 |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include "../../inttypes.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]; |
|
|
|
// make MSVC shut up on strcpy() |
|
#ifdef _MSC_VER |
|
#pragma warning(push) |
|
#pragma warning(disable : 4996) |
|
#endif |
|
strcpy(tmp, code); // safe because code is way shorter than 128 bytes |
|
#ifdef _MSC_VER |
|
#pragma warning(pop) |
|
#endif |
|
|
|
// 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 = 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 = 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 = 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 = 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 = 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 = reg; |
|
else |
|
MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = 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); |
|
} |
|
|
|
#endif
|
|
|