Skip to content

Commit

Permalink
py/inlinethumb: Remove 30-bit restriction on movwt instruction.
Browse files Browse the repository at this point in the history
movwt can now move a full 32-bit constant into a register.
  • Loading branch information
dpgeorge committed Jan 7, 2016
1 parent 47dc592 commit ea8be37
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 7 deletions.
7 changes: 3 additions & 4 deletions docs/reference/asm_thumb2_mov.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
5 changes: 2 additions & 3 deletions py/emitinlinethumb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions tests/inlineasm/asmconst.py
Original file line number Diff line number Diff line change
@@ -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()))
1 change: 1 addition & 0 deletions tests/inlineasm/asmconst.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xfffffff

0 comments on commit ea8be37

Please sign in to comment.