diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/asmthumb.c | 39 | ||||
-rw-r--r-- | py/asmthumb.h | 11 | ||||
-rw-r--r-- | py/emitinlinethumb.c | 20 |
3 files changed, 41 insertions, 29 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c index c361dbd0a8..d5452ff6f5 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -293,27 +293,44 @@ void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_ #define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff)) -void asm_thumb_b_n(asm_thumb_t *as, uint label) { +bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction if (SIGNED_FIT12(rel)) { asm_thumb_op16(as, OP_B_N(rel)); + return true; } else { - printf("asm_thumb_b_n: branch does not fit in 12 bits\n"); + return false; } } #define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff)) -void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label) { +bool asm_thumb_bcc_n_label(asm_thumb_t *as, int cond, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->code_offset; rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction if (SIGNED_FIT9(rel)) { asm_thumb_op16(as, OP_BCC_N(cond, rel)); + return true; } else { - printf("asm_thumb_bcc_n: branch does not fit in 9 bits\n"); + return false; + } +} + +#define OP_BL_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) +#define OP_BL_LO(byte_offset) (0xf800 | (((byte_offset) >> 1) & 0x07ff)) + +bool asm_thumb_bl_label(asm_thumb_t *as, uint label) { + mp_uint_t dest = get_label_dest(as, label); + mp_int_t rel = dest - as->code_offset; + rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction + if (SIGNED_FIT23(rel)) { + asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel)); + return true; + } else { + return false; } } @@ -422,20 +439,6 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { } } -#define OP_BL_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) -#define OP_BL_LO(byte_offset) (0xf800 | (((byte_offset) >> 1) & 0x07ff)) - -void asm_thumb_bl(asm_thumb_t *as, uint label) { - mp_uint_t dest = get_label_dest(as, label); - mp_int_t rel = dest - as->code_offset; - rel -= 4; // account for instruction prefetch, PC is 4 bytes ahead of this instruction - if (SIGNED_FIT23(rel)) { - asm_thumb_op32(as, OP_BL_HI(rel), OP_BL_LO(rel)); - } else { - printf("asm_thumb_bl: branch does not fit in 23 bits\n"); - } -} - #define OP_BLX(reg) (0x4780 | ((reg) << 3)) #define OP_SVC(arg) (0xdf00 | (arg)) diff --git a/py/asmthumb.h b/py/asmthumb.h index 8d413322f2..2dd4dbb995 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -214,8 +214,10 @@ static inline void asm_thumb_ldrh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uin void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src); void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src); -void asm_thumb_b_n(asm_thumb_t *as, uint label); -void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label); +// these return true if the destination is in range, false otherwise +bool asm_thumb_b_n_label(asm_thumb_t *as, uint label); +bool asm_thumb_bcc_n_label(asm_thumb_t *as, int cond, uint label); +bool asm_thumb_bl_label(asm_thumb_t *as, uint label); void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience @@ -224,9 +226,8 @@ void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience -void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience ? +void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch -void asm_thumb_bl(asm_thumb_t *as, uint label); -void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp); // convenience ? +void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp); // convenience #endif // __MICROPY_INCLUDED_PY_ASMTHUMB_H__ diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 530bd95254..ddcd5d3947 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -367,12 +367,14 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a } else if (n_args == 1) { if (strcmp(op_str, "b") == 0) { int label_num = get_arg_label(emit, op_str, pn_args[0]); - // TODO check that this succeeded, ie branch was within range - asm_thumb_b_n(emit->as, label_num); + if (!asm_thumb_b_n_label(emit->as, label_num)) { + goto branch_not_in_range; + } } else if (strcmp(op_str, "bl") == 0) { int label_num = get_arg_label(emit, op_str, pn_args[0]); - // TODO check that this succeeded, ie branch was within range - asm_thumb_bl(emit->as, label_num); + if (!asm_thumb_bl_label(emit->as, label_num)) { + goto branch_not_in_range; + } } else if (strcmp(op_str, "bx") == 0) { mp_uint_t r = get_arg_reg(emit, op_str, pn_args[0], 15); asm_thumb_op16(emit->as, 0x4700 | (r << 3)); @@ -387,8 +389,9 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a goto unknown_op; } int label_num = get_arg_label(emit, op_str, pn_args[0]); - // TODO check that this succeeded, ie branch was within range - asm_thumb_bcc_n(emit->as, cc, label_num); + if (!asm_thumb_bcc_n_label(emit->as, cc, label_num)) { + goto branch_not_in_range; + } } else if (op_str[0] == 'i' && op_str[1] == 't') { const char *arg_str = get_arg_str(pn_args[0]); mp_uint_t cc = -1; @@ -608,6 +611,11 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a unknown_op: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Thumb instruction '%s' with %d arguments", op_str, n_args)); + return; + +branch_not_in_range: + emit_inline_thumb_error_msg(emit, "branch not in range"); + return; } const emit_inline_asm_method_table_t emit_inline_thumb_method_table = { |