Skip to content

Commit 5e8ab92

Browse files
committed
fix dual-instruction jumps with immediate values
This was a previously untested and incorrectly handled case. There was already some offset manipulation to account for the extra instructions for handling non-native conditions. Because of the way symbol offsets are calculated by py-esp32-ulp, namely that extra instructions are already included in the offsets, the relative distance to a forward lying label is 1 instruction too much. Or put another way, when expanding a jump into 2 instructions the "current offset" refers to the first instruction, while it's only the second instruction that jumps to the intended label, so that difference must be accounted for. Thus, for symbols we need to always subtract 1 from the offset. For immediate values, we only subtract 1 for a backward jump.
1 parent 1cb0db3 commit 5e8ab92

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

esp32_ulp/opcodes.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,9 @@ def get_rel(arg):
342342
if arg.type == IMM:
343343
if arg.value & 3 != 0: # bitwise version of: arg.value % 4 != 0
344344
raise ValueError('Relative offset must be a multiple of 4')
345-
return arg.value >> 2 # bitwise version of: arg.value // 4
345+
return IMM, arg.value >> 2 # bitwise version of: arg.value // 4
346346
if arg.type == SYM:
347-
return symbols.resolve_relative(arg.value)
347+
return SYM, symbols.resolve_relative(arg.value)
348348
raise TypeError('wanted: immediate, got: %s' % arg.raw)
349349

350350

@@ -652,7 +652,7 @@ def _jump_relr(threshold, cond, offset):
652652

653653

654654
def i_jumpr(offset, threshold, condition):
655-
offset = get_rel(offset)
655+
offset_type, offset = get_rel(offset)
656656
threshold = get_imm(threshold)
657657
condition = get_cond(condition)
658658
if condition == 'lt':
@@ -669,7 +669,11 @@ def i_jumpr(offset, threshold, condition):
669669
# jump over next JUMPR
670670
skip_ins = _jump_relr(threshold + 1, BRCOND_GE, 2)
671671
# jump to target
672-
offset -= 1 # adjust for the additional JUMPR instruction
672+
if (offset_type == IMM and offset < 0) or offset_type == SYM:
673+
# adjust for the additional JUMPR instruction
674+
# for IMM offsets, the offset is relative to the 2nd instruction, so only backwards jumps need adjusting
675+
# for SYM offsets, label offsets already include the extra instruction, so both directions need adjusting
676+
offset -= 1
673677
jump_ins = _jump_relr(threshold, BRCOND_GE, offset)
674678
return (skip_ins, jump_ins)
675679
else:
@@ -691,7 +695,7 @@ def _jump_rels(threshold, cond, offset):
691695

692696

693697
def i_jumps(offset, threshold, condition):
694-
offset = get_rel(offset)
698+
offset_type, offset = get_rel(offset)
695699
threshold = get_imm(threshold)
696700
condition = get_cond(condition)
697701
if condition == 'lt':
@@ -711,7 +715,11 @@ def i_jumps(offset, threshold, condition):
711715
# jump over next JUMPS
712716
skip_ins = _jump_rels(threshold, skip_cond, 2)
713717
# jump to target
714-
offset -= 1 # adjust for the additional JUMPS instruction
718+
if (offset_type == IMM and offset < 0) or offset_type == SYM:
719+
# adjust for the additional JUMPS instruction
720+
# for IMM offsets, the offset is relative to the 2nd instruction, so only backwards jumps need adjusting
721+
# for SYM offsets, label offsets already include the extra instruction, so both directions need adjusting
722+
offset -= 1
715723
jump_ins = _jump_rels(threshold, jump_cond, offset)
716724

717725
return (skip_ins, jump_ins)

tests/compat/jumps.S

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@ entry:
2626

2727
# jumps with immediate offset (specified in bytes, but real instruction uses words)
2828
jumps 0, 42, lt
29+
jumps 0, 42, eq #dual-instruction condition
2930

3031
jumps 4, 42, lt
32+
jumps 4, 42, eq #dual-instruction condition
3133
jumps 8, 42, lt
3234
jumps 32, 42, lt
3335

3436
jumps -4, 42, lt
37+
jumps -4, 42, eq #dual-instruction condition
3538
jumps -8, 42, lt
3639
jumps -32, 42, lt
3740

@@ -52,12 +55,15 @@ entry:
5255

5356
# jumpr with immediate offset (specified in bytes, but real instruction uses words)
5457
jumpr 0, 42, lt
58+
jumpr 0, 42, eq #dual-instruction condition
5559

5660
jumpr 4, 42, lt
61+
jumpr 4, 42, eq #dual-instruction condition
5762
jumpr 8, 42, lt
5863
jumpr 32, 42, lt
5964

6065
jumpr -4, 42, lt
66+
jumpr -4, 42, eq #dual-instruction condition
6167
jumpr -8, 42, lt
6268
jumpr -32, 42, lt
6369

0 commit comments

Comments
 (0)