#ifndef CAPSTONE_XCORE_H
#define CAPSTONE_XCORE_H

/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2014-2015 */

#ifdef __cplusplus
extern "C" {
#endif

#include "platform.h"

#ifdef _MSC_VER
#pragma warning(disable:4201)
#endif

/// Operand type for instruction's operands
typedef enum xcore_op_type {
	XCORE_OP_INVALID = 0, ///< = CS_OP_INVALID (Uninitialized).
	XCORE_OP_REG, ///< = CS_OP_REG (Register operand).
	XCORE_OP_IMM, ///< = CS_OP_IMM (Immediate operand).
	XCORE_OP_MEM, ///< = CS_OP_MEM (Memory operand).
} xcore_op_type;

/// XCore registers
typedef enum xcore_reg {
	XCORE_REG_INVALID = 0,

	XCORE_REG_CP,
	XCORE_REG_DP,
	XCORE_REG_LR,
	XCORE_REG_SP,
	XCORE_REG_R0,
	XCORE_REG_R1,
	XCORE_REG_R2,
	XCORE_REG_R3,
	XCORE_REG_R4,
	XCORE_REG_R5,
	XCORE_REG_R6,
	XCORE_REG_R7,
	XCORE_REG_R8,
	XCORE_REG_R9,
	XCORE_REG_R10,
	XCORE_REG_R11,

	// 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_ENDING,	// <-- mark the end of the list of registers
} xcore_reg;

/// Instruction's operand referring to memory
/// This is associated with XCORE_OP_MEM operand type above
typedef struct xcore_op_mem {
	uint8_t base;		///< base register, can be safely interpreted as
				///< a value of type `xcore_reg`, but it is only
				///< one byte wide
	uint8_t index;		///< index register, same conditions apply here
	int32_t disp;	///< displacement/offset value
	int     direct;	///< +1: forward, -1: backward
} xcore_op_mem;

/// Instruction operand
typedef struct cs_xcore_op {
	xcore_op_type type;	///< operand type
	union {
		xcore_reg reg;	///< register value for REG operand
		int32_t imm;		///< immediate value for IMM operand
		xcore_op_mem mem;		///< base/disp value for MEM operand
	};
} cs_xcore_op;

/// Instruction structure
typedef struct cs_xcore {
	/// Number of operands of this instruction,
	/// or 0 when instruction has no operand.
	uint8_t op_count;
	cs_xcore_op operands[8]; ///< operands for this instruction.
} cs_xcore;

/// XCore instruction
typedef enum xcore_insn {
	XCORE_INS_INVALID = 0,

	XCORE_INS_ADD,
	XCORE_INS_ANDNOT,
	XCORE_INS_AND,
	XCORE_INS_ASHR,
	XCORE_INS_BAU,
	XCORE_INS_BITREV,
	XCORE_INS_BLA,
	XCORE_INS_BLAT,
	XCORE_INS_BL,
	XCORE_INS_BF,
	XCORE_INS_BT,
	XCORE_INS_BU,
	XCORE_INS_BRU,
	XCORE_INS_BYTEREV,
	XCORE_INS_CHKCT,
	XCORE_INS_CLRE,
	XCORE_INS_CLRPT,
	XCORE_INS_CLRSR,
	XCORE_INS_CLZ,
	XCORE_INS_CRC8,
	XCORE_INS_CRC32,
	XCORE_INS_DCALL,
	XCORE_INS_DENTSP,
	XCORE_INS_DGETREG,
	XCORE_INS_DIVS,
	XCORE_INS_DIVU,
	XCORE_INS_DRESTSP,
	XCORE_INS_DRET,
	XCORE_INS_ECALLF,
	XCORE_INS_ECALLT,
	XCORE_INS_EDU,
	XCORE_INS_EEF,
	XCORE_INS_EET,
	XCORE_INS_EEU,
	XCORE_INS_ENDIN,
	XCORE_INS_ENTSP,
	XCORE_INS_EQ,
	XCORE_INS_EXTDP,
	XCORE_INS_EXTSP,
	XCORE_INS_FREER,
	XCORE_INS_FREET,
	XCORE_INS_GETD,
	XCORE_INS_GET,
	XCORE_INS_GETN,
	XCORE_INS_GETR,
	XCORE_INS_GETSR,
	XCORE_INS_GETST,
	XCORE_INS_GETTS,
	XCORE_INS_INCT,
	XCORE_INS_INIT,
	XCORE_INS_INPW,
	XCORE_INS_INSHR,
	XCORE_INS_INT,
	XCORE_INS_IN,
	XCORE_INS_KCALL,
	XCORE_INS_KENTSP,
	XCORE_INS_KRESTSP,
	XCORE_INS_KRET,
	XCORE_INS_LADD,
	XCORE_INS_LD16S,
	XCORE_INS_LD8U,
	XCORE_INS_LDA16,
	XCORE_INS_LDAP,
	XCORE_INS_LDAW,
	XCORE_INS_LDC,
	XCORE_INS_LDW,
	XCORE_INS_LDIVU,
	XCORE_INS_LMUL,
	XCORE_INS_LSS,
	XCORE_INS_LSUB,
	XCORE_INS_LSU,
	XCORE_INS_MACCS,
	XCORE_INS_MACCU,
	XCORE_INS_MJOIN,
	XCORE_INS_MKMSK,
	XCORE_INS_MSYNC,
	XCORE_INS_MUL,
	XCORE_INS_NEG,
	XCORE_INS_NOT,
	XCORE_INS_OR,
	XCORE_INS_OUTCT,
	XCORE_INS_OUTPW,
	XCORE_INS_OUTSHR,
	XCORE_INS_OUTT,
	XCORE_INS_OUT,
	XCORE_INS_PEEK,
	XCORE_INS_REMS,
	XCORE_INS_REMU,
	XCORE_INS_RETSP,
	XCORE_INS_SETCLK,
	XCORE_INS_SET,
	XCORE_INS_SETC,
	XCORE_INS_SETD,
	XCORE_INS_SETEV,
	XCORE_INS_SETN,
	XCORE_INS_SETPSC,
	XCORE_INS_SETPT,
	XCORE_INS_SETRDY,
	XCORE_INS_SETSR,
	XCORE_INS_SETTW,
	XCORE_INS_SETV,
	XCORE_INS_SEXT,
	XCORE_INS_SHL,
	XCORE_INS_SHR,
	XCORE_INS_SSYNC,
	XCORE_INS_ST16,
	XCORE_INS_ST8,
	XCORE_INS_STW,
	XCORE_INS_SUB,
	XCORE_INS_SYNCR,
	XCORE_INS_TESTCT,
	XCORE_INS_TESTLCL,
	XCORE_INS_TESTWCT,
	XCORE_INS_TSETMR,
	XCORE_INS_START,
	XCORE_INS_WAITEF,
	XCORE_INS_WAITET,
	XCORE_INS_WAITEU,
	XCORE_INS_XOR,
	XCORE_INS_ZEXT,

	XCORE_INS_ENDING,   // <-- mark the end of the list of instructions
} xcore_insn;

/// Group of XCore instructions
typedef enum xcore_insn_group {
	XCORE_GRP_INVALID = 0, ///< = CS_GRP_INVALID

	// Generic groups
	// all jump instructions (conditional+direct+indirect jumps)
	XCORE_GRP_JUMP,	///< = CS_GRP_JUMP

	XCORE_GRP_ENDING,   // <-- mark the end of the list of groups
} xcore_insn_group;

#ifdef __cplusplus
}
#endif

#endif
