|
47 | 47 | ALU_SEL_RST=2 |
48 | 48 |
|
49 | 49 | OPCODE_BRANCH=8 |
| 50 | +# https://github.com/espressif/binutils-esp32ulp/blob/d61f86f97eda43fc118df30d019fc062aaa6bc8d/include/opcode/esp32ulp_esp32.h#L85 |
50 | 51 | SUB_OPCODE_BX=0 |
| 52 | +SUB_OPCODE_BR=1 |
| 53 | +SUB_OPCODE_BS=2 |
51 | 54 | BX_JUMP_TYPE_DIRECT=0 |
52 | 55 | BX_JUMP_TYPE_ZERO=1 |
53 | 56 | 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 |
61 | 63 |
|
62 | 64 | OPCODE_END=9 |
63 | 65 | SUB_OPCODE_END=0 |
@@ -210,23 +212,23 @@ def make_ins(layout): |
210 | 212 | """) |
211 | 213 |
|
212 | 214 |
|
213 | | -_b=make_ins(""" |
| 215 | +_br=make_ins(""" |
214 | 216 | 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 |
216 | 218 | offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words |
217 | 219 | 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) |
219 | 221 | opcode : 4 # Opcode (OPCODE_BRANCH) |
220 | 222 | """) |
221 | 223 |
|
222 | 224 |
|
223 | | -_bc=make_ins(""" |
| 225 | +_bs=make_ins(""" |
224 | 226 | imm : 8 # Immediate value to compare against |
225 | 227 | 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 |
227 | 229 | offset : 7 # Absolute value of target PC offset w.r.t. current PC, expressed in words |
228 | 230 | 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) |
230 | 232 | opcode : 4 # Opcode (OPCODE_BRANCH) |
231 | 233 | """) |
232 | 234 |
|
@@ -299,7 +301,7 @@ def arg_qualify(arg): |
299 | 301 | if0<=reg<=3: |
300 | 302 | returnARG(REG,reg,arg) |
301 | 303 | 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']: |
303 | 305 | returnARG(COND,arg_lower,arg) |
304 | 306 | try: |
305 | 307 | returnARG(IMM,int(arg),arg) |
@@ -338,7 +340,9 @@ def get_rel(arg): |
338 | 340 | ifisinstance(arg,str): |
339 | 341 | arg=arg_qualify(arg) |
340 | 342 | 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 |
342 | 346 | ifarg.type==SYM: |
343 | 347 | returnsymbols.resolve_relative(arg.value) |
344 | 348 | raiseTypeError('wanted: immediate, got: %s'%arg.raw) |
@@ -634,41 +638,93 @@ def i_jump(target, condition='--'): |
634 | 638 | raiseTypeError('unsupported operand: %s'%target.raw) |
635 | 639 |
|
636 | 640 |
|
| 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 | + |
637 | 654 | defi_jumpr(offset,threshold,condition): |
638 | 655 | offset=get_rel(offset) |
639 | 656 | threshold=get_imm(threshold) |
640 | 657 | condition=get_cond(condition) |
641 | 658 | ifcondition=='lt': |
642 | | -cmp_op=B_CMP_L |
| 659 | +cmp_op=BRCOND_LT |
643 | 660 | 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) |
645 | 675 | else: |
646 | 676 | 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 |
654 | 691 |
|
655 | 692 |
|
656 | 693 | defi_jumps(offset,threshold,condition): |
657 | 694 | offset=get_rel(offset) |
658 | 695 | threshold=get_imm(threshold) |
659 | 696 | condition=get_cond(condition) |
660 | 697 | 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) |
666 | 718 | else: |
667 | 719 | 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 |