xcore: handle details for some special tricky instructions

This commit is contained in:
Nguyen Anh Quynh 2014-05-27 23:34:03 +08:00
parent 8c1c36f0fc
commit be2b788dc1
6 changed files with 144 additions and 8 deletions

View File

@ -434,6 +434,8 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)
default: // unreachable.
case 0:
// DBG_VALUE, BUNDLE, LIFETIME_START, LIFETIME_END, CLRE_0R, DCALL_0R, DE...
// already done. this means we have to extract details out ourself.
XCore_insn_extract(MI, AsmStrs+(Bits & 2047)-1);
return;
break;
case 1:
@ -495,35 +497,35 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)
case 7:
// INITCP_2r
SStream_concat(O, "%s", "]:cp, ");
set_mem_access(MI, false, 0);
set_mem_access(MI, false, XCORE_REG_CP);
printOperand(MI, 0, O);
return;
break;
case 8:
// INITDP_2r
SStream_concat(O, "%s", "]:dp, ");
set_mem_access(MI, false, 0);
set_mem_access(MI, false, XCORE_REG_DP);
printOperand(MI, 0, O);
return;
break;
case 9:
// INITLR_l2r
SStream_concat(O, "%s", "]:lr, ");
set_mem_access(MI, false, 0);
set_mem_access(MI, false, XCORE_REG_LR);
printOperand(MI, 0, O);
return;
break;
case 10:
// INITPC_2r
SStream_concat(O, "%s", "]:pc, ");
set_mem_access(MI, false, 0);
set_mem_access(MI, false, XCORE_REG_PC);
printOperand(MI, 0, O);
return;
break;
case 11:
// INITSP_2r
SStream_concat(O, "%s", "]:sp, ");
set_mem_access(MI, false, 0);
set_mem_access(MI, false, XCORE_REG_SP);
printOperand(MI, 0, O);
return;
break;

View File

@ -39,6 +39,94 @@ void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
*/
}
// stw sed, sp[3]
void XCore_insn_extract(MCInst *MI, char *code)
{
int id;
char *p, *p2;
char tmp[128];
// find the first space
strcpy(tmp, code);
p = strchr(tmp, ' ');
if (p) {
p++;
// find the next ','
p2 = strchr(p, ',');
if (p2) {
*p2 = '\0';
id = XCore_reg_id(p);
if (id) {
// register
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
MI->flat_insn.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
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_MEM;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.base = id;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = XCORE_REG_INVALID;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = 0;
MI->flat_insn.xcore.operands[MI->flat_insn.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
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = id;
} else {
// a number means disp
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.disp = atoi(p2);
}
}
MI->flat_insn.xcore.op_count++;
}
} else {
// a register?
id = XCore_reg_id(p2);
if (id) {
// register
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
MI->flat_insn.xcore.op_count++;
}
}
}
} else {
id = XCore_reg_id(p);
if (id) {
// register
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].type = XCORE_OP_REG;
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].reg = id;
MI->flat_insn.xcore.op_count++;
}
}
}
}
static void set_mem_access(MCInst *MI, bool status, int reg)
{
if (MI->csh->detail != CS_OPT_ON)
@ -69,6 +157,9 @@ static void set_mem_access(MCInst *MI, bool status, int reg)
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.direct = -1;
}
} else {
if (reg) {
MI->flat_insn.xcore.operands[MI->flat_insn.xcore.op_count].mem.index = reg;
}
// done, create the next operand slot
MI->flat_insn.xcore.op_count++;
}

View File

@ -12,4 +12,7 @@ void XCore_printInst(MCInst *MI, SStream *O, void *Info);
void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci);
// extract details from assembly code @code
void XCore_insn_extract(MCInst *MI, char *code);
#endif

View File

@ -13,7 +13,6 @@
#define GET_INSTRINFO_ENUM
#include "XCoreGenInstrInfo.inc"
#ifndef CAPSTONE_DIET
static name_map reg_name_maps[] = {
{ XCORE_REG_INVALID, NULL },
@ -33,8 +32,19 @@ static name_map reg_name_maps[] = {
{ XCORE_REG_R9, "r9" },
{ XCORE_REG_R10, "r10" },
{ XCORE_REG_R11, "r11" },
// pseudo registers
{ XCORE_REG_PC, "pc" },
{ XCORE_REG_SCP, "scp" },
{ XCORE_REG_SSR, "ssr" },
{ XCORE_REG_ET, "et" },
{ XCORE_REG_ED, "ed" },
{ XCORE_REG_SED, "sed" },
{ XCORE_REG_KEP, "kep" },
{ XCORE_REG_KSP, "ksp" },
{ XCORE_REG_ID, "id" },
};
#endif
const char *XCore_reg_name(csh handle, unsigned int reg)
{
@ -48,6 +58,19 @@ const char *XCore_reg_name(csh handle, unsigned int reg)
#endif
}
xcore_reg XCore_reg_id(char *name)
{
int i;
for(i = 1; i < ARR_SIZE(reg_name_maps); i++) {
if (!strcmp(name, reg_name_maps[i].name))
return reg_name_maps[i].id;
}
// not found
return 0;
}
static insn_map insns[] = {
// dummy item
{

View File

@ -17,5 +17,8 @@ const char *XCore_insn_name(csh handle, unsigned int id);
// map internal raw register to 'public' register
xcore_reg XCore_map_register(unsigned int r);
// map register name to register ID
xcore_reg XCore_reg_id(char *name);
#endif

View File

@ -71,7 +71,21 @@ typedef enum xcore_reg {
XCORE_REG_R10,
XCORE_REG_R11,
XCORE_REG_MAX,
//> pseudo registers
XCORE_REG_PC, // pc
// internal thread registers
// see The-XMOS-XS1-Architecture(X7879A).pdf
XCORE_REG_SCP, // save pc
XCORE_REG_SSR, // save status
XCORE_REG_ET, // exception type
XCORE_REG_ED, // exception data
XCORE_REG_SED, // save exception data
XCORE_REG_KEP, // kernel entry pointer
XCORE_REG_KSP, // kernel stack pointer
XCORE_REG_ID, // thread ID
XCORE_REG_MAX, // <-- mark the end of the list of registers
} xcore_reg;
//> XCore instruction