summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2024-09-09 10:09:15 +1000
committerDamien George <damien@micropython.org>2024-09-19 14:52:58 +1000
commit8b35f2c7fad87198c4ccab243cb3e8a61c7d0f3c (patch)
treeb74d7f3a6dba2353b7039d244d9e59967018440b
parent46d8db81d33e6da383ebf0fd0a063ea1f1948ce1 (diff)
tools/mpy_ld.py: Support jumping more than 2k on armv6m architectures.
Native .mpy files targetting armv6m (eg RP2040) cannot currently have more than about 2kiB of native code (between the start of the file and the init function). This commit fixes that by using bigger jumps to jump to the init function. Signed-off-by: Damien George <damien@micropython.org>
-rwxr-xr-xtools/mpy_ld.py22
1 files changed, 19 insertions, 3 deletions
diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py
index 45aadadd5..c77c46d44 100755
--- a/tools/mpy_ld.py
+++ b/tools/mpy_ld.py
@@ -89,10 +89,26 @@ def asm_jump_x86(entry):
def asm_jump_thumb(entry):
- # Only signed values that fit in 12 bits are supported
+ # This function must return the same number of bytes for the encoding of the jump
+ # regardless of the value of `entry`.
b_off = entry - 4
- assert b_off >> 11 == 0 or b_off >> 11 == -1, b_off
- return struct.pack("<H", 0xE000 | (b_off >> 1 & 0x07FF))
+ if b_off >> 11 == 0 or b_off >> 11 == -1:
+ # Signed value fits in 12 bits.
+ b0 = 0xE000 | (b_off >> 1 & 0x07FF)
+ b1 = 0
+ b2 = 0
+ b3 = 0
+ else:
+ # Use bl to do a large jump/call:
+ # push {r0, lr}
+ # bl <dest>
+ # pop {r0, pc}
+ b_off -= 2 # skip "push {r0, lr}"
+ b0 = 0xB400 | 0x0100 | 0x0001 # push, lr, r0
+ b1 = 0xF000 | (((b_off) >> 12) & 0x07FF)
+ b2 = 0xF800 | (((b_off) >> 1) & 0x07FF)
+ b3 = 0xBC00 | 0x0100 | 0x0001 # pop, pc, r0
+ return struct.pack("<HHHH", b0, b1, b2, b3)
def asm_jump_thumb2(entry):