⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm-codegen.h

📁 this program is for arm cpu and wince
💻 H
📖 第 1 页 / 共 3 页
字号:
/*
 * arm-codegen.h
 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
 */


#ifndef ARM_H
#define ARM_H

#ifdef __cplusplus
extern "C" {
#endif

typedef unsigned int arminstr_t;
typedef unsigned int armword_t;

/* Helper functions */
arminstr_t* arm_emit_std_prologue(arminstr_t* p, unsigned int local_size);
arminstr_t* arm_emit_std_epilogue(arminstr_t* p, unsigned int local_size, int pop_regs);
arminstr_t* arm_emit_lean_prologue(arminstr_t* p, unsigned int local_size, int push_regs);
int arm_is_power_of_2(armword_t val);
int calc_arm_mov_const_shift(armword_t val);
int is_arm_const(armword_t val);
int arm_bsf(armword_t val);
arminstr_t* arm_mov_reg_imm32_cond(arminstr_t* p, int reg, armword_t imm32, int cond);
arminstr_t* arm_mov_reg_imm32(arminstr_t* p, int reg, armword_t imm32);



#if defined(_MSC_VER) || defined(__CC_NORCROFT)
	void __inline _arm_emit(arminstr_t** p, arminstr_t i) {**p = i; (*p)++;}
#	define ARM_EMIT(p, i) _arm_emit((arminstr_t**)&p, (arminstr_t)(i))
#else
#	define ARM_EMIT(p, i) do { arminstr_t *__ainstrp = (void*)(p); *__ainstrp = (arminstr_t)(i); (p) = (void*)(__ainstrp+1);} while (0)
#endif

#if defined(_MSC_VER) && !defined(ARM_NOIASM)
#	define ARM_IASM(_expr) __emit (_expr)
#else
#	define ARM_IASM(_expr)
#endif

/* even_scale = rot << 1 */
#define ARM_SCALE(imm8, even_scale) ( ((imm8) >> (even_scale)) | ((imm8) << (32 - even_scale)) )



typedef enum {
	ARMREG_R0 = 0,
	ARMREG_R1,
	ARMREG_R2,
	ARMREG_R3,
	ARMREG_R4,
	ARMREG_R5,
	ARMREG_R6,
	ARMREG_R7,
	ARMREG_R8,
	ARMREG_R9,
	ARMREG_R10,
	ARMREG_R11,
	ARMREG_R12,
	ARMREG_R13,
	ARMREG_R14,
	ARMREG_R15,


	/* aliases */
	/* args */
	ARMREG_A1 = ARMREG_R0,
	ARMREG_A2 = ARMREG_R1,
	ARMREG_A3 = ARMREG_R2,
	ARMREG_A4 = ARMREG_R3,

	/* local vars */
	ARMREG_V1 = ARMREG_R4,
	ARMREG_V2 = ARMREG_R5,
	ARMREG_V3 = ARMREG_R6,
	ARMREG_V4 = ARMREG_R7,
	ARMREG_V5 = ARMREG_R8,
	ARMREG_V6 = ARMREG_R9,
	ARMREG_V7 = ARMREG_R10,

	ARMREG_FP = ARMREG_R11,
	ARMREG_IP = ARMREG_R12,
	ARMREG_SP = ARMREG_R13,
	ARMREG_LR = ARMREG_R14,
	ARMREG_PC = ARMREG_R15,

	/* co-processor */
	ARMREG_CR0 = 0,
	ARMREG_CR1,
	ARMREG_CR2,
	ARMREG_CR3,
	ARMREG_CR4,
	ARMREG_CR5,
	ARMREG_CR6,
	ARMREG_CR7,
	ARMREG_CR8,
	ARMREG_CR9,
	ARMREG_CR10,
	ARMREG_CR11,
	ARMREG_CR12,
	ARMREG_CR13,
	ARMREG_CR14,
	ARMREG_CR15,

	/* XScale: acc0 on CP0 */
	ARMREG_ACC0 = ARMREG_CR0,

	ARMREG_MAX = ARMREG_R15
} ARMReg;

/* number of argument registers */
#define ARM_NUM_ARG_REGS 4

/* bitvector for all argument regs (A1-A4) */
#define ARM_ALL_ARG_REGS \
	(1 << ARMREG_A1) | (1 << ARMREG_A2) | (1 << ARMREG_A3) | (1 << ARMREG_A4)


typedef enum {
	ARMCOND_EQ = 0x0,          /* Equal; Z = 1 */
	ARMCOND_NE = 0x1,          /* Not equal, or unordered; Z = 0 */
	ARMCOND_CS = 0x2,          /* Carry set; C = 1 */
	ARMCOND_HS = ARMCOND_CS,   /* Unsigned higher or same; */
	ARMCOND_CC = 0x3,          /* Carry clear; C = 0 */
	ARMCOND_LO = ARMCOND_CC,   /* Unsigned lower */
	ARMCOND_MI = 0x4,          /* Negative; N = 1 */
	ARMCOND_PL = 0x5,          /* Positive or zero; N = 0 */
	ARMCOND_VS = 0x6,          /* Overflow; V = 1 */
	ARMCOND_VC = 0x7,          /* No overflow; V = 0 */
	ARMCOND_HI = 0x8,          /* Unsigned higher; C = 1 && Z = 0 */
	ARMCOND_LS = 0x9,          /* Unsigned lower or same; C = 0 || Z = 1 */
	ARMCOND_GE = 0xA,          /* Signed greater than or equal; N = V */
	ARMCOND_LT = 0xB,          /* Signed less than; N != V */
	ARMCOND_GT = 0xC,          /* Signed greater than; Z = 0 && N = V */
	ARMCOND_LE = 0xD,          /* Signed less than or equal; Z = 1 && N != V */
	ARMCOND_AL = 0xE,          /* Always */
	ARMCOND_NV = 0xF,          /* Never */

	ARMCOND_SHIFT = 28
} ARMCond;

#define ARMCOND_MASK (ARMCOND_NV << ARMCOND_SHIFT)

#define ARM_DEF_COND(cond) (((cond) & 0xF) << ARMCOND_SHIFT)



typedef enum {
	ARMSHIFT_LSL = 0,
	ARMSHIFT_LSR = 1,
	ARMSHIFT_ASR = 2,
	ARMSHIFT_ROR = 3,

	ARMSHIFT_ASL = ARMSHIFT_LSL
	/* rrx = (ror, 1) */
} ARMShiftType;


typedef struct {
	armword_t PSR_c : 8;
	armword_t PSR_x : 8;
	armword_t PSR_s : 8;
	armword_t PSR_f : 8;
} ARMPSR;

typedef enum {
	ARMOP_AND = 0x0,
	ARMOP_EOR = 0x1,
	ARMOP_SUB = 0x2,
	ARMOP_RSB = 0x3,
	ARMOP_ADD = 0x4,
	ARMOP_ADC = 0x5,
	ARMOP_SBC = 0x6,
	ARMOP_RSC = 0x7,
	ARMOP_TST = 0x8,
	ARMOP_TEQ = 0x9,
	ARMOP_CMP = 0xa,
	ARMOP_CMN = 0xb,
	ARMOP_ORR = 0xc,
	ARMOP_MOV = 0xd,
	ARMOP_BIC = 0xe,
	ARMOP_MVN = 0xf,


	/* not really opcodes */

	ARMOP_STR = 0x0,
	ARMOP_LDR = 0x1,

	/* ARM2+ */
	ARMOP_MUL   = 0x0, /* Rd := Rm*Rs */
	ARMOP_MLA   = 0x1, /* Rd := (Rm*Rs)+Rn */

	/* ARM3M+ */
	ARMOP_UMULL = 0x4,
	ARMOP_UMLAL = 0x5,
	ARMOP_SMULL = 0x6,
	ARMOP_SMLAL = 0x7,

	/* for data transfers with register offset */
	ARM_UP   = 1,
	ARM_DOWN = 0
} ARMOpcode;

typedef enum {
	THUMBOP_AND  = 0,
	THUMBOP_EOR  = 1,
	THUMBOP_LSL  = 2,
	THUMBOP_LSR  = 3,
	THUMBOP_ASR  = 4,
	THUMBOP_ADC  = 5,
	THUMBOP_SBC  = 6,
	THUMBOP_ROR  = 7,
	THUMBOP_TST  = 8,
	THUMBOP_NEG  = 9,
	THUMBOP_CMP  = 10,
	THUMBOP_CMN  = 11,
	THUMBOP_ORR  = 12,
	THUMBOP_MUL  = 13,
	THUMBOP_BIC  = 14,
	THUMBOP_MVN  = 15,
	THUMBOP_MOV  = 16,
	THUMBOP_CMPI = 17,
	THUMBOP_ADD  = 18,
	THUMBOP_SUB  = 19,
	THUMBOP_CMPH = 19,
	THUMBOP_MOVH = 20
} ThumbOpcode;


/* Generic form - all ARM instructions are conditional. */
typedef struct {
	arminstr_t icode : 28;
	arminstr_t cond  :  4;
} ARMInstrGeneric;



/* Branch or Branch with Link instructions. */
typedef struct {
	arminstr_t offset : 24;
	arminstr_t link   :  1;
	arminstr_t tag    :  3; /* 1 0 1 */
	arminstr_t cond   :  4;
} ARMInstrBR;

#define ARM_BR_ID 5
#define ARM_BR_MASK 7 << 25
#define ARM_BR_TAG ARM_BR_ID << 25

#define ARM_DEF_BR(offs, l, cond) ((offs & 0x00FFFFFF) | ((l) << 24) | (ARM_BR_TAG) | (cond << ARMCOND_SHIFT))

/* branch */
#define ARM_B_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 0, cond))
#define ARM_B(p, offs) ARM_B_COND((p), ARMCOND_AL, (offs))
/* branch with link */
#define ARM_BL_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 1, cond))
#define ARM_BL(p, offs) ARM_BL_COND((p), ARMCOND_AL, (offs))

#define ARM_DEF_BX(reg,sub,cond) (0x12fff << 8 | (reg) | ((sub) << 4) | ((cond) << ARMCOND_SHIFT))

#define ARM_BX_COND(p, cond, reg) ARM_EMIT(p, ARM_DEF_BX(reg, 1, cond))
#define ARM_BX(p, reg) ARM_BX_COND((p), ARMCOND_AL, (reg))

#define ARM_BLX_REG_COND(p, cond, reg) ARM_EMIT(p, ARM_DEF_BX(reg, 3, cond))
#define ARM_BLX_REG(p, reg) ARM_BLX_REG_COND((p), ARMCOND_AL, (reg))

/* Data Processing Instructions - there are 3 types. */

typedef struct {
	arminstr_t imm : 8;
	arminstr_t rot : 4;
} ARMDPI_op2_imm;

typedef struct {
	arminstr_t rm   : 4;
	arminstr_t tag  : 1; /* 0 - immediate shift, 1 - reg shift */
	arminstr_t type : 2; /* shift type - logical, arithmetic, rotate */
} ARMDPI_op2_reg_shift;


/* op2 is reg shift by imm */
typedef union {
	ARMDPI_op2_reg_shift r2;
	struct {
		arminstr_t _dummy_r2 : 7;
		arminstr_t shift : 5;
	} imm;
} ARMDPI_op2_reg_imm;

/* op2 is reg shift by reg */
typedef union {
	ARMDPI_op2_reg_shift r2;
	struct {
		arminstr_t _dummy_r2 : 7;
		arminstr_t pad       : 1; /* always 0, to differentiate from HXFER etc. */
		arminstr_t rs        : 4;
	} reg;
} ARMDPI_op2_reg_reg;

/* Data processing instrs */
typedef union {
	ARMDPI_op2_imm op2_imm;

	ARMDPI_op2_reg_shift op2_reg;
	ARMDPI_op2_reg_imm op2_reg_imm;
	ARMDPI_op2_reg_reg op2_reg_reg;

	struct {
		arminstr_t op2    : 12; /* raw operand 2 */
		arminstr_t rd     :  4; /* destination reg */
		arminstr_t rn     :  4; /* first operand reg */
		arminstr_t s      :  1; /* S-bit controls PSR update */
		arminstr_t opcode :  4; /* arithmetic/logic operation */
		arminstr_t type   :  1; /* type of op2, 0 = register, 1 = immediate */
		arminstr_t tag    :  2; /* 0 0 */
		arminstr_t cond   :  4;
	} all;
} ARMInstrDPI;

#define ARM_DPI_ID 0
#define ARM_DPI_MASK 3 << 26
#define ARM_DPI_TAG ARM_DPI_ID << 26

#define ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, cond) \
	((imm8) & 0xFF)      | \
	(((rot) & 0xF) << 8) | \
	((rd) << 12)         | \
	((rn) << 16)         | \
	((s) << 20)          | \
	((op) << 21)         | \
	(1 << 25)            | \
	(ARM_DPI_TAG)        | \
	ARM_DEF_COND(cond)


#define ARM_DEF_DPI_IMM(imm8, rot, rd, rn, s, op) \
	ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, ARMCOND_AL)

/* codegen */
#define ARM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
	ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
#define ARM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
	ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))

/* inline */
#define ARM_IASM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
	ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
#define ARM_IASM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
	ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))



#define ARM_DEF_DPI_REG_IMMSHIFT_COND(rm, shift_type, imm_shift, rd, rn, s, op, cond) \
	(rm)                        | \
	((shift_type & 3) << 5)     | \
	(((imm_shift) & 0x1F) << 7) | \
	((rd) << 12)                | \
	((rn) << 16)                | \
	((s) << 20)                 | \

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -