📄 arm-codegen.h
字号:
((op) << 21) | \
(ARM_DPI_TAG) | \
ARM_DEF_COND(cond)
/* codegen */
#define ARM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
#define ARM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
#define ARM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
#define ARM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
/* inline */
#define ARM_IASM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
#define ARM_IASM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
#define ARM_IASM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
#define ARM_IASM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
ARM_IASM_EMIT(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
/* Rd := Rn op (Rm shift_type Rs) */
#define ARM_DEF_DPI_REG_REGSHIFT_COND(rm, shift_type, rs, rd, rn, s, op, cond) \
(rm) | \
(1 << 4) | \
((shift_type & 3) << 5) | \
((rs) << 8) | \
((rd) << 12) | \
((rn) << 16) | \
((s) << 20) | \
((op) << 21) | \
(ARM_DPI_TAG) | \
ARM_DEF_COND(cond)
/* codegen */
#define ARM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
#define ARM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
/* inline */
#define ARM_IASM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
#define ARM_IASM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
/* Multiple register transfer. */
typedef struct {
arminstr_t reg_list : 16; /* bitfield */
arminstr_t rn : 4; /* base reg */
arminstr_t ls : 1; /* load(1)/store(0) */
arminstr_t wb : 1; /* write-back "!" */
arminstr_t s : 1; /* restore PSR, force user bit */
arminstr_t u : 1; /* up/down */
arminstr_t p : 1; /* pre(1)/post(0) index */
arminstr_t tag : 3; /* 1 0 0 */
arminstr_t cond : 4;
} ARMInstrMRT;
#define ARM_MRT_ID 4
#define ARM_MRT_MASK 7 << 25
#define ARM_MRT_TAG ARM_MRT_ID << 25
#define ARM_DEF_MRT(regs, rn, l, w, s, u, p, cond) \
(regs) | \
(rn << 16) | \
(l << 20) | \
(w << 21) | \
(s << 22) | \
(u << 23) | \
(p << 24) | \
(ARM_MRT_TAG) | \
ARM_DEF_COND(cond)
#define ARM_LDMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 1, 0, 0, 1, 0, ARMCOND_AL))
#define ARM_STMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 0, 0, 0, 1, 0, ARMCOND_AL))
/* stmdb sp!, {regs} */
#define ARM_PUSH(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
#define ARM_IASM_PUSH(regs) ARM_IASM(ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
/* ldmia sp!, {regs} */
#define ARM_POP(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
#define ARM_IASM_POP(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
/* ldmia sp, {regs} ; (no write-back) */
#define ARM_POP_NWB(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
#define ARM_IASM_POP_NWB(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
#define ARM_PUSH1(p, r1) ARM_PUSH(p, (1 << r1))
#define ARM_PUSH2(p, r1, r2) ARM_PUSH(p, (1 << r1) | (1 << r2))
#define ARM_PUSH3(p, r1, r2, r3) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3))
#define ARM_PUSH4(p, r1, r2, r3, r4) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
#define ARM_PUSH5(p, r1, r2, r3, r4, r5) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
#define ARM_PUSH6(p, r1, r2, r3, r4, r5, r6) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6))
#define ARM_PUSH7(p, r1, r2, r3, r4, r5, r6, r7) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7))
#define ARM_PUSH8(p, r1, r2, r3, r4, r5, r6, r7, r8) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8))
#define ARM_POP8(p, r1, r2, r3, r4, r5, r6, r7, r8) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7) | (1 << r8))
#define ARM_POP7(p, r1, r2, r3, r4, r5, r6, r7) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6) | (1 << r7))
#define ARM_POP6(p, r1, r2, r3, r4, r5, r6) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5) | (1 << r6))
#define ARM_POP5(p, r1, r2, r3, r4, r5) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
#define ARM_POP4(p, r1, r2, r3, r4) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
#define ARM_POP3(p, r1, r2, r3) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3))
#define ARM_POP2(p, r1, r2) ARM_POP(p, (1 << r1) | (1 << r2))
#define ARM_POP1(p, r1) ARM_POP(p, (1 << r1))
/* Multiply instructions */
typedef struct {
arminstr_t rm : 4;
arminstr_t tag2 : 4; /* 9 */
arminstr_t rs : 4;
arminstr_t rn : 4;
arminstr_t rd : 4;
arminstr_t s : 1;
arminstr_t opcode : 3;
arminstr_t tag : 4;
arminstr_t cond : 4;
} ARMInstrMul;
#define ARM_MUL_ID 0
#define ARM_MUL_ID2 9
#define ARM_MUL_MASK ((0xF << 24) | (0xF << 4))
#define ARM_MUL_TAG ((ARM_MUL_ID << 24) | (ARM_MUL_ID2 << 4))
#define ARM_DEF_MUL_COND(op, rd, rm, rs, rn, s, cond) \
(rm) | \
((rs) << 8) | \
((rn) << 12) | \
((rd) << 16) | \
((s & 1) << 17) | \
((op & 7) << 18) | \
ARM_MUL_TAG | \
ARM_DEF_COND(cond)
/* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */
#define ARM_MUL_COND(p, rd, rm, rs, cond) \
ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
#define ARM_MUL(p, rd, rm, rs) \
ARM_MUL_COND(p, rd, rm, rs, ARMCOND_AL)
#define ARM_MULS_COND(p, rd, rm, rs, cond) \
ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
#define ARM_MULS(p, rd, rm, rs) \
ARM_MULS_COND(p, rd, rm, rs, ARMCOND_AL)
#define ARM_MUL_REG_REG(p, rd, rm, rs) ARM_MUL(p, rd, rm, rs)
#define ARM_MULS_REG_REG(p, rd, rm, rs) ARM_MULS(p, rd, rm, rs)
/* inline */
#define ARM_IASM_MUL_COND(rd, rm, rs, cond) \
ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
#define ARM_IASM_MUL(rd, rm, rs) \
ARM_IASM_MUL_COND(rd, rm, rs, ARMCOND_AL)
#define ARM_IASM_MULS_COND(rd, rm, rs, cond) \
ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
#define ARM_IASM_MULS(rd, rm, rs) \
ARM_IASM_MULS_COND(rd, rm, rs, ARMCOND_AL)
/* Rd := (Rm * Rs) + Rn; 32x32+32->32 */
#define ARM_MLA_COND(p, rd, rm, rs, rn, cond) \
ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
#define ARM_MLA(p, rd, rm, rs, rn) \
ARM_MLA_COND(p, rd, rm, rs, rn, ARMCOND_AL)
#define ARM_MLAS_COND(p, rd, rm, rs, rn, cond) \
ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
#define ARM_MLAS(p, rd, rm, rs, rn) \
ARM_MLAS_COND(p, rd, rm, rs, rn, ARMCOND_AL)
/* inline */
#define ARM_IASM_MLA_COND(rd, rm, rs, rn, cond) \
ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
#define ARM_IASM_MLA(rd, rm, rs, rn) \
ARM_IASM_MLA_COND(rd, rm, rs, rn, ARMCOND_AL)
#define ARM_IASM_MLAS_COND(rd, rm, rs, rn, cond) \
ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
#define ARM_IASM_MLAS(rd, rm, rs, rn) \
ARM_IASM_MLAS_COND(rd, rm, rs, rn, ARMCOND_AL)
/* Word/byte transfer */
typedef union {
ARMDPI_op2_reg_imm op2_reg_imm;
struct {
arminstr_t op2_imm : 12;
arminstr_t rd : 4;
arminstr_t rn : 4;
arminstr_t ls : 1;
arminstr_t wb : 1;
arminstr_t b : 1;
arminstr_t u : 1; /* down(0) / up(1) */
arminstr_t p : 1; /* post-index(0) / pre-index(1) */
arminstr_t type : 1; /* imm(0) / register(1) */
arminstr_t tag : 2; /* 0 1 */
arminstr_t cond : 4;
} all;
} ARMInstrWXfer;
#define ARM_WXFER_ID 1
#define ARM_WXFER_MASK 3 << 26
#define ARM_WXFER_TAG ARM_WXFER_ID << 26
#define ARM_DEF_WXFER_IMM(imm12, rd, rn, ls, wb, b, p, cond) \
((((int)imm12) < 0) ? -(int)(imm12) : (imm12)) | \
((rd) << 12) | \
((rn) << 16) | \
((ls) << 20) | \
((wb) << 21) | \
((b) << 22) | \
(((int)(imm12) >= 0) << 23) | \
((p) << 24) | \
ARM_WXFER_TAG | \
ARM_DEF_COND(cond)
#define ARM_WXFER_MAX_OFFS 0xFFF
/* this macro checks for imm12 bounds */
#define ARM_EMIT_WXFER_IMM(ptr, imm12, rd, rn, ls, wb, b, p, cond) \
do { \
int _imm12 = (int)(imm12) < -ARM_WXFER_MAX_OFFS \
? -ARM_WXFER_MAX_OFFS \
: (int)(imm12) > ARM_WXFER_MAX_OFFS \
? ARM_WXFER_MAX_OFFS \
: (int)(imm12); \
ARM_EMIT((ptr), \
ARM_DEF_WXFER_IMM(_imm12, (rd), (rn), (ls), (wb), (b), (p), (cond))); \
} while (0)
/* LDRx */
/* immediate offset, post-index */
#define ARM_LDR_IMM_POST_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 0, cond))
#define ARM_LDR_IMM_POST(p, rd, rn, imm) ARM_LDR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
#define ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 0, cond))
#define ARM_LDRB_IMM_POST(p, rd, rn, imm) ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
/* immediate offset, pre-index */
#define ARM_LDR_IMM_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
#define ARM_LDR_IMM(p, rd, rn, imm) ARM_LDR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
#define ARM_LDRB_IMM_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
#define ARM_LDRB_IMM(p, rd, rn, imm) ARM_LDRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
/* STRx */
/* immediate offset, post-index */
#define ARM_STR_IMM_POST_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 0, cond))
#define ARM_STR_IMM_POST(p, rd, rn, imm) ARM_STR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
#define ARM_STRB_IMM_POST_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 0, cond))
#define ARM_STRB_IMM_POST(p, rd, rn, imm) ARM_STRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
/* immediate offset, pre-index */
#define ARM_STR_IMM_COND(p, rd, rn, imm, cond) \
ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)
/* ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)) */
#define ARM_STR_IMM(p, rd, rn, imm) ARM_STR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
#define ARM_STRB_IMM_COND(p, rd, rn, imm, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 1, cond))
#define ARM_STRB_IMM(p, rd, rn, imm) ARM_STRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
/* write-back */
#define ARM_STR_IMM_WB_COND(p, rd, rn, imm, cond) \
ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 1, 0, 1, cond)
#define ARM_STR_IMM_WB(p, rd, rn, imm) ARM_STR_IMM_WB_COND(p, rd, rn, imm, ARMCOND_AL)
#define ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, u, p, cond) \
(rm) | \
((shift_type) << 5) | \
((shift) << 7) | \
((rd) << 12) | \
((rn) << 16) | \
((ls) << 20) | \
((wb) << 21) | \
((b) << 22) | \
((u) << 23) | \
((p) << 24) | \
(1 << 25) | \
ARM_WXFER_TAG | \
ARM_DEF_COND(cond)
#define ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_UP, p, cond)
#define ARM_DEF_WXFER_REG_MINUS_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_DOWN, p, cond)
#define ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
#define ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
#define ARM_LDR_REG_REG(p, rd, rn, rm) \
ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
#define ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
#define ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
#define ARM_LDRB_REG_REG(p, rd, rn, rm) \
ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
#define ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 0, 1, cond))
#define ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
#define ARM_STR_REG_REG(p, rd, rn, rm) \
ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
/* zero-extend */
#define ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 1, 1, cond))
#define ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
#define ARM_STRB_REG_REG(p, rd, rn, rm) \
ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
/* ARMv4+ */
/* Half-word or byte (signed) transfer. */
typedef struct {
arminstr_t rm : 4; /* imm_lo */
arminstr_t tag3 : 1; /* 1 */
arminstr_t h : 1; /* half-word or byte */
arminstr_t s : 1; /* sign-extend or zero-extend */
arminstr_t tag2 : 1; /* 1 */
arminstr_t imm_hi : 4;
arminstr_t rd : 4;
arminstr_t rn : 4;
arminstr_t ls : 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -