Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf4b0720

Browse files
Merge pull request#50 from wnienhaus/fix-relative-jumps
Fix relative jumps
2 parents2844227 +c29b7a2 commitf4b0720

File tree

4 files changed

+172
-46
lines changed

4 files changed

+172
-46
lines changed

‎.github/workflows/run_tests.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
-name:Install dependencies
1414
run:|
1515
sudo apt-get update
16-
sudo apt-get install -y git build-essential libffi-dev pkg-config python3 bison flex
16+
sudo apt-get install -y git build-essential libffi-dev pkg-config python3 bison flex xxd
1717
1818
-name:Record version
1919
run:|

‎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
iffuncisnotNone:
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=0ifself.a_pass==1elsefunc(*args)
275-
self.append_section(instruction.to_bytes(4,'little'),TEXT)
269+
ifself.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+
ifnotisinstance(result,tuple):
278+
result= (result,)
279+
280+
forinstructioninresult:
281+
self.append_section(instruction.to_bytes(4,'little'),TEXT)
276282
continue
277283
raiseValueError('Unknown opcode or directive: %s'%opcode)
278284
self.finalize_sections()

‎esp32_ulp/opcodes.py‎

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,19 @@
4747
ALU_SEL_RST=2
4848

4949
OPCODE_BRANCH=8
50+
# https://github.com/espressif/binutils-esp32ulp/blob/d61f86f97eda43fc118df30d019fc062aaa6bc8d/include/opcode/esp32ulp_esp32.h#L85
5051
SUB_OPCODE_BX=0
52+
SUB_OPCODE_BR=1
53+
SUB_OPCODE_BS=2
5154
BX_JUMP_TYPE_DIRECT=0
5255
BX_JUMP_TYPE_ZERO=1
5356
BX_JUMP_TYPE_OVF=2
54-
SUB_OPCODE_B=1
55-
B_CMP_L=0
56-
B_CMP_GE=1
57-
SUB_OPCODE_BC=2
58-
BC_CMP_LT=0
59-
BC_CMP_GT=1
60-
BC_CMP_EQ=2
57+
# https://github.com/espressif/binutils-esp32ulp/blob/d61f86f97eda43fc118df30d019fc062aaa6bc8d/gas/config/tc-esp32ulp.h#L91
58+
BRCOND_LT=0
59+
BRCOND_GE=1
60+
BRCOND_LE=2
61+
BRCOND_EQ=3
62+
BRCOND_GT=4
6163

6264
OPCODE_END=9
6365
SUB_OPCODE_END=0
@@ -210,23 +212,23 @@ def make_ins(layout):
210212
""")
211213

212214

213-
_b=make_ins("""
215+
_br=make_ins("""
214216
imm : 16 # Immediate value to compare against
215-
cmp : 1 # Comparison to perform:B_CMP_L orB_CMP_GE
217+
cmp : 1 # Comparison to perform:BRCOND_LT orBRCOND_GE
216218
offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words
217219
sign : 1 # Sign of target PC offset: 0: positive, 1: negative
218-
sub_opcode : 3 # Sub opcode (SUB_OPCODE_B)
220+
sub_opcode : 3 # Sub opcode (SUB_OPCODE_BR)
219221
opcode : 4 # Opcode (OPCODE_BRANCH)
220222
""")
221223

222224

