|
|
@ -260,21 +260,6 @@ void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) { |
|
|
|
c[3] = op2 >> 8; |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_FORMAT_2(op, rlo_dest, rlo_src, src_b) ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest)) |
|
|
|
|
|
|
|
void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b) { |
|
|
|
assert(rlo_dest < ASM_THUMB_REG_R8); |
|
|
|
assert(rlo_src < ASM_THUMB_REG_R8); |
|
|
|
asm_thumb_op16(as, OP_FORMAT_2(op, rlo_dest, rlo_src, src_b)); |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_FORMAT_3(op, rlo, i8) ((op) | ((rlo) << 8) | (i8)) |
|
|
|
|
|
|
|
void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8) { |
|
|
|
assert(rlo < ASM_THUMB_REG_R8); |
|
|
|
asm_thumb_op16(as, OP_FORMAT_3(op, rlo, i8)); |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest)) |
|
|
|
|
|
|
|
void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) { |
|
|
@ -283,12 +268,6 @@ void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) { |
|
|
|
asm_thumb_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src)); |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset) ((op) | (((offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest)) |
|
|
|
|
|
|
|
void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset) { |
|
|
|
asm_thumb_op16(as, OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset)); |
|
|
|
} |
|
|
|
|
|
|
|
void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) { |
|
|
|
uint op_lo; |
|
|
|
if (reg_src < 8) { |
|
|
@ -305,26 +284,13 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) { |
|
|
|
asm_thumb_op16(as, 0x4600 | op_lo); |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_MOVW (0xf240) |
|
|
|
#define OP_MOVT (0xf2c0) |
|
|
|
|
|
|
|
// if loading lo half with movw, the i16 value will be zero extended into the r32 register!
|
|
|
|
STATIC void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) { |
|
|
|
void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) { |
|
|
|
assert(reg_dest < ASM_THUMB_REG_R15); |
|
|
|
// mov[wt] reg_dest, #i16_src
|
|
|
|
asm_thumb_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff)); |
|
|
|
} |
|
|
|
|
|
|
|
// the i16_src value will be zero extended into the r32 register!
|
|
|
|
void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { |
|
|
|
asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i16_src); |
|
|
|
} |
|
|
|
|
|
|
|
// the i16_src value will be zero extended into the r32 register!
|
|
|
|
void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { |
|
|
|
asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i16_src); |
|
|
|
} |
|
|
|
|
|
|
|
#define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff)) |
|
|
|
|
|
|
|
void asm_thumb_b_n(asm_thumb_t *as, uint label) { |
|
|
@ -355,15 +321,15 @@ void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) { |
|
|
|
// movw, movt does it in 8 bytes
|
|
|
|
// ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw
|
|
|
|
|
|
|
|
asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i32); |
|
|
|
asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i32 >> 16); |
|
|
|
asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32); |
|
|
|
asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVT, reg_dest, i32 >> 16); |
|
|
|
} |
|
|
|
|
|
|
|
void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) { |
|
|
|
if (reg_dest < 8 && UNSIGNED_FIT8(i32)) { |
|
|
|
asm_thumb_mov_rlo_i8(as, reg_dest, i32); |
|
|
|
} else if (UNSIGNED_FIT16(i32)) { |
|
|
|
asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i32); |
|
|
|
asm_thumb_mov_reg_i16(as, ASM_THUMB_OP_MOVW, reg_dest, i32); |
|
|
|
} else { |
|
|
|
asm_thumb_mov_reg_i32(as, reg_dest, i32); |
|
|
|
} |
|
|
@ -485,7 +451,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp |
|
|
|
|
|
|
|
if (fun_id < 32) { |
|
|
|
// load ptr to function from table, indexed by fun_id (must be in range 0-31); 4 bytes
|
|
|
|
asm_thumb_op16(as, OP_FORMAT_9_10(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, ASM_THUMB_REG_R7, fun_id)); |
|
|
|
asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, ASM_THUMB_REG_R7, fun_id)); |
|
|
|
asm_thumb_op16(as, OP_BLX(reg_temp)); |
|
|
|
} else { |
|
|
|
// load ptr to function into register using immediate; 6 bytes
|
|
|
|