3 * Copyright (c) 2002 Sergey Chaban <serge@wildwestsoftware.com>
14 typedef unsigned int arminstr_t;
15 typedef unsigned int armword_t;
17 /* Helper functions */
18 arminstr_t* arm_emit_std_prologue(arminstr_t* p, unsigned int local_size);
19 arminstr_t* arm_emit_std_epilogue(arminstr_t* p, unsigned int local_size, int pop_regs);
20 arminstr_t* arm_emit_lean_prologue(arminstr_t* p, unsigned int local_size, int push_regs);
21 int arm_is_power_of_2(armword_t val);
22 int calc_arm_mov_const_shift(armword_t val);
23 int is_arm_const(armword_t val);
24 int arm_bsf(armword_t val);
25 arminstr_t* arm_mov_reg_imm32_cond(arminstr_t* p, int reg, armword_t imm32, int cond);
26 arminstr_t* arm_mov_reg_imm32(arminstr_t* p, int reg, armword_t imm32);
30 #if defined(_MSC_VER) || defined(__CC_NORCROFT)
31 void __inline _arm_emit(arminstr_t** p, arminstr_t i) {**p = i; (*p)++;}
32 # define ARM_EMIT(p, i) _arm_emit((arminstr_t**)&p, (arminstr_t)(i))
34 # define ARM_EMIT(p, i) do { arminstr_t *__ainstrp = (void*)(p); *__ainstrp = (arminstr_t)(i); (p) = (void*)(__ainstrp+1);} while (0)
37 #if defined(_MSC_VER) && !defined(ARM_NOIASM)
38 # define ARM_IASM(_expr) __emit (_expr)
40 # define ARM_IASM(_expr)
43 /* even_scale = rot << 1 */
44 #define ARM_SCALE(imm8, even_scale) ( ((imm8) >> (even_scale)) | ((imm8) << (32 - even_scale)) )
69 ARMREG_A1 = ARMREG_R0,
70 ARMREG_A2 = ARMREG_R1,
71 ARMREG_A3 = ARMREG_R2,
72 ARMREG_A4 = ARMREG_R3,
75 ARMREG_V1 = ARMREG_R4,
76 ARMREG_V2 = ARMREG_R5,
77 ARMREG_V3 = ARMREG_R6,
78 ARMREG_V4 = ARMREG_R7,
79 ARMREG_V5 = ARMREG_R8,
80 ARMREG_V6 = ARMREG_R9,
81 ARMREG_V7 = ARMREG_R10,
83 ARMREG_FP = ARMREG_R11,
84 ARMREG_IP = ARMREG_R12,
85 ARMREG_SP = ARMREG_R13,
86 ARMREG_LR = ARMREG_R14,
87 ARMREG_PC = ARMREG_R15,
107 /* XScale: acc0 on CP0 */
108 ARMREG_ACC0 = ARMREG_CR0,
110 ARMREG_MAX = ARMREG_R15
113 /* number of argument registers */
114 #define ARM_NUM_ARG_REGS 4
116 /* bitvector for all argument regs (A1-A4) */
117 #define ARM_ALL_ARG_REGS \
118 (1 << ARMREG_A1) | (1 << ARMREG_A2) | (1 << ARMREG_A3) | (1 << ARMREG_A4)
122 ARMCOND_EQ = 0x0, /* Equal; Z = 1 */
123 ARMCOND_NE = 0x1, /* Not equal, or unordered; Z = 0 */
124 ARMCOND_CS = 0x2, /* Carry set; C = 1 */
125 ARMCOND_HS = ARMCOND_CS, /* Unsigned higher or same; */
126 ARMCOND_CC = 0x3, /* Carry clear; C = 0 */
127 ARMCOND_LO = ARMCOND_CC, /* Unsigned lower */
128 ARMCOND_MI = 0x4, /* Negative; N = 1 */
129 ARMCOND_PL = 0x5, /* Positive or zero; N = 0 */
130 ARMCOND_VS = 0x6, /* Overflow; V = 1 */
131 ARMCOND_VC = 0x7, /* No overflow; V = 0 */
132 ARMCOND_HI = 0x8, /* Unsigned higher; C = 1 && Z = 0 */
133 ARMCOND_LS = 0x9, /* Unsigned lower or same; C = 0 || Z = 1 */
134 ARMCOND_GE = 0xA, /* Signed greater than or equal; N = V */
135 ARMCOND_LT = 0xB, /* Signed less than; N != V */
136 ARMCOND_GT = 0xC, /* Signed greater than; Z = 0 && N = V */
137 ARMCOND_LE = 0xD, /* Signed less than or equal; Z = 1 && N != V */
138 ARMCOND_AL = 0xE, /* Always */
139 ARMCOND_NV = 0xF, /* Never */
144 #define ARMCOND_MASK (ARMCOND_NV << ARMCOND_SHIFT)
146 #define ARM_DEF_COND(cond) (((cond) & 0xF) << ARMCOND_SHIFT)
156 ARMSHIFT_ASL = ARMSHIFT_LSL
187 /* not really opcodes */
193 ARMOP_MUL = 0x0, /* Rd := Rm*Rs */
194 ARMOP_MLA = 0x1, /* Rd := (Rm*Rs)+Rn */
202 /* for data transfers with register offset */
233 /* Generic form - all ARM instructions are conditional. */
235 arminstr_t icode : 28;
241 /* Branch or Branch with Link instructions. */
243 arminstr_t offset : 24;
245 arminstr_t tag : 3; /* 1 0 1 */
250 #define ARM_BR_MASK 7 << 25
251 #define ARM_BR_TAG ARM_BR_ID << 25
253 #define ARM_DEF_BR(offs, l, cond) ((offs) | ((l) << 24) | (ARM_BR_TAG) | (cond << ARMCOND_SHIFT))
256 #define ARM_B_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 0, cond))
257 #define ARM_B(p, offs) ARM_B_COND((p), ARMCOND_AL, (offs))
258 /* branch with link */
259 #define ARM_BL_COND(p, cond, offset) ARM_EMIT(p, ARM_DEF_BR(offset, 1, cond))
260 #define ARM_BL(p, offs) ARM_BL_COND((p), ARMCOND_AL, (offs))
262 #define ARM_DEF_BX(reg,sub,cond) (0x12fff << 8 | (reg) | ((sub) << 4) | ((cond) << ARMCOND_SHIFT))
264 #define ARM_BX_COND(p, cond, reg) ARM_EMIT(p, ARM_DEF_BX(reg, 1, cond))
265 #define ARM_BX(p, reg) ARM_BX_COND((p), ARMCOND_AL, (reg))
267 #define ARM_BLX_REG_COND(p, cond, reg) ARM_EMIT(p, ARM_DEF_BX(reg, 3, cond))
268 #define ARM_BLX_REG(p, reg) ARM_BLX_REG_COND((p), ARMCOND_AL, (reg))
270 /* Data Processing Instructions - there are 3 types. */
279 arminstr_t tag : 1; /* 0 - immediate shift, 1 - reg shift */
280 arminstr_t type : 2; /* shift type - logical, arithmetic, rotate */
281 } ARMDPI_op2_reg_shift;
284 /* op2 is reg shift by imm */
286 ARMDPI_op2_reg_shift r2;
288 arminstr_t _dummy_r2 : 7;
289 arminstr_t shift : 5;
291 } ARMDPI_op2_reg_imm;
293 /* op2 is reg shift by reg */
295 ARMDPI_op2_reg_shift r2;
297 arminstr_t _dummy_r2 : 7;
298 arminstr_t pad : 1; /* always 0, to differentiate from HXFER etc. */
301 } ARMDPI_op2_reg_reg;
303 /* Data processing instrs */
305 ARMDPI_op2_imm op2_imm;
307 ARMDPI_op2_reg_shift op2_reg;
308 ARMDPI_op2_reg_imm op2_reg_imm;
309 ARMDPI_op2_reg_reg op2_reg_reg;
312 arminstr_t op2 : 12; /* raw operand 2 */
313 arminstr_t rd : 4; /* destination reg */
314 arminstr_t rn : 4; /* first operand reg */
315 arminstr_t s : 1; /* S-bit controls PSR update */
316 arminstr_t opcode : 4; /* arithmetic/logic operation */
317 arminstr_t type : 1; /* type of op2, 0 = register, 1 = immediate */
318 arminstr_t tag : 2; /* 0 0 */
324 #define ARM_DPI_MASK 3 << 26
325 #define ARM_DPI_TAG ARM_DPI_ID << 26
327 #define ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, cond) \
329 (((rot) & 0xF) << 8) | \
339 #define ARM_DEF_DPI_IMM(imm8, rot, rd, rn, s, op) \
340 ARM_DEF_DPI_IMM_COND(imm8, rot, rd, rn, s, op, ARMCOND_AL)
343 #define ARM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
344 ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
345 #define ARM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
346 ARM_EMIT(p, ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))
349 #define ARM_IASM_DPIOP_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
350 ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 0, (op), cond))
351 #define ARM_IASM_DPIOP_S_REG_IMM8ROT_COND(p, op, rd, rn, imm8, rot, cond) \
352 ARM_IASM(ARM_DEF_DPI_IMM_COND((imm8), ((rot) >> 1), (rd), (rn), 1, (op), cond))
356 #define ARM_DEF_DPI_REG_IMMSHIFT_COND(rm, shift_type, imm_shift, rd, rn, s, op, cond) \
358 ((shift_type & 3) << 5) | \
359 (((imm_shift) & 0x1F) << 7) | \
368 #define ARM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
369 ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
371 #define ARM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
372 ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
374 #define ARM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
375 ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
377 #define ARM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
378 ARM_EMIT(p, ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
381 #define ARM_IASM_DPIOP_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
382 ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 0, (op), cond))
384 #define ARM_IASM_DPIOP_S_REG_IMMSHIFT_COND(p, op, rd, rn, rm, shift_t, imm_shift, cond) \
385 ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), shift_t, imm_shift, (rd), (rn), 1, (op), cond))
387 #define ARM_IASM_DPIOP_REG_REG_COND(p, op, rd, rn, rm, cond) \
388 ARM_IASM(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 0, (op), cond))
390 #define ARM_IASM_DPIOP_S_REG_REG_COND(p, op, rd, rn, rm, cond) \
391 ARM_IASM_EMIT(ARM_DEF_DPI_REG_IMMSHIFT_COND((rm), ARMSHIFT_LSL, 0, (rd), (rn), 1, (op), cond))
394 /* Rd := Rn op (Rm shift_type Rs) */
395 #define ARM_DEF_DPI_REG_REGSHIFT_COND(rm, shift_type, rs, rd, rn, s, op, cond) \
398 ((shift_type & 3) << 5) | \
408 #define ARM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
409 ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
411 #define ARM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
412 ARM_EMIT(p, ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
415 #define ARM_IASM_DPIOP_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
416 ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 0, (op), cond))
418 #define ARM_IASM_DPIOP_S_REG_REGSHIFT_COND(p, op, rd, rn, rm, shift_t, rs, cond) \
419 ARM_IASM(ARM_DEF_DPI_REG_REGSHIFT_COND((rm), shift_t, (rs), (rd), (rn), 1, (op), cond))
423 /* Multiple register transfer. */
425 arminstr_t reg_list : 16; /* bitfield */
426 arminstr_t rn : 4; /* base reg */
427 arminstr_t ls : 1; /* load(1)/store(0) */
428 arminstr_t wb : 1; /* write-back "!" */
429 arminstr_t s : 1; /* restore PSR, force user bit */
430 arminstr_t u : 1; /* up/down */
431 arminstr_t p : 1; /* pre(1)/post(0) index */
432 arminstr_t tag : 3; /* 1 0 0 */
437 #define ARM_MRT_MASK 7 << 25
438 #define ARM_MRT_TAG ARM_MRT_ID << 25
440 #define ARM_DEF_MRT(regs, rn, l, w, s, u, p, cond) \
452 #define ARM_LDMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 1, 0, 0, 1, 0, ARMCOND_AL))
453 #define ARM_STMIA(p, base, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, base, 0, 0, 0, 1, 0, ARMCOND_AL))
455 /* stmdb sp!, {regs} */
456 #define ARM_PUSH(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
457 #define ARM_IASM_PUSH(regs) ARM_IASM(ARM_DEF_MRT(regs, ARMREG_SP, 0, 1, 0, 0, 1, ARMCOND_AL))
459 /* ldmia sp!, {regs} */
460 #define ARM_POP(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
461 #define ARM_IASM_POP(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 1, 0, 1, 0, ARMCOND_AL))
463 /* ldmia sp, {regs} ; (no write-back) */
464 #define ARM_POP_NWB(p, regs) ARM_EMIT(p, ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
465 #define ARM_IASM_POP_NWB(regs) ARM_IASM_EMIT(ARM_DEF_MRT(regs, ARMREG_SP, 1, 0, 0, 1, 0, ARMCOND_AL))
467 #define ARM_PUSH1(p, r1) ARM_PUSH(p, (1 << r1))
468 #define ARM_PUSH2(p, r1, r2) ARM_PUSH(p, (1 << r1) | (1 << r2))
469 #define ARM_PUSH3(p, r1, r2, r3) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3))
470 #define ARM_PUSH4(p, r1, r2, r3, r4) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
471 #define ARM_PUSH5(p, r1, r2, r3, r4, r5) ARM_PUSH(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
472 #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))
473 #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))
474 #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))
476 #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))
477 #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))
478 #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))
479 #define ARM_POP5(p, r1, r2, r3, r4, r5) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4) | (1 << r5))
480 #define ARM_POP4(p, r1, r2, r3, r4) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3) | (1 << r4))
481 #define ARM_POP3(p, r1, r2, r3) ARM_POP(p, (1 << r1) | (1 << r2) | (1 << r3))
482 #define ARM_POP2(p, r1, r2) ARM_POP(p, (1 << r1) | (1 << r2))
483 #define ARM_POP1(p, r1) ARM_POP(p, (1 << r1))
486 /* Multiply instructions */
489 arminstr_t tag2 : 4; /* 9 */
494 arminstr_t opcode : 3;
500 #define ARM_MUL_ID2 9
501 #define ARM_MUL_MASK ((0xF << 24) | (0xF << 4))
502 #define ARM_MUL_TAG ((ARM_MUL_ID << 24) | (ARM_MUL_ID2 << 4))
504 #define ARM_DEF_MUL_COND(op, rd, rm, rs, rn, s, cond) \
514 /* Rd := (Rm * Rs)[31:0]; 32 x 32 -> 32 */
515 #define ARM_MUL_COND(p, rd, rm, rs, cond) \
516 ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
517 #define ARM_MUL(p, rd, rm, rs) \
518 ARM_MUL_COND(p, rd, rm, rs, ARMCOND_AL)
519 #define ARM_MULS_COND(p, rd, rm, rs, cond) \
520 ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
521 #define ARM_MULS(p, rd, rm, rs) \
522 ARM_MULS_COND(p, rd, rm, rs, ARMCOND_AL)
523 #define ARM_MUL_REG_REG(p, rd, rm, rs) ARM_MUL(p, rd, rm, rs)
524 #define ARM_MULS_REG_REG(p, rd, rm, rs) ARM_MULS(p, rd, rm, rs)
527 #define ARM_IASM_MUL_COND(rd, rm, rs, cond) \
528 ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 0, cond))
529 #define ARM_IASM_MUL(rd, rm, rs) \
530 ARM_IASM_MUL_COND(rd, rm, rs, ARMCOND_AL)
531 #define ARM_IASM_MULS_COND(rd, rm, rs, cond) \
532 ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MUL, rd, rm, rs, 0, 1, cond))
533 #define ARM_IASM_MULS(rd, rm, rs) \
534 ARM_IASM_MULS_COND(rd, rm, rs, ARMCOND_AL)
537 /* Rd := (Rm * Rs) + Rn; 32x32+32->32 */
538 #define ARM_MLA_COND(p, rd, rm, rs, rn, cond) \
539 ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
540 #define ARM_MLA(p, rd, rm, rs, rn) \
541 ARM_MLA_COND(p, rd, rm, rs, rn, ARMCOND_AL)
542 #define ARM_MLAS_COND(p, rd, rm, rs, rn, cond) \
543 ARM_EMIT(p, ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
544 #define ARM_MLAS(p, rd, rm, rs, rn) \
545 ARM_MLAS_COND(p, rd, rm, rs, rn, ARMCOND_AL)
548 #define ARM_IASM_MLA_COND(rd, rm, rs, rn, cond) \
549 ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 0, cond))
550 #define ARM_IASM_MLA(rd, rm, rs, rn) \
551 ARM_IASM_MLA_COND(rd, rm, rs, rn, ARMCOND_AL)
552 #define ARM_IASM_MLAS_COND(rd, rm, rs, rn, cond) \
553 ARM_IASM_EMIT(ARM_DEF_MUL_COND(ARMOP_MLA, rd, rm, rs, rn, 1, cond))
554 #define ARM_IASM_MLAS(rd, rm, rs, rn) \
555 ARM_IASM_MLAS_COND(rd, rm, rs, rn, ARMCOND_AL)
559 /* Word/byte transfer */
561 ARMDPI_op2_reg_imm op2_reg_imm;
563 arminstr_t op2_imm : 12;
569 arminstr_t u : 1; /* down(0) / up(1) */
570 arminstr_t p : 1; /* post-index(0) / pre-index(1) */
571 arminstr_t type : 1; /* imm(0) / register(1) */
572 arminstr_t tag : 2; /* 0 1 */
577 #define ARM_WXFER_ID 1
578 #define ARM_WXFER_MASK 3 << 26
579 #define ARM_WXFER_TAG ARM_WXFER_ID << 26
582 #define ARM_DEF_WXFER_IMM(imm12, rd, rn, ls, wb, b, p, cond) \
583 ((((int)imm12) < 0) ? -(int)(imm12) : (imm12)) | \
589 (((int)(imm12) >= 0) << 23) | \
594 #define ARM_WXFER_MAX_OFFS 0xFFF
596 /* this macro checks for imm12 bounds */
597 #define ARM_EMIT_WXFER_IMM(ptr, imm12, rd, rn, ls, wb, b, p, cond) \
599 int _imm12 = (int)(imm12) < -ARM_WXFER_MAX_OFFS \
600 ? -ARM_WXFER_MAX_OFFS \
601 : (int)(imm12) > ARM_WXFER_MAX_OFFS \
602 ? ARM_WXFER_MAX_OFFS \
605 ARM_DEF_WXFER_IMM(_imm12, (rd), (rn), (ls), (wb), (b), (p), (cond))); \
610 /* immediate offset, post-index */
611 #define ARM_LDR_IMM_POST_COND(p, rd, rn, imm, cond) \
612 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 0, cond))
614 #define ARM_LDR_IMM_POST(p, rd, rn, imm) ARM_LDR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
616 #define ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, cond) \
617 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 0, cond))
619 #define ARM_LDRB_IMM_POST(p, rd, rn, imm) ARM_LDRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
621 /* immediate offset, pre-index */
622 #define ARM_LDR_IMM_COND(p, rd, rn, imm, cond) \
623 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
625 #define ARM_LDR_IMM(p, rd, rn, imm) ARM_LDR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
627 #define ARM_LDRB_IMM_COND(p, rd, rn, imm, cond) \
628 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
630 #define ARM_LDRB_IMM(p, rd, rn, imm) ARM_LDRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
633 /* immediate offset, post-index */
634 #define ARM_STR_IMM_POST_COND(p, rd, rn, imm, cond) \
635 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 0, cond))
637 #define ARM_STR_IMM_POST(p, rd, rn, imm) ARM_STR_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
639 #define ARM_STRB_IMM_POST_COND(p, rd, rn, imm, cond) \
640 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 0, cond))
642 #define ARM_STRB_IMM_POST(p, rd, rn, imm) ARM_STRB_IMM_POST_COND(p, rd, rn, imm, ARMCOND_AL)
644 /* immediate offset, pre-index */
645 #define ARM_STR_IMM_COND(p, rd, rn, imm, cond) \
646 ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)
647 /* ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 0, 1, cond)) */
649 #define ARM_STR_IMM(p, rd, rn, imm) ARM_STR_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
651 #define ARM_STRB_IMM_COND(p, rd, rn, imm, cond) \
652 ARM_EMIT(p, ARM_DEF_WXFER_IMM(imm, rd, rn, ARMOP_STR, 0, 1, 1, cond))
654 #define ARM_STRB_IMM(p, rd, rn, imm) ARM_STRB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
657 #define ARM_STR_IMM_WB_COND(p, rd, rn, imm, cond) \
658 ARM_EMIT_WXFER_IMM(p, imm, rd, rn, ARMOP_STR, 1, 0, 1, cond)
659 #define ARM_STR_IMM_WB(p, rd, rn, imm) ARM_STR_IMM_WB_COND(p, rd, rn, imm, ARMCOND_AL)
662 #define ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, u, p, cond) \
664 ((shift_type) << 5) | \
677 #define ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
678 ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_UP, p, cond)
679 #define ARM_DEF_WXFER_REG_MINUS_REG_COND(rm, shift_type, shift, rd, rn, ls, wb, b, p, cond) \
680 ARM_DEF_WXFER_REG_REG_UPDOWN_COND(rm, shift_type, shift, rd, rn, ls, wb, b, ARM_DOWN, p, cond)
683 #define ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
684 ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 0, 1, cond))
685 #define ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
686 ARM_LDR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
687 #define ARM_LDR_REG_REG(p, rd, rn, rm) \
688 ARM_LDR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
690 #define ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
691 ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_LDR, 0, 1, 1, cond))
692 #define ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
693 ARM_LDRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
694 #define ARM_LDRB_REG_REG(p, rd, rn, rm) \
695 ARM_LDRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
697 #define ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
698 ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 0, 1, cond))
699 #define ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
700 ARM_STR_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
701 #define ARM_STR_REG_REG(p, rd, rn, rm) \
702 ARM_STR_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
705 #define ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, cond) \
706 ARM_EMIT(p, ARM_DEF_WXFER_REG_REG_COND(rm, shift_type, shift, rd, rn, ARMOP_STR, 0, 1, 1, cond))
707 #define ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, shift_type, shift) \
708 ARM_STRB_REG_REG_SHIFT_COND(p, rd, rn, rm, shift_type, shift, ARMCOND_AL)
709 #define ARM_STRB_REG_REG(p, rd, rn, rm) \
710 ARM_STRB_REG_REG_SHIFT(p, rd, rn, rm, ARMSHIFT_LSL, 0)
714 /* Half-word or byte (signed) transfer. */
716 arminstr_t rm : 4; /* imm_lo */
717 arminstr_t tag3 : 1; /* 1 */
718 arminstr_t h : 1; /* half-word or byte */
719 arminstr_t s : 1; /* sign-extend or zero-extend */
720 arminstr_t tag2 : 1; /* 1 */
721 arminstr_t imm_hi : 4;
726 arminstr_t type : 1; /* imm(1) / reg(0) */
727 arminstr_t u : 1; /* +- */
728 arminstr_t p : 1; /* pre/post-index */
733 #define ARM_HXFER_ID 0
734 #define ARM_HXFER_ID2 1
735 #define ARM_HXFER_ID3 1
736 #define ARM_HXFER_MASK ((0x7 << 25) | (0x9 << 4))
737 #define ARM_HXFER_TAG ((ARM_HXFER_ID << 25) | (ARM_HXFER_ID2 << 7) | (ARM_HXFER_ID3 << 4))
739 #define ARM_DEF_HXFER_IMM_COND(imm, h, s, rd, rn, ls, wb, p, cond) \
740 ((imm) < 0?(-(imm)) & 0xF:(imm) & 0xF) | \
743 ((imm) < 0?((-(imm)) << 4) & 0xF00:((imm) << 4) & 0xF00) | \
749 (((int)(imm) >= 0) << 23) | \
754 #define ARM_LDRH_IMM_COND(p, rd, rn, imm, cond) \
755 ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond))
756 #define ARM_LDRH_IMM(p, rd, rn, imm) \
757 ARM_LDRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
758 #define ARM_LDRSH_IMM_COND(p, rd, rn, imm, cond) \
759 ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
760 #define ARM_LDRSH_IMM(p, rd, rn, imm) \
761 ARM_LDRSH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
762 #define ARM_LDRSB_IMM_COND(p, rd, rn, imm, cond) \
763 ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
764 #define ARM_LDRSB_IMM(p, rd, rn, imm) \
765 ARM_LDRSB_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
768 #define ARM_STRH_IMM_COND(p, rd, rn, imm, cond) \
769 ARM_EMIT(p, ARM_DEF_HXFER_IMM_COND(imm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond))
770 #define ARM_STRH_IMM(p, rd, rn, imm) \
771 ARM_STRH_IMM_COND(p, rd, rn, imm, ARMCOND_AL)
774 #define ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, u, p, cond) \
788 #define ARM_DEF_HXFER_REG_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \
789 ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_UP, p, cond)
790 #define ARM_DEF_HXFER_REG_MINUS_REG_COND(rm, h, s, rd, rn, ls, wb, p, cond) \
791 ARM_DEF_HXFER_REG_REG_UPDOWN_COND(rm, h, s, rd, rn, ls, wb, ARM_DOWN, p, cond)
793 #define ARM_LDRH_REG_REG_COND(p, rm, rd, rn, cond) \
794 ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_LDR, 0, 1, cond))
795 #define ARM_LDRH_REG_REG(p, rm, rd, rn) \
796 ARM_LDRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
797 #define ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, cond) \
798 ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
799 #define ARM_LDRSH_REG_REG(p, rm, rd, rn) \
800 ARM_LDRSH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
801 #define ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, cond) \
802 ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 0, 1, rd, rn, ARMOP_LDR, 0, 1, cond))
803 #define ARM_LDRSB_REG_REG(p, rm, rd, rn) ARM_LDRSB_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
805 #define ARM_STRH_REG_REG_COND(p, rm, rd, rn, cond) \
806 ARM_EMIT(p, ARM_DEF_HXFER_REG_REG_COND(rm, 1, 0, rd, rn, ARMOP_STR, 0, 1, cond))
807 #define ARM_STRH_REG_REG(p, rm, rd, rn) \
808 ARM_STRH_REG_REG_COND(p, rm, rd, rn, ARMCOND_AL)
815 arminstr_t tag3 : 8; /* 0x9 */
820 arminstr_t tag : 5; /* 0x2 */
825 #define ARM_SWP_ID2 9
826 #define ARM_SWP_MASK ((0x1F << 23) | (3 << 20) | (0xFF << 4))
827 #define ARM_SWP_TAG ((ARM_SWP_ID << 23) | (ARM_SWP_ID2 << 4))
831 /* Software interrupt */
838 #define ARM_SWI_ID 0xF
839 #define ARM_SWI_MASK (0xF << 24)
840 #define ARM_SWI_TAG (ARM_SWI_ID << 24)
844 /* Co-processor Data Processing */
847 arminstr_t tag2 : 1; /* 0 */
849 arminstr_t cpn : 4; /* CP number */
853 arminstr_t tag : 4; /* 0xE */
857 #define ARM_CDP_ID 0xE
858 #define ARM_CDP_ID2 0
859 #define ARM_CDP_MASK ((0xF << 24) | (1 << 4))
860 #define ARM_CDP_TAG ((ARM_CDP_ID << 24) | (ARM_CDP_ID2 << 4))
863 /* Co-processor Data Transfer (ldc/stc) */
879 #define ARM_CDT_MASK (7 << 25)
880 #define ARM_CDT_TAG (ARM_CDT_ID << 25)
883 /* Co-processor Register Transfer (mcr/mrc) */
897 #define ARM_CRT_ID 0xE
898 #define ARM_CRT_ID2 0x1
899 #define ARM_CRT_MASK ((0xF << 24) | (1 << 4))
900 #define ARM_CRT_TAG ((ARM_CRT_ID << 24) | (ARM_CRT_ID2 << 4))
902 /* Move register to PSR. */
904 ARMDPI_op2_imm op2_imm;
907 arminstr_t pad : 8; /* 0 */
908 arminstr_t tag4 : 4; /* 0xF */
910 arminstr_t tag3 : 2; /* 0x2 */
912 arminstr_t tag2 : 2; /* 0x2 */
914 arminstr_t tag : 2; /* 0 */
920 #define ARM_MSR_ID2 2
921 #define ARM_MSR_ID3 2
922 #define ARM_MSR_ID4 0xF
923 #define ARM_MSR_MASK ((3 << 26) | \
927 #define ARM_MSR_TAG ((ARM_MSR_ID << 26) | \
928 (ARM_MSR_ID2 << 23) | \
929 (ARM_MSR_ID3 << 20) | \
933 /* Move PSR to register. */
935 arminstr_t tag3 : 12;
938 arminstr_t sel : 1; /* CPSR | SPSR */
944 #define ARM_MRS_ID2 0xF
945 #define ARM_MRS_ID3 0
946 #define ARM_MRS_MASK ((0x1F << 23) | (0x3F << 16) | 0xFFF)
947 #define ARM_MRS_TAG ((ARM_MRS_ID << 23) | (ARM_MRS_ID2 << 16) | ARM_MRS_ID3)
952 #include "arm_dpimacros.h"
954 #define ARM_NOP(p) ARM_MOV_REG_REG(p, ARMREG_R0, ARMREG_R0)
957 #define ARM_SHL_IMM_COND(p, rd, rm, imm, cond) \
958 ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond)
959 #define ARM_SHL_IMM(p, rd, rm, imm) \
960 ARM_SHL_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
961 #define ARM_SHLS_IMM_COND(p, rd, rm, imm, cond) \
962 ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, imm, cond)
963 #define ARM_SHLS_IMM(p, rd, rm, imm) \
964 ARM_SHLS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
966 #define ARM_SHR_IMM_COND(p, rd, rm, imm, cond) \
967 ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond)
968 #define ARM_SHR_IMM(p, rd, rm, imm) \
969 ARM_SHR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
970 #define ARM_SHRS_IMM_COND(p, rd, rm, imm, cond) \
971 ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, imm, cond)
972 #define ARM_SHRS_IMM(p, rd, rm, imm) \
973 ARM_SHRS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
975 #define ARM_SAR_IMM_COND(p, rd, rm, imm, cond) \
976 ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond)
977 #define ARM_SAR_IMM(p, rd, rm, imm) \
978 ARM_SAR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
979 #define ARM_SARS_IMM_COND(p, rd, rm, imm, cond) \
980 ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, imm, cond)
981 #define ARM_SARS_IMM(p, rd, rm, imm) \
982 ARM_SARS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
984 #define ARM_ROR_IMM_COND(p, rd, rm, imm, cond) \
985 ARM_MOV_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond)
986 #define ARM_ROR_IMM(p, rd, rm, imm) \
987 ARM_ROR_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
988 #define ARM_RORS_IMM_COND(p, rd, rm, imm, cond) \
989 ARM_MOVS_REG_IMMSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, imm, cond)
990 #define ARM_RORS_IMM(p, rd, rm, imm) \
991 ARM_RORS_IMM_COND(p, rd, rm, imm, ARMCOND_AL)
993 #define ARM_SHL_REG_COND(p, rd, rm, rs, cond) \
994 ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond)
995 #define ARM_SHL_REG(p, rd, rm, rs) \
996 ARM_SHL_REG_COND(p, rd, rm, rs, ARMCOND_AL)
997 #define ARM_SHLS_REG_COND(p, rd, rm, rs, cond) \
998 ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSL, rs, cond)
999 #define ARM_SHLS_REG(p, rd, rm, rs) \
1000 ARM_SHLS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1001 #define ARM_SHLS_REG_REG(p, rd, rm, rs) ARM_SHLS_REG(p, rd, rm, rs)
1003 #define ARM_SHR_REG_COND(p, rd, rm, rs, cond) \
1004 ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond)
1005 #define ARM_SHR_REG(p, rd, rm, rs) \
1006 ARM_SHR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1007 #define ARM_SHRS_REG_COND(p, rd, rm, rs, cond) \
1008 ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_LSR, rs, cond)
1009 #define ARM_SHRS_REG(p, rd, rm, rs) \
1010 ARM_SHRS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1011 #define ARM_SHRS_REG_REG(p, rd, rm, rs) ARM_SHRS_REG(p, rd, rm, rs)
1013 #define ARM_SAR_REG_COND(p, rd, rm, rs, cond) \
1014 ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond)
1015 #define ARM_SAR_REG(p, rd, rm, rs) \
1016 ARM_SAR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1017 #define ARM_SARS_REG_COND(p, rd, rm, rs, cond) \
1018 ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ASR, rs, cond)
1019 #define ARM_SARS_REG(p, rd, rm, rs) \
1020 ARM_SARS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1021 #define ARM_SARS_REG_REG(p, rd, rm, rs) ARM_SARS_REG(p, rd, rm, rs)
1023 #define ARM_ROR_REG_COND(p, rd, rm, rs, cond) \
1024 ARM_MOV_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond)
1025 #define ARM_ROR_REG(p, rd, rm, rs) \
1026 ARM_ROR_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1027 #define ARM_RORS_REG_COND(p, rd, rm, rs, cond) \
1028 ARM_MOVS_REG_REGSHIFT_COND(p, rd, rm, ARMSHIFT_ROR, rs, cond)
1029 #define ARM_RORS_REG(p, rd, rm, rs) \
1030 ARM_RORS_REG_COND(p, rd, rm, rs, ARMCOND_AL)
1031 #define ARM_RORS_REG_REG(p, rd, rm, rs) ARM_RORS_REG(p, rd, rm, rs)
1033 #define ARM_DBRK(p) ARM_EMIT(p, 0xE6000010)
1034 #define ARM_IASM_DBRK() ARM_IASM_EMIT(0xE6000010)
1036 #define ARM_INC(p, reg) ARM_ADD_REG_IMM8(p, reg, reg, 1)
1037 #define ARM_DEC(p, reg) ARM_SUB_REG_IMM8(p, reg, reg, 1)
1042 /* Count leading zeros, CLZ{cond} Rd, Rm */
1045 arminstr_t tag2 : 8;
1047 arminstr_t tag : 12;
1048 arminstr_t cond : 4;
1051 #define ARM_CLZ_ID 0x16F
1052 #define ARM_CLZ_ID2 0xF1
1053 #define ARM_CLZ_MASK ((0xFFF << 16) | (0xFF < 4))
1054 #define ARM_CLZ_TAG ((ARM_CLZ_ID << 16) | (ARM_CLZ_ID2 << 4))
1064 ARMInstrWXfer wxfer;
1065 ARMInstrHXfer hxfer;
1075 ARMInstrGeneric generic;