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