Skip to content

Commit 180885d

Browse files
committed
add EQ condition for JUMPR and support for opcodes emitting >1 instruction
1 parent b2cdb24 commit 180885d

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

esp32_ulp/assemble.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,22 @@ def assembler_pass(self, lines):
263263
continue
264264
else:
265265
# machine instruction
266-
func = getattr(opcodes, 'i_' + opcode.lower(), None)
266+
opcode_lower = opcode.lower()
267+
func = getattr(opcodes, 'i_' + opcode_lower, None)
267268
if func is not None:
268-
# during the first pass, symbols are not all known yet.
269-
# so some expressions may not evaluate to something (yet).
270-
# instruction building requires sane arguments however.
271-
# since all instructions are 4 bytes long, we simply skip
272-
# building instructions during pass 1, and append an "empty
273-
# instruction" to the section to get the right section size.
274-
instruction = 0 if self.a_pass == 1 else func(*args)
275-
self.append_section(instruction.to_bytes(4, 'little'), TEXT)
269+
if self.a_pass == 1:
270+
# during the first pass, symbols are not all known yet.
271+
# so we add empty instructions to the section, to determine
272+
# section sizes and symbol offsets for pass 2.
273+
result = (0,) * opcodes.no_of_instr(opcode_lower, args)
274+
else:
275+
result = func(*args)
276+
277+
if not isinstance(result, tuple):
278+
result = (result,)
279+
280+
for instruction in result:
281+
self.append_section(instruction.to_bytes(4, 'little'), TEXT)
276282
continue
277283
raise ValueError('Unknown opcode or directive: %s' % opcode)
278284
self.finalize_sections()

esp32_ulp/opcodes.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,19 @@ def i_jump(target, condition='--'):
636636
raise TypeError('unsupported operand: %s' % target.raw)
637637

638638

639+
def _jump_relr(threshold, cond, offset):
640+
"""
641+
Equivalent of I_JUMP_RELR macro in binutils-esp32ulp
642+
"""
643+
_br.imm = threshold
644+
_br.cmp = cond
645+
_br.offset = abs(offset)
646+
_br.sign = 0 if offset >= 0 else 1
647+
_br.sub_opcode = SUB_OPCODE_BR
648+
_br.opcode = OPCODE_BRANCH
649+
return _br.all
650+
651+
639652
def i_jumpr(offset, threshold, condition):
640653
offset = get_rel(offset)
641654
threshold = get_imm(threshold)
@@ -650,15 +663,16 @@ def i_jumpr(offset, threshold, condition):
650663
elif condition == 'gt': # gt == ge(threshold+1)
651664
threshold += 1
652665
cmp_op = BRCOND_GE
666+
elif condition == 'eq': # eq == ge(threshold) but not ge(threshold+1)
667+
# jump over next JUMPR
668+
skip_ins = _jump_relr(threshold + 1, BRCOND_GE, 2)
669+
# jump to target
670+
offset -= 1 # adjust for the additional JUMPR instruction
671+
jump_ins = _jump_relr(threshold, BRCOND_GE, offset)
672+
return (skip_ins, jump_ins)
653673
else:
654674
raise ValueError("invalid comparison condition")
655-
_br.imm = threshold
656-
_br.cmp = cmp_op
657-
_br.offset = abs(offset)
658-
_br.sign = 0 if offset >= 0 else 1
659-
_br.sub_opcode = SUB_OPCODE_BR
660-
_br.opcode = OPCODE_BRANCH
661-
return _br.all
675+
return _jump_relr(threshold, cmp_op, offset)
662676

663677

664678
def i_jumps(offset, threshold, condition):
@@ -680,3 +694,10 @@ def i_jumps(offset, threshold, condition):
680694
_bs.sub_opcode = SUB_OPCODE_BS
681695
_bs.opcode = OPCODE_BRANCH
682696
return _bs.all
697+
698+
699+
def no_of_instr(opcode, args):
700+
if opcode == 'jumpr' and get_cond(args[2]) == 'eq':
701+
return 2
702+
703+
return 1

tests/compat/jumps.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ entry:
1919
jumpr later, 42, le
2020
jumpr entry, 42, gt
2121
jumpr later, 42, gt
22+
jumpr entry, 42, eq
23+
jumpr later, 42, eq
2224

2325
nop
2426
nop

0 commit comments

Comments
 (0)