diff --git a/arch/XCore/XCoreGenAsmWriter.inc b/arch/XCore/XCoreGenAsmWriter.inc index 28b94a88..e60d7917 100644 --- a/arch/XCore/XCoreGenAsmWriter.inc +++ b/arch/XCore/XCoreGenAsmWriter.inc @@ -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; diff --git a/arch/XCore/XCoreInstPrinter.c b/arch/XCore/XCoreInstPrinter.c index 1f4f704c..f1d797f4 100644 --- a/arch/XCore/XCoreInstPrinter.c +++ b/arch/XCore/XCoreInstPrinter.c @@ -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++; } diff --git a/arch/XCore/XCoreInstPrinter.h b/arch/XCore/XCoreInstPrinter.h index c78d3f07..dc34d9a6 100644 --- a/arch/XCore/XCoreInstPrinter.h +++ b/arch/XCore/XCoreInstPrinter.h @@ -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 diff --git a/arch/XCore/XCoreMapping.c b/arch/XCore/XCoreMapping.c index ade5b9e6..3aa5c72e 100644 --- a/arch/XCore/XCoreMapping.c +++ b/arch/XCore/XCoreMapping.c @@ -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 { diff --git a/arch/XCore/XCoreMapping.h b/arch/XCore/XCoreMapping.h index a21840f7..8d8a9b2c 100644 --- a/arch/XCore/XCoreMapping.h +++ b/arch/XCore/XCoreMapping.h @@ -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 diff --git a/include/xcore.h b/include/xcore.h index 5bc67705..a2133d4f 100644 --- a/include/xcore.h +++ b/include/xcore.h @@ -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