#ifndef CAPSTONE_SPARC_H
#define CAPSTONE_SPARC_H

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

#ifdef __cplusplus
extern "C" {
#endif

#include "platform.h"

// GCC SPARC toolchain has a default macro called "sparc" which breaks
// compilation
#undef sparc

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

/// Enums corresponding to Sparc condition codes, both icc's and fcc's.
typedef enum sparc_cc {
	SPARC_CC_INVALID = 0,	///< invalid CC (default)
	// Integer condition codes
	SPARC_CC_ICC_A   =  8+256,  ///< Always
	SPARC_CC_ICC_N   =  0+256,  ///< Never
	SPARC_CC_ICC_NE  =  9+256,  ///< Not Equal
	SPARC_CC_ICC_E   =  1+256,  ///< Equal
	SPARC_CC_ICC_G   = 10+256,  ///< Greater
	SPARC_CC_ICC_LE  =  2+256,  ///< Less or Equal
	SPARC_CC_ICC_GE  = 11+256,  ///< Greater or Equal
	SPARC_CC_ICC_L   =  3+256,  ///< Less
	SPARC_CC_ICC_GU  = 12+256,  ///< Greater Unsigned
	SPARC_CC_ICC_LEU =  4+256,  ///< Less or Equal Unsigned
	SPARC_CC_ICC_CC  = 13+256,  ///< Carry Clear/Great or Equal Unsigned
	SPARC_CC_ICC_CS  =  5+256,  ///< Carry Set/Less Unsigned
	SPARC_CC_ICC_POS = 14+256,  ///< Positive
	SPARC_CC_ICC_NEG =  6+256,  ///< Negative
	SPARC_CC_ICC_VC  = 15+256,  ///< Overflow Clear
	SPARC_CC_ICC_VS  =  7+256,  ///< Overflow Set

	// Floating condition codes
	SPARC_CC_FCC_A   =  8+16+256,  ///< Always
	SPARC_CC_FCC_N   =  0+16+256,  ///< Never
	SPARC_CC_FCC_U   =  7+16+256,  ///< Unordered
	SPARC_CC_FCC_G   =  6+16+256,  ///< Greater
	SPARC_CC_FCC_UG  =  5+16+256,  ///< Unordered or Greater
	SPARC_CC_FCC_L   =  4+16+256,  ///< Less
	SPARC_CC_FCC_UL  =  3+16+256,  ///< Unordered or Less
	SPARC_CC_FCC_LG  =  2+16+256,  ///< Less or Greater
	SPARC_CC_FCC_NE  =  1+16+256,  ///< Not Equal
	SPARC_CC_FCC_E   =  9+16+256,  ///< Equal
	SPARC_CC_FCC_UE  = 10+16+256,  ///< Unordered or Equal
	SPARC_CC_FCC_GE  = 11+16+256,  ///< Greater or Equal
	SPARC_CC_FCC_UGE = 12+16+256,  ///< Unordered or Greater or Equal
	SPARC_CC_FCC_LE  = 13+16+256,  ///< Less or Equal
	SPARC_CC_FCC_ULE = 14+16+256,  ///< Unordered or Less or Equal
	SPARC_CC_FCC_O   = 15+16+256,  ///< Ordered
} sparc_cc;

/// Branch hint
typedef enum sparc_hint {
	SPARC_HINT_INVALID = 0,	///< no hint
	SPARC_HINT_A	= 1 << 0,	///< annul delay slot instruction
	SPARC_HINT_PT	= 1 << 1,	///< branch taken
	SPARC_HINT_PN	= 1 << 2,	///< branch NOT taken
	SPARC_HINT_A_PN	= SPARC_HINT_A | SPARC_HINT_PN,
	SPARC_HINT_A_PT	= SPARC_HINT_A | SPARC_HINT_PT,
} sparc_hint;

/// Operand type for instruction's operands
typedef enum sparc_op_type {
	SPARC_OP_INVALID = 0, ///< = CS_OP_INVALID (Uninitialized).
	SPARC_OP_REG, ///< = CS_OP_REG (Register operand).
	SPARC_OP_IMM, ///< = CS_OP_IMM (Immediate operand).
	SPARC_OP_MEM, ///< = CS_OP_MEM (Memory operand).
} sparc_op_type;

/// SPARC registers
typedef enum sparc_reg {
	SPARC_REG_INVALID = 0,

	SPARC_REG_F0,
	SPARC_REG_F1,
	SPARC_REG_F2,
	SPARC_REG_F3,
	SPARC_REG_F4,
	SPARC_REG_F5,
	SPARC_REG_F6,
	SPARC_REG_F7,
	SPARC_REG_F8,
	SPARC_REG_F9,
	SPARC_REG_F10,
	SPARC_REG_F11,
	SPARC_REG_F12,
	SPARC_REG_F13,
	SPARC_REG_F14,
	SPARC_REG_F15,
	SPARC_REG_F16,
	SPARC_REG_F17,
	SPARC_REG_F18,
	SPARC_REG_F19,
	SPARC_REG_F20,
	SPARC_REG_F21,
	SPARC_REG_F22,
	SPARC_REG_F23,
	SPARC_REG_F24,
	SPARC_REG_F25,
	SPARC_REG_F26,
	SPARC_REG_F27,
	SPARC_REG_F28,
	SPARC_REG_F29,
	SPARC_REG_F30,
	SPARC_REG_F31,
	SPARC_REG_F32,
	SPARC_REG_F34,
	SPARC_REG_F36,
	SPARC_REG_F38,
	SPARC_REG_F40,
	SPARC_REG_F42,
	SPARC_REG_F44,
	SPARC_REG_F46,
	SPARC_REG_F48,
	SPARC_REG_F50,
	SPARC_REG_F52,
	SPARC_REG_F54,
	SPARC_REG_F56,
	SPARC_REG_F58,
	SPARC_REG_F60,
	SPARC_REG_F62,
	SPARC_REG_FCC0,	// Floating condition codes
	SPARC_REG_FCC1,
	SPARC_REG_FCC2,
	SPARC_REG_FCC3,
	SPARC_REG_FP,
	SPARC_REG_G0,
	SPARC_REG_G1,
	SPARC_REG_G2,
	SPARC_REG_G3,
	SPARC_REG_G4,
	SPARC_REG_G5,
	SPARC_REG_G6,
	SPARC_REG_G7,
	SPARC_REG_I0,
	SPARC_REG_I1,
	SPARC_REG_I2,
	SPARC_REG_I3,
	SPARC_REG_I4,
	SPARC_REG_I5,
	SPARC_REG_I7,
	SPARC_REG_ICC,	// Integer condition codes
	SPARC_REG_L0,
	SPARC_REG_L1,
	SPARC_REG_L2,
	SPARC_REG_L3,
	SPARC_REG_L4,
	SPARC_REG_L5,
	SPARC_REG_L6,
	SPARC_REG_L7,
	SPARC_REG_O0,
	SPARC_REG_O1,
	SPARC_REG_O2,
	SPARC_REG_O3,
	SPARC_REG_O4,
	SPARC_REG_O5,
	SPARC_REG_O7,
	SPARC_REG_SP,
	SPARC_REG_Y,

	// special register
	SPARC_REG_XCC,

	SPARC_REG_ENDING,   // <-- mark the end of the list of registers

	// extras
	SPARC_REG_O6 = SPARC_REG_SP,
	SPARC_REG_I6 = SPARC_REG_FP,
} sparc_reg;

/// Instruction's operand referring to memory
/// This is associated with SPARC_OP_MEM operand type above
typedef struct sparc_op_mem {
	uint8_t base;		///< base register, can be safely interpreted as
				///< a value of type `sparc_reg`, but it is only
				///< one byte wide
	uint8_t index;		///< index register, same conditions apply here
	int32_t disp;		///< displacement/offset value
} sparc_op_mem;

/// Instruction operand
typedef struct cs_sparc_op {
	sparc_op_type type;	///< operand type
	union {
		sparc_reg reg;	///< register value for REG operand
		int64_t imm;		///< immediate value for IMM operand
		sparc_op_mem mem;		///< base/disp value for MEM operand
	};
} cs_sparc_op;

/// Instruction structure
typedef struct cs_sparc {
	sparc_cc cc;	///< code condition for this insn
	sparc_hint hint;	///< branch hint: encoding as bitwise OR of sparc_hint.
	/// Number of operands of this instruction,
	/// or 0 when instruction has no operand.
	uint8_t op_count;
	cs_sparc_op operands[4]; ///< operands for this instruction.
} cs_sparc;

/// SPARC instruction
typedef enum sparc_insn {
	SPARC_INS_INVALID = 0,

	SPARC_INS_ADDCC,
	SPARC_INS_ADDX,
	SPARC_INS_ADDXCC,
	SPARC_INS_ADDXC,
	SPARC_INS_ADDXCCC,
	SPARC_INS_ADD,
	SPARC_INS_ALIGNADDR,
	SPARC_INS_ALIGNADDRL,
	SPARC_INS_ANDCC,
	SPARC_INS_ANDNCC,
	SPARC_INS_ANDN,
	SPARC_INS_AND,
	SPARC_INS_ARRAY16,
	SPARC_INS_ARRAY32,
	SPARC_INS_ARRAY8,
	SPARC_INS_B,
	SPARC_INS_JMP,
	SPARC_INS_BMASK,
	SPARC_INS_FB,
	SPARC_INS_BRGEZ,
	SPARC_INS_BRGZ,
	SPARC_INS_BRLEZ,
	SPARC_INS_BRLZ,
	SPARC_INS_BRNZ,
	SPARC_INS_BRZ,
	SPARC_INS_BSHUFFLE,
	SPARC_INS_CALL,
	SPARC_INS_CASX,
	SPARC_INS_CAS,
	SPARC_INS_CMASK16,
	SPARC_INS_CMASK32,
	SPARC_INS_CMASK8,
	SPARC_INS_CMP,
	SPARC_INS_EDGE16,
	SPARC_INS_EDGE16L,
	SPARC_INS_EDGE16LN,
	SPARC_INS_EDGE16N,
	SPARC_INS_EDGE32,
	SPARC_INS_EDGE32L,
	SPARC_INS_EDGE32LN,
	SPARC_INS_EDGE32N,
	SPARC_INS_EDGE8,
	SPARC_INS_EDGE8L,
	SPARC_INS_EDGE8LN,
	SPARC_INS_EDGE8N,
	SPARC_INS_FABSD,
	SPARC_INS_FABSQ,
	SPARC_INS_FABSS,
	SPARC_INS_FADDD,
	SPARC_INS_FADDQ,
	SPARC_INS_FADDS,
	SPARC_INS_FALIGNDATA,
	SPARC_INS_FAND,
	SPARC_INS_FANDNOT1,
	SPARC_INS_FANDNOT1S,
	SPARC_INS_FANDNOT2,
	SPARC_INS_FANDNOT2S,
	SPARC_INS_FANDS,
	SPARC_INS_FCHKSM16,
	SPARC_INS_FCMPD,
	SPARC_INS_FCMPEQ16,
	SPARC_INS_FCMPEQ32,
	SPARC_INS_FCMPGT16,
	SPARC_INS_FCMPGT32,
	SPARC_INS_FCMPLE16,
	SPARC_INS_FCMPLE32,
	SPARC_INS_FCMPNE16,
	SPARC_INS_FCMPNE32,
	SPARC_INS_FCMPQ,
	SPARC_INS_FCMPS,
	SPARC_INS_FDIVD,
	SPARC_INS_FDIVQ,
	SPARC_INS_FDIVS,
	SPARC_INS_FDMULQ,
	SPARC_INS_FDTOI,
	SPARC_INS_FDTOQ,
	SPARC_INS_FDTOS,
	SPARC_INS_FDTOX,
	SPARC_INS_FEXPAND,
	SPARC_INS_FHADDD,
	SPARC_INS_FHADDS,
	SPARC_INS_FHSUBD,
	SPARC_INS_FHSUBS,
	SPARC_INS_FITOD,
	SPARC_INS_FITOQ,
	SPARC_INS_FITOS,
	SPARC_INS_FLCMPD,
	SPARC_INS_FLCMPS,
	SPARC_INS_FLUSHW,
	SPARC_INS_FMEAN16,
	SPARC_INS_FMOVD,
	SPARC_INS_FMOVQ,
	SPARC_INS_FMOVRDGEZ,
	SPARC_INS_FMOVRQGEZ,
	SPARC_INS_FMOVRSGEZ,
	SPARC_INS_FMOVRDGZ,
	SPARC_INS_FMOVRQGZ,
	SPARC_INS_FMOVRSGZ,
	SPARC_INS_FMOVRDLEZ,
	SPARC_INS_FMOVRQLEZ,
	SPARC_INS_FMOVRSLEZ,
	SPARC_INS_FMOVRDLZ,
	SPARC_INS_FMOVRQLZ,
	SPARC_INS_FMOVRSLZ,
	SPARC_INS_FMOVRDNZ,
	SPARC_INS_FMOVRQNZ,
	SPARC_INS_FMOVRSNZ,
	SPARC_INS_FMOVRDZ,
	SPARC_INS_FMOVRQZ,
	SPARC_INS_FMOVRSZ,
	SPARC_INS_FMOVS,
	SPARC_INS_FMUL8SUX16,
	SPARC_INS_FMUL8ULX16,
	SPARC_INS_FMUL8X16,
	SPARC_INS_FMUL8X16AL,
	SPARC_INS_FMUL8X16AU,
	SPARC_INS_FMULD,
	SPARC_INS_FMULD8SUX16,
	SPARC_INS_FMULD8ULX16,
	SPARC_INS_FMULQ,
	SPARC_INS_FMULS,
	SPARC_INS_FNADDD,
	SPARC_INS_FNADDS,
	SPARC_INS_FNAND,
	SPARC_INS_FNANDS,
	SPARC_INS_FNEGD,
	SPARC_INS_FNEGQ,
	SPARC_INS_FNEGS,
	SPARC_INS_FNHADDD,
	SPARC_INS_FNHADDS,
	SPARC_INS_FNOR,
	SPARC_INS_FNORS,
	SPARC_INS_FNOT1,
	SPARC_INS_FNOT1S,
	SPARC_INS_FNOT2,
	SPARC_INS_FNOT2S,
	SPARC_INS_FONE,
	SPARC_INS_FONES,
	SPARC_INS_FOR,
	SPARC_INS_FORNOT1,
	SPARC_INS_FORNOT1S,
	SPARC_INS_FORNOT2,
	SPARC_INS_FORNOT2S,
	SPARC_INS_FORS,
	SPARC_INS_FPACK16,
	SPARC_INS_FPACK32,
	SPARC_INS_FPACKFIX,
	SPARC_INS_FPADD16,
	SPARC_INS_FPADD16S,
	SPARC_INS_FPADD32,
	SPARC_INS_FPADD32S,
	SPARC_INS_FPADD64,
	SPARC_INS_FPMERGE,
	SPARC_INS_FPSUB16,
	SPARC_INS_FPSUB16S,
	SPARC_INS_FPSUB32,
	SPARC_INS_FPSUB32S,
	SPARC_INS_FQTOD,
	SPARC_INS_FQTOI,
	SPARC_INS_FQTOS,
	SPARC_INS_FQTOX,
	SPARC_INS_FSLAS16,
	SPARC_INS_FSLAS32,
	SPARC_INS_FSLL16,
	SPARC_INS_FSLL32,
	SPARC_INS_FSMULD,
	SPARC_INS_FSQRTD,
	SPARC_INS_FSQRTQ,
	SPARC_INS_FSQRTS,
	SPARC_INS_FSRA16,
	SPARC_INS_FSRA32,
	SPARC_INS_FSRC1,
	SPARC_INS_FSRC1S,
	SPARC_INS_FSRC2,
	SPARC_INS_FSRC2S,
	SPARC_INS_FSRL16,
	SPARC_INS_FSRL32,
	SPARC_INS_FSTOD,
	SPARC_INS_FSTOI,
	SPARC_INS_FSTOQ,
	SPARC_INS_FSTOX,
	SPARC_INS_FSUBD,
	SPARC_INS_FSUBQ,
	SPARC_INS_FSUBS,
	SPARC_INS_FXNOR,
	SPARC_INS_FXNORS,
	SPARC_INS_FXOR,
	SPARC_INS_FXORS,
	SPARC_INS_FXTOD,
	SPARC_INS_FXTOQ,
	SPARC_INS_FXTOS,
	SPARC_INS_FZERO,
	SPARC_INS_FZEROS,
	SPARC_INS_JMPL,
	SPARC_INS_LDD,
	SPARC_INS_LD,
	SPARC_INS_LDQ,
	SPARC_INS_LDSB,
	SPARC_INS_LDSH,
	SPARC_INS_LDSW,
	SPARC_INS_LDUB,
	SPARC_INS_LDUH,
	SPARC_INS_LDX,
	SPARC_INS_LZCNT,
	SPARC_INS_MEMBAR,
	SPARC_INS_MOVDTOX,
	SPARC_INS_MOV,
	SPARC_INS_MOVRGEZ,
	SPARC_INS_MOVRGZ,
	SPARC_INS_MOVRLEZ,
	SPARC_INS_MOVRLZ,
	SPARC_INS_MOVRNZ,
	SPARC_INS_MOVRZ,
	SPARC_INS_MOVSTOSW,
	SPARC_INS_MOVSTOUW,
	SPARC_INS_MULX,
	SPARC_INS_NOP,
	SPARC_INS_ORCC,
	SPARC_INS_ORNCC,
	SPARC_INS_ORN,
	SPARC_INS_OR,
	SPARC_INS_PDIST,
	SPARC_INS_PDISTN,
	SPARC_INS_POPC,
	SPARC_INS_RD,
	SPARC_INS_RESTORE,
	SPARC_INS_RETT,
	SPARC_INS_SAVE,
	SPARC_INS_SDIVCC,
	SPARC_INS_SDIVX,
	SPARC_INS_SDIV,
	SPARC_INS_SETHI,
	SPARC_INS_SHUTDOWN,
	SPARC_INS_SIAM,
	SPARC_INS_SLLX,
	SPARC_INS_SLL,
	SPARC_INS_SMULCC,
	SPARC_INS_SMUL,
	SPARC_INS_SRAX,
	SPARC_INS_SRA,
	SPARC_INS_SRLX,
	SPARC_INS_SRL,
	SPARC_INS_STBAR,
	SPARC_INS_STB,
	SPARC_INS_STD,
	SPARC_INS_ST,
	SPARC_INS_STH,
	SPARC_INS_STQ,
	SPARC_INS_STX,
	SPARC_INS_SUBCC,
	SPARC_INS_SUBX,
	SPARC_INS_SUBXCC,
	SPARC_INS_SUB,
	SPARC_INS_SWAP,
	SPARC_INS_TADDCCTV,
	SPARC_INS_TADDCC,
	SPARC_INS_T,
	SPARC_INS_TSUBCCTV,
	SPARC_INS_TSUBCC,
	SPARC_INS_UDIVCC,
	SPARC_INS_UDIVX,
	SPARC_INS_UDIV,
	SPARC_INS_UMULCC,
	SPARC_INS_UMULXHI,
	SPARC_INS_UMUL,
	SPARC_INS_UNIMP,
	SPARC_INS_FCMPED,
	SPARC_INS_FCMPEQ,
	SPARC_INS_FCMPES,
	SPARC_INS_WR,
	SPARC_INS_XMULX,
	SPARC_INS_XMULXHI,
	SPARC_INS_XNORCC,
	SPARC_INS_XNOR,
	SPARC_INS_XORCC,
	SPARC_INS_XOR,

	// alias instructions
	SPARC_INS_RET,
	SPARC_INS_RETL,

	SPARC_INS_ENDING,   // <-- mark the end of the list of instructions
} sparc_insn;

/// Group of SPARC instructions
typedef enum sparc_insn_group {
	SPARC_GRP_INVALID = 0, ///< = CS_GRP_INVALID

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

	// Architecture-specific groups
	SPARC_GRP_HARDQUAD = 128,
	SPARC_GRP_V9,
	SPARC_GRP_VIS,
	SPARC_GRP_VIS2,
	SPARC_GRP_VIS3, 
	SPARC_GRP_32BIT,
	SPARC_GRP_64BIT,

	SPARC_GRP_ENDING,   // <-- mark the end of the list of groups
} sparc_insn_group;

#ifdef __cplusplus
}
#endif

#endif
