|
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 or B_CMP_GE |
| 217 | + cmp : 1 # Comparison to perform: BRCOND_LT or BRCOND_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 | if 0 <= reg <= 3:
|
300 | 302 | return ARG(REG, reg, arg)
|
301 | 303 | raise ValueError('arg_qualify: valid registers are r0, r1, r2, r3. Given: %s' % arg)
|
302 |
| - if arg_lower in ['--', 'eq', 'ov', 'lt', 'gt', 'ge']: |
| 304 | + if arg_lower in ['--', 'eq', 'ov', 'lt', 'gt', 'ge', 'le']: |
303 | 305 | return ARG(COND, arg_lower, arg)
|
304 | 306 | try:
|
305 | 307 | return ARG(IMM, int(arg), arg)
|
@@ -338,7 +340,9 @@ def get_rel(arg):
|
338 | 340 | if isinstance(arg, str):
|
339 | 341 | arg = arg_qualify(arg)
|
340 | 342 | if arg.type == IMM:
|
341 |
| - return arg.value |
| 343 | + if arg.value & 3 != 0: # bitwise version of: arg.value % 4 != 0 |
| 344 | + raise ValueError('Relative offset must be a multiple of 4') |
| 345 | + return arg.value >> 2 # bitwise version of: arg.value // 4 |
342 | 346 | if arg.type == SYM:
|
343 | 347 | return symbols.resolve_relative(arg.value)
|
344 | 348 | raise TypeError('wanted: immediate, got: %s' % arg.raw)
|
@@ -634,41 +638,93 @@ def i_jump(target, condition='--'):
|
634 | 638 | raise TypeError('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 = 0 if offset >= 0 else 1 |
| 649 | + _br.sub_opcode = SUB_OPCODE_BR |
| 650 | + _br.opcode = OPCODE_BRANCH |
| 651 | + return _br.all |
| 652 | + |
| 653 | + |
637 | 654 | def i_jumpr(offset, threshold, condition):
|
638 | 655 | offset = get_rel(offset)
|
639 | 656 | threshold = get_imm(threshold)
|
640 | 657 | condition = get_cond(condition)
|
641 | 658 | if condition == 'lt':
|
642 |
| - cmp_op = B_CMP_L |
| 659 | + cmp_op = BRCOND_LT |
643 | 660 | elif condition == 'ge':
|
644 |
| - cmp_op = B_CMP_GE |
| 661 | + cmp_op = BRCOND_GE |
| 662 | + elif condition == 'le': # le == lt(threshold+1) |
| 663 | + threshold += 1 |
| 664 | + cmp_op = BRCOND_LT |
| 665 | + elif condition == 'gt': # gt == ge(threshold+1) |
| 666 | + threshold += 1 |
| 667 | + cmp_op = BRCOND_GE |
| 668 | + elif condition == '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 | raise ValueError("invalid comparison condition")
|
647 |
| - _b.imm = threshold |
648 |
| - _b.cmp = cmp_op |
649 |
| - _b.offset = abs(offset) |
650 |
| - _b.sign = 0 if offset >= 0 else 1 |
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 = 0 if offset >= 0 else 1 |
| 688 | + _bs.sub_opcode = SUB_OPCODE_BS |
| 689 | + _bs.opcode = OPCODE_BRANCH |
| 690 | + return _bs.all |
654 | 691 |
|
655 | 692 |
|
656 | 693 | def i_jumps(offset, threshold, condition):
|
657 | 694 | offset = get_rel(offset)
|
658 | 695 | threshold = get_imm(threshold)
|
659 | 696 | condition = get_cond(condition)
|
660 | 697 | if condition == 'lt':
|
661 |
| - cmp_op = BC_CMP_LT |
662 |
| - elif condition == 'gt': |
663 |
| - cmp_op = BC_CMP_GT |
664 |
| - elif condition == 'eq': |
665 |
| - cmp_op = BC_CMP_EQ |
| 698 | + cmp_op = BRCOND_LT |
| 699 | + elif condition == 'le': |
| 700 | + cmp_op = BRCOND_LE |
| 701 | + elif condition == 'ge': |
| 702 | + cmp_op = BRCOND_GE |
| 703 | + elif condition in ('eq', 'gt'): |
| 704 | + if condition == 'eq': # eq == le but not lt |
| 705 | + skip_cond = BRCOND_LT |
| 706 | + jump_cond = BRCOND_LE |
| 707 | + elif condition == '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 | raise ValueError("invalid comparison condition")
|
668 |
| - _bc.imm = threshold |
669 |
| - _bc.cmp = cmp_op |
670 |
| - _bc.offset = abs(offset) |
671 |
| - _bc.sign = 0 if offset >= 0 else 1 |
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 | +def no_of_instr(opcode, args): |
| 724 | + if opcode == 'jumpr' and get_cond(args[2]) == 'eq': |
| 725 | + return 2 |
| 726 | + |
| 727 | + if opcode == 'jumps' and get_cond(args[2]) in ('eq', 'gt'): |
| 728 | + return 2 |
| 729 | + |
| 730 | + return 1 |
0 commit comments