xcore: handle details for some special tricky instructions
diff --git a/arch/XCore/XCoreGenAsmWriter.inc b/arch/XCore/XCoreGenAsmWriter.inc
index 28b94a8..e60d791 100644
--- a/arch/XCore/XCoreGenAsmWriter.inc
+++ b/arch/XCore/XCoreGenAsmWriter.inc
@@ -434,6 +434,8 @@
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 @@
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 1f4f704..f1d797f 100644
--- a/arch/XCore/XCoreInstPrinter.c
+++ b/arch/XCore/XCoreInstPrinter.c
@@ -39,6 +39,94 @@
*/
}
+// 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 @@
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 c78d3f0..dc34d9a 100644
--- a/arch/XCore/XCoreInstPrinter.h
+++ b/arch/XCore/XCoreInstPrinter.h
@@ -12,4 +12,7 @@
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 ade5b9e..3aa5c72 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 @@
{ 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 @@
#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 a21840f..8d8a9b2 100644
--- a/arch/XCore/XCoreMapping.h
+++ b/arch/XCore/XCoreMapping.h
@@ -17,5 +17,8 @@
// 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 5bc6770..a2133d4 100644
--- a/include/xcore.h
+++ b/include/xcore.h
@@ -71,7 +71,21 @@
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