223-
_bc=make_ins("""
225+
_bs=make_ins("""
224226
imm : 8 # Immediate value to compare against
225227
unused : 7 # Unused
226-
cmp : 2 # Comparison to perform:BC_CMP_LT, GT or EQ
228+
cmp : 2 # Comparison to perform:BRCOND_LT, GT or EQ
227229
offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words
228230
sign : 1 # Sign of target PC offset: 0: positive, 1: negative
229-
sub_opcode : 3 # Sub opcode (SUB_OPCODE_BC)
231+
sub_opcode : 3 # Sub opcode (SUB_OPCODE_BS)
230232
opcode : 4 # Opcode (OPCODE_BRANCH)
231233
""")
232234

@@ -299,7 +301,7 @@ def arg_qualify(arg):
299301
if0<=reg<=3:
300302
returnARG(REG,reg,arg)
301303
raiseValueError('arg_qualify: valid registers are r0, r1, r2, r3. Given: %s'%arg)
302-
ifarg_lowerin ['--','eq','ov','lt','gt','ge']:
304+
ifarg_lowerin ['--','eq','ov','lt','gt','ge','le']:
303305
returnARG(COND,arg_lower,arg)
304306
try:
305307
returnARG(IMM,int(arg),arg)
@@ -338,7 +340,9 @@ def get_rel(arg):
338340
ifisinstance(arg,str):
339341
arg=arg_qualify(arg)
340342
ifarg.type==IMM:
341-
returnarg.value
343+
ifarg.value&3!=0:# bitwise version of: arg.value % 4 != 0
344+
raiseValueError('Relative offset must be a multiple of 4')
345+
returnarg.value>>2# bitwise version of: arg.value // 4
342346
ifarg.type==SYM:
343347
returnsymbols.resolve_relative(arg.value)
344348
raiseTypeError('wanted: immediate, got: %s'%arg.raw)
@@ -634,41 +638,93 @@ def i_jump(target, condition='--'):
634638
raiseTypeError('unsupported operand: %s'%target.raw)
635639

636640

641+
def_jump_relr(threshold,cond,offset):
642+
"""
643+
Equivalent of I_JUMP_RELR macro in binutils-esp32ulp
644+
"""
645+
_br.imm=threshold
646+
_br.cmp=cond
647+
_br.offset=abs(offset)
648+
_br.sign=0ifoffset>=0else1
649+
_br.sub_opcode=SUB_OPCODE_BR
650+
_br.opcode=OPCODE_BRANCH
651+
return_br.all
652+
653+
637654
defi_jumpr(offset,threshold,condition):
638655
offset=get_rel(offset)
639656
threshold=get_imm(threshold)
640657
condition=get_cond(condition)
641658
ifcondition=='lt':
642-
cmp_op=B_CMP_L
659+
cmp_op=BRCOND_LT
643660
elifcondition=='ge':
644-
cmp_op=B_CMP_GE
661+
cmp_op=BRCOND_GE
662+
elifcondition=='le':# le == lt(threshold+1)
663+
threshold+=1
664+
cmp_op=BRCOND_LT
665+
elifcondition=='gt':# gt == ge(threshold+1)
666+
threshold+=1
667+
cmp_op=BRCOND_GE
668+
elifcondition=='eq':# eq == ge(threshold) but not ge(threshold+1)
669+
# jump over next JUMPR
670+
skip_ins=_jump_relr(threshold+1,BRCOND_GE,2)
671+
# jump to target
672+
offset-=1# adjust for the additional JUMPR instruction
673+
jump_ins=_jump_relr(threshold,BRCOND_GE,offset)
674+
return (skip_ins,jump_ins)
645675
else:
646676
raiseValueError("invalid comparison condition")
647-
_b.imm=threshold
648-
_b.cmp=cmp_op
649-
_b.offset=abs(offset)
650-
_b.sign=0ifoffset>=0else1
651-
_b.sub_opcode=SUB_OPCODE_B
652-
_b.opcode=OPCODE_BRANCH
653-
return_b.all
677+
return_jump_relr(threshold,cmp_op,offset)
678+
679+
680+
def_jump_rels(threshold,cond,offset):
681+
"""
682+
Equivalent of I_JUMP_RELS macro in binutils-esp32ulp
683+
"""
684+
_bs.imm=threshold
685+
_bs.cmp=cond
686+
_bs.offset=abs(offset)
687+
_bs.sign=0ifoffset>=0else1
688+
_bs.sub_opcode=SUB_OPCODE_BS
689+
_bs.opcode=OPCODE_BRANCH
690+
return_bs.all
654691

655692

656693
defi_jumps(offset,threshold,condition):
657694
offset=get_rel(offset)
658695
threshold=get_imm(threshold)
659696
condition=get_cond(condition)
660697
ifcondition=='lt':
661-
cmp_op=BC_CMP_LT
662-
elifcondition=='gt':
663-
cmp_op=BC_CMP_GT
664-
elifcondition=='eq':
665-
cmp_op=BC_CMP_EQ
698+
cmp_op=BRCOND_LT
699+
elifcondition=='le':
700+
cmp_op=BRCOND_LE
701+
elifcondition=='ge':
702+
cmp_op=BRCOND_GE
703+
elifconditionin ('eq','gt'):
704+
ifcondition=='eq':# eq == le but not lt
705+
skip_cond=BRCOND_LT
706+
jump_cond=BRCOND_LE
707+
elifcondition=='gt':# gt == ge but not le
708+
skip_cond=BRCOND_LE
709+
jump_cond=BRCOND_GE
710+
711+
# jump over next JUMPS
712+
skip_ins=_jump_rels(threshold,skip_cond,2)
713+
# jump to target
714+
offset-=1# adjust for the additional JUMPS instruction
715+
jump_ins=_jump_rels(threshold,jump_cond,offset)
716+
717+
return (skip_ins,jump_ins)
666718
else:
667719
raiseValueError("invalid comparison condition")
668-
_bc.imm=threshold
669-
_bc.cmp=cmp_op
670-
_bc.offset=abs(offset)
671-
_bc.sign=0ifoffset>=0else1
672-
_bc.sub_opcode=SUB_OPCODE_BC
673-
_bc.opcode=OPCODE_BRANCH
674-
return_bc.all
720+
return_jump_rels(threshold,cmp_op,offset)
721+
722+
723+
defno_of_instr(opcode,args):
724+
ifopcode=='jumpr'andget_cond(args[2])=='eq':
725+
return2
726+
727+
ifopcode=='jumps'andget_cond(args[2])in ('eq','gt'):
728+
return2
729+
730+
return1

‎tests/compat/jumps.S‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.text
2+
.set const,3
3+
.global const# exporting symbol is required for binutils, not important for py-esp32-ulp
4+
5+
entry:
6+
nop
7+
8+
# jumps with labels
9+
jumps entry,42, lt
10+
jumps entry,42, lt
11+
jumps later,42, lt
12+
jumps entry,42, le
13+
jumps later,42, le
14+
jumps entry,42, ge
15+
jumps later,42, ge
16+
jumps entry,42, eq
17+
jumps later,42, eq
18+
jumps entry,42, gt
19+
jumps later,42, gt
20+
21+
# jumps with immediate offset (specified in bytes, but real instruction uses words)
22+
jumps0,42, lt
23+
24+
jumps4,42, lt
25+
jumps8,42, lt
26+
jumps32,42, lt
27+
28+
jumps-4,42, lt
29+
jumps-8,42, lt
30+
jumps-32,42, lt
31+
32+
# jumps with immediate offset from absolute symbol
33+
jumps const,42, lt
34+
35+
# jumpr with labels
36+
jumpr entry,42, lt
37+
jumpr later,42, lt
38+
jumpr entry,42, ge
39+
jumpr later,42, ge
40+
jumpr entry,42, le
41+
jumpr later,42, le
42+
jumpr entry,42, gt
43+
jumpr later,42, gt
44+
jumpr entry,42, eq
45+
jumpr later,42, eq
46+
47+
# jumpr with immediate offset (specified in bytes, but real instruction uses words)
48+
jumpr0,42, lt
49+
50+
jumpr4,42, lt
51+
jumpr8,42, lt
52+
jumpr32,42, lt
53+
54+
jumpr-4,42, lt
55+
jumpr-8,42, lt
56+
jumpr-32,42, lt
57+
58+
# jumps with immediate offset from absolute symbol
59+
jumpr const,42, lt
60+
61+
nop
62+
nop
63+
nop
64+
later:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp