Inline assembler data statement: suggested enhancement
The data statement enables data to be included with code. Unfortunately it doesn't seem possible to access it without explicitly manipulating the program counter. Attempts to assign labels to registers produce an error. For example it would be good to be able to write something like this (to access an element from a data array):
d1 = const(12)
d2 = const(13)
@micropython.asm_thumb
def bar(r0):
b(START)
label(MYDATA)
data(4, d1, d2)
label(START)
movwt(r1, MYDATA)
add(r0, r0, r0) # Convert index to byte offset
add(r0, r0, r0)
add(r1, r1, r0) # add offset to data address
ldr(r0, [r1, 0])
But this fails with "unsupported Thumb instruction 'movwt' with 2 arguments". The code can be made to work as follows, but it seems inelegant compared to using a label.
d0 = const(1234567)
d1 = const(987654)
d2 = const(3*d1)
@micropython.asm_thumb
def getdata(r0):
push({pc})
b(START)
data(4, d0, d1, d2)
label(START)
pop({r2})
add(r2, 2) # skip the b() instruction
add(r0, r0, r0)
add(r0, r0, r0) # Convert array offset to bytes
add(r2, r2, r0) # Add to adjusted address
ldr(r0, [r2, 0]) # get the requested data
py/asmthumb: Implement long jumps on Thumb/armv6m architecture.
Summary
Implement long jumps (greater than +/- 2k code distance) for armv6m targets, eg RPI_PICO.
With this change, all tests (except thread tests) now pass on RPI_PICO when using the native emitter:
(plug in RPI_PICO)
$ cd tests
$ ./run-tests.py -t a0 --via-mpy --emit native
Testing
Tested on an RPI_PICO as above. Prior to this PR 8 tests would fail due to large jumps not being implemented. Now they pass.
Trade-offs and Alternatives
All forwards jumps now take 8 or 10 bytes, whereas previously they took only 2 bytes. That's just because it's not possible to know in advance how long the jump is, and the emitter must commit to the size of the instruction in early passes (one day that could be improved by adding more assembler passes).
The jump can now clobber register r1, which it uses as a temporary to calculate the long jump. Clobbering this register is OK, it's anyway used as a temporary in the native emitter and is never needed across jumps (but r0 is because it's used to return a value from the function, so that can't be used here as a temporary).