From ea8be373a975356808a19a79f1dd20383bec82ba Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 7 Jan 2016 14:54:13 +0000 Subject: [PATCH] py/inlinethumb: Remove 30-bit restriction on movwt instruction. movwt can now move a full 32-bit constant into a register. --- docs/reference/asm_thumb2_mov.rst | 7 +++---- py/emitinlinethumb.c | 5 ++--- tests/inlineasm/asmconst.py | 8 ++++++++ tests/inlineasm/asmconst.py.exp | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 tests/inlineasm/asmconst.py create mode 100644 tests/inlineasm/asmconst.py.exp diff --git a/docs/reference/asm_thumb2_mov.rst b/docs/reference/asm_thumb2_mov.rst index e42460881e..900bf957b6 100644 --- a/docs/reference/asm_thumb2_mov.rst +++ b/docs/reference/asm_thumb2_mov.rst @@ -21,8 +21,7 @@ Where immediate values are used, these are zero-extended to 32 bits. Thus movt writes an immediate value to the top halfword of the destination register. It does not affect the contents of the bottom halfword. -* movwt(Rd, imm30) ``Rd = imm30`` +* movwt(Rd, imm32) ``Rd = imm32`` -movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` and a ``movt`` -to move a zero extended 30 bit value into Rd. Where the full 32 bits are required a -workround is to use the movw and movt operations. +movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` followed +by a ``movt`` to move a 32-bit value into Rd. diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 854b1460dd..317febe923 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -703,11 +703,10 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a goto op_movw_movt; } else if (ARMV7M && strcmp(op_str, "movwt") == 0) { // this is a convenience instruction - // we clear the MSB since it might be set from extracting the small int value mp_uint_t reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); - int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff); + uint32_t i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff); asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVW, reg_dest, i_src & 0xffff); - asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0x7fff); + asm_thumb_mov_reg_i16(emit->as, ASM_THUMB_OP_MOVT, reg_dest, (i_src >> 16) & 0xffff); } else if (ARMV7M && strcmp(op_str, "ldrex") == 0) { mp_uint_t r_dest = get_arg_reg(emit, op_str, pn_args[0], 15); mp_parse_node_t pn_base, pn_offset; diff --git a/tests/inlineasm/asmconst.py b/tests/inlineasm/asmconst.py new file mode 100644 index 0000000000..299a25093c --- /dev/null +++ b/tests/inlineasm/asmconst.py @@ -0,0 +1,8 @@ +# test constants in assembler + +@micropython.asm_thumb +def c1(): + movwt(r0, 0xffffffff) + movwt(r1, 0xf0000000) + sub(r0, r0, r1) +print(hex(c1())) diff --git a/tests/inlineasm/asmconst.py.exp b/tests/inlineasm/asmconst.py.exp new file mode 100644 index 0000000000..3ef9fcabd7 --- /dev/null +++ b/tests/inlineasm/asmconst.py.exp @@ -0,0 +1 @@ +0xfffffff