eBPF atomic operations supported are: ADD, OR, AND, XOR, CHG, CMP (compare and exchange). To keep backward compatibility, atomic operations uses the same op-mode that exchange and add operation.
Atomic instructions use f-imm32 to represent the opcode as an extra encoding, a new f-op-atomic operand field was declared with its offset member in zero and length in 32 bits allowing be used by CGEN as a constant value computing in a right way the mask/value along with the class, size and mode field operands, f-op-atomic contains the atomic operation and it's endianness dependent: 63 39 32 31 7 0 +---------------+-----+--------------+-----+ | | | | | +---------------+-----+--------------+-----+ | | | +--> OP_MODE_ATOMIC | | OP_CLASS_STX | | OP_SIZE_{DW | W} +---> OP_ATOMIC_XX{ADD,OR,AND, ..} Atomic instructions has the BPF_FETCH bit set, allowing be fully compliant with gcc __atomic built-in functions. Regression tests to the following targets were done: bpf arm-linuxeabi arm-nacl arm-netbsdelf arm-nto arm-pe arm-symbianelf arm-vxworks arm-wince-pe aarch64-linux alpha-dec-vms alpha-linux alpha-linuxecoff alpha-netbsd alpha-unknown-freebsd4.7 am33_2.0-linux arc-linux-uclibc avr-elf bfin-elf cr16-elf cris-elf crisv32-linux crx-elf d10v-elf d30v-elf dlx-elf epiphany-elf fr30-elf frv-elf frv-linux ft32-elf h8300-elf hppa-linux hppa-hp-hpux10 hppa64-hp-hpux11.23 hppa64-linux mips-linux mips-vxworks mips64-linux mipsel-linux-gnu mipsisa32el-linux mips64-openbsd mipstx39-elf ia64-elf ia64-freebsd5 ia64-hpux ia64-linux ia64-netbsd ia64-vms ip2k-elf iq2000-elf lm32-elf m32c-elf m32r-elf m68hc11-elf m68hc12-elf m68k-elf m68k-linux m68k-netbsd mcore-elf mcore-pe mep-elf metag-linux microblaze-elf mmix mn10200-elf mn10300-elf moxie-elf ms1-elf msp430-elf mt-elf nds32le-elf nios2-linux or1k-elf pdp11-dec-aout pj-elf powerpc-eabisim powerpc-eabivle powerpc-linux powerpc-nto powerpc-wrs-vxworks powerpc64-linux powerpcle-cygwin powerpcle-elf powerpc64le-linux ppc-lynxos pru-elf riscv32-elf riscv64-elf rl78-elf rs6000-aix4.3.3 rs6000-aix5.1 rx-elf s390-linux s390x-linux score-elf sh-linux sh-nto sh-pe sh-rtems sh-vxworks shl-unknown-netbsdelf sparc-aout sparc-linux sparc-vxworks sparc64-linux sparc-sun-solaris2.12 spu-elf tic30-unknown-aout tic30-unknown-coff tic4x-coff tic54x-coff tic6x-elf tilegx-linux tilepro-linux v850-elf vax-netbsdelf visium-elf i386-darwin i386-lynxos i586-linux i686-nacl i686-pc-beos i686-pc-elf i686-pe i686-vxworks x86_64-linux x86_64-w64-mingw32 x86_64-nacl xgate-elf xstormy16-elf xtensa-elf z8k-coff z80-coff. This patch relies on the functionality implemented in CGEN patch: 'Compute correct mask and values when offset in define-ifield is not 0.' If an instruction field is defined in a long form, assigning an offset different to 0 the mask and constant values are not computed appropriately. https://sourceware.org/pipermail/cgen/2021q3.txt cpu/ * bpf.cpu (f-op-atomic): Define field for eBPF atomic (extra) opcodes. (h-r0): Used by sim in compare and exchange eBPF atomic operation (insn-atomic-op-XX): eBPF opcodes in BE and LE. (insn-op-mode): Update code field (mode sub-field) to ATOMIC. (define-callc-call-insn): Add a 'callc' instruction, CGEN now is taking (f-regs) in the right place/value when mask/value is computed. (dais): Add p-macro to expand eBPF atomics definitions. gas/ * testsuite/gas/bpf/atomic-be.d: Adding eBPF atomic instructions. * testsuite/gas/bpf/atomic.d: Likewise. * testsuite/gas/bpf/atomic.s: Likewise. include/ * opcode/cgen.h: Replace data from CGEN_INSN_INT by CGEN_INSN_LGUINT. opcodes/ * cgen-dis.in: Replace data from CGEN_INSN_INT by CGEN_INSN_LGUINT. * cgen-opc.c: Likewise. * bpf-desc.c: Regenerate. * bpf-desc.h: Likewise. * bpf-opc.c: Likewise. * bpf-opc.h: Likewise. * bpf-dis.c: Likewise. --- cpu/ChangeLog | 10 ++ cpu/bpf.cpu | 172 +++++++++++++++++++------ gas/ChangeLog | 6 + gas/testsuite/gas/bpf/atomic-be.d | 14 ++- gas/testsuite/gas/bpf/atomic.d | 14 ++- gas/testsuite/gas/bpf/atomic.s | 11 +- include/ChangeLog | 4 + include/opcode/cgen.h | 12 +- opcodes/bpf-desc.c | 112 +++++++++++++++++ opcodes/bpf-desc.h | 26 ++-- opcodes/bpf-dis.c | 2 +- opcodes/bpf-opc.c | 202 +++++++++++++++++++++++++----- opcodes/bpf-opc.h | 14 ++- opcodes/cgen-dis.c | 6 +- opcodes/cgen-dis.in | 2 +- opcodes/cgen-opc.c | 8 +- 16 files changed, 513 insertions(+), 102 deletions(-) diff --git a/cpu/ChangeLog b/cpu/ChangeLog index 2739df0edd..20bee25777 100644 --- a/cpu/ChangeLog +++ b/cpu/ChangeLog @@ -1,3 +1,13 @@ +2021-08-27 Guillermo E. Martinez <guillermo.e.marti...@oracle.com> + + * bpf.cpu (f-op-atomic): Define field for eBPF atomic (extra) opcodes. + (h-r0): Used by sim in compare and exchange eBPF atomic operation + (insn-atomic-op-XX): eBPF opcodes in BE and LE. + (insn-op-mode): Update code field (mode sub-field) to ATOMIC. + (define-callc-call-insn): Add a 'callc' instruction, CGEN now is + taking (f-regs) in the right place/value when mask/value is computed. + (dais): Add p-macro to expand eBPF atomics definitions. + 2021-05-06 Stafford Horne <sho...@gmail.com> PR 21464 diff --git a/cpu/bpf.cpu b/cpu/bpf.cpu index 13dde7094c..75681dd285 100644 --- a/cpu/bpf.cpu +++ b/cpu/bpf.cpu @@ -206,7 +206,19 @@ (type pc UDI) (get () (raw-reg h-pc)) (set (newval) (set (raw-reg h-pc) newval))) - + +;; r0 register is used by compare and exchange atomic operation +;; used in addressing by offset mode, so they compare/xchange +;; values in memory with r0. + +(define-hardware + (name h-r0) + (comment "r0 register") + (attrs all-isas) + (type register DI) + (get () (raw-reg h-r0)) + (set (newval) (set (raw-reg h-r0) newval))) + ;; A 64-bit h-sint to be used by the imm64 operand below. XXX this ;; shouldn't be needed, as h-sint is supposed to be able to hold ;; 64-bit values. However, in practice CGEN limits h-sint to 32 bits @@ -274,11 +286,48 @@ (dwf f-op-mode "eBPF opcode mode" (all-isas) 0 8 7 3 UINT) (dwf f-op-size "eBPF opcode size" (all-isas) 0 8 4 2 UINT) +;; Atomic instructions use f-imm32 to represent the opcode as +;; an extra encoding. These new instruction are characterized +;; by a new opcode (first 8 bits) plus an atomic operation +;; specified as a number stored in the imm32 instruction +;; operand, this means that atomic instructions are using +;; f-imm32 that shouldn't contain an opcode. +;; +;; 63 39 32 31 7 0 +;; +---------------+-----+--------------+-----+ +;; | | | | | +;; +---------------+-----+--------------+-----+ +;; | | +;; | +--> OP_MODE_ATOMIC | +;; | OP_CLASS_STX | +;; | OP_SIZE_{DW | W} +;; +---> OP_ATOMIC_XX{ADD,OR,AND, ..} + +(dwf f-op-atomic "eBPF atomic insn opcode" (all-isas) 32 64 31 32 UINT) + +(define-normal-insn-enum insn-atomic-op-le "eBPF atomic insn" + ((ISA ebpfle xbpfle)) OP_ATOMIC_LE_ f-op-atomic + ((ADD #x01) + (OR #x41) + (AND #x51) + (XOR #xa1) + (CHG #xe1) + (CMP #xf1))) + +(define-normal-insn-enum insn-atomic-op-be "eBPF atomic insn" + ((ISA ebpfbe xbpfbe)) OP_ATOMIC_BE_ f-op-atomic + ((ADD #x01000000) + (OR #x41000000) + (AND #x51000000) + (XOR #xa1000000) + (CHG #xe1000000) + (CMP #xf1000000))) + (define-normal-insn-enum insn-op-mode "eBPF load/store instruction modes" (all-isas) OP_MODE_ f-op-mode ((IMM #b000) (ABS #b001) (IND #b010) (MEM #b011) ;; #b100 and #b101 are used in classic BPF only, reserved in eBPF. - (XADD #b110))) + (ATOMIC #b110))) (define-normal-insn-enum insn-op-size "eBPF load/store instruction sizes" (all-isas) OP_SIZE_ f-op-size @@ -758,24 +807,42 @@ (define-condjump-insns le) (define-condjump-insns be) -;; The `call' instruction doesn't make use of registers, but the -;; semantic routine should have access to the src register in order to -;; properly interpret the meaning of disp32. Therefore we need one -;; version per ISA. +(define-pmacro (define-callc-call-insn x-endian) + (begin -(define-pmacro (define-call-insn x-endian) - (dni (.sym call x-endian) - "call" - (endian-isas x-endian) - "call $disp32" - (+ disp32 (f-offset16 0) (f-regs 0) - OP_CLASS_JMP OP_SRC_K OP_CODE_CALL) - (c-call VOID - "bpfbf_call" disp32 (ifield (.sym f-src x-endian))) - ())) + ;; The `callc' instruction doesn't make use of registers, but the + ;; semantic routine should have access to the src register in order to + ;; properly interpret the meaning of disp32. Therefore we need one + ;; version per ISA. It expects as argument a constant value representing + ;; the offset of the instruction to be fetched relative to `pc'. + + (dni (.sym callc x-endian) + "callc" + (endian-isas x-endian) + "call $disp32" + (+ disp32 (f-offset16 0) (f-regs 0) + OP_CLASS_JMP OP_SRC_K OP_CODE_CALL) + (c-call VOID + "bpfbf_call" disp32 (ifield (.sym f-src x-endian))) + ()) + + ;; The `call' instruction use a disp32 operator fetch an instruction + ;; from a signed offset value relative to `pc'(symbols), this is known + ;; as internal calls (BPF_PSEUDO_CALL), it's indicated by a constant + ;; value: 0x1, in f-src-xendian. + + (dni (.sym call x-endian) + "call" + (endian-isas x-endian) + "call $disp32" + (+ disp32 (f-offset16 0) (.if (.eq x-endian le) (f-regs #x10) (f-regs #x01)) + OP_CLASS_JMP OP_SRC_K OP_CODE_CALL) + (c-call VOID + "bpfbf_call" disp32 (ifield (.sym f-src x-endian))) + ()))) -(define-call-insn le) -(define-call-insn be) +(define-callc-call-insn le) +(define-callc-call-insn be) (define-pmacro (define-callr-insn x-endian) (dni (.sym callr x-endian) @@ -810,35 +877,60 @@ ;;; Atomic instructions -;; The atomic exchange-and-add instructions come in two flavors: one +;; The atomic exchange-and-op instructions come in two flavors: one ;; for swapping 64-bit quantities and another for 32-bit quantities. -(define-pmacro (sem-exchange-and-add x-endian x-mode) +(define-pmacro (sem-exchange-and-op x-semop x-endian x-mode) + (sequence VOID ((x-mode tmp)) + (set x-mode tmp (mem x-mode (add DI (.sym dst x-endian) offset16))) + (set x-mode tmp + (x-semop x-mode tmp (.sym src x-endian))))) + +(define-pmacro (sem-exchange x-semop x-endian x-mode) + (sequence VOID ((x-mode tmp) (x-mode sreg)) + (set x-mode tmp (mem x-mode (add DI (.sym dst x-endian) offset16))) + (set x-mode sreg (.sym src x-endian)) + (set x-mode (.sym src x-endian) tmp) + (set x-mode tmp sreg))) + +(define-pmacro (sem-cmp-exchange x-semop x-endian x-mode) (sequence VOID ((x-mode tmp)) - ;; XXX acquire lock in simulator... as a hardware element? (set x-mode tmp (mem x-mode (add DI (.sym dst x-endian) offset16))) - (set x-mode - (mem x-mode (add DI (.sym dst x-endian) offset16)) - (add x-mode tmp (.sym src x-endian))))) + (if (eq x-mode (reg h-r0) tmp) + (set x-mode tmp (.sym src x-endian)) + (set x-mode tmp tmp)))) + +(define-pmacro (dai x-basename x-suffix x-size x-op-code x-endian x-mode proc) + (begin + (dni (.str "x" x-basename x-suffix x-endian) + (.str "x" x-basename x-suffix x-endian) + (endian-isas x-endian) + (.str "x" x-basename x-suffix " [$dst" x-endian "+$offset16],$src" x-endian) + (+ (.sym src x-endian) (.sym dst x-endian) + offset16 OP_MODE_ATOMIC x-size OP_CLASS_STX x-op-code) + (proc x-basename x-endian x-mode) + ()))) + +(define-pmacro (dais x-basename x-op-code x-endian semproc) + (begin + (dai x-basename "dw" OP_SIZE_DW x-op-code x-endian DI semproc) + (dai x-basename "w" OP_SIZE_W x-op-code x-endian SI semproc))) (define-pmacro (define-atomic-insns x-endian) (begin - (dni (.str "xadddw" x-endian) - "xadddw" - (endian-isas x-endian) - (.str "xadddw [$dst" x-endian "+$offset16],$src" x-endian) - (+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian) - offset16 OP_MODE_XADD OP_SIZE_DW OP_CLASS_STX) - (sem-exchange-and-add x-endian DI) - ()) - (dni (.str "xaddw" x-endian) - "xaddw" - (endian-isas x-endian) - (.str "xaddw [$dst" x-endian "+$offset16],$src" x-endian) - (+ (f-imm32 0) (.sym src x-endian) (.sym dst x-endian) - offset16 OP_MODE_XADD OP_SIZE_W OP_CLASS_STX) - (sem-exchange-and-add x-endian SI) - ()))) + (dais add (.if (.eq x-endian le) OP_ATOMIC_LE_ADD OP_ATOMIC_BE_ADD) + x-endian sem-exchange-and-op) + (dais or (.if (.eq x-endian le) OP_ATOMIC_LE_OR OP_ATOMIC_BE_OR) + x-endian sem-exchange-and-op) + (dais and (.if (.eq x-endian le) OP_ATOMIC_LE_AND OP_ATOMIC_BE_AND) + x-endian sem-exchange-and-op) + (dais xor (.if (.eq x-endian le) OP_ATOMIC_LE_XOR OP_ATOMIC_BE_XOR) + x-endian sem-exchange-and-op) + (dais chg (.if (.eq x-endian le) OP_ATOMIC_LE_CHG OP_ATOMIC_BE_CHG) + x-endian sem-exchange) + (dais cmp (.if (.eq x-endian le) OP_ATOMIC_LE_CMP OP_ATOMIC_BE_CMP) + x-endian sem-cmp-exchange) + )) (define-atomic-insns le) (define-atomic-insns be) diff --git a/gas/ChangeLog b/gas/ChangeLog index 6bcb035621..4c0972a585 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2021-08-27 Guillermo E. Martinez <guillermo.e.marti...@oracle.com> + + * testsuite/gas/bpf/atomic-be.d: Adding eBPF atomic instructions. + * testsuite/gas/bpf/atomic.d: Likewise. + * testsuite/gas/bpf/atomic.s: Likewise. + 2021-06-11 H.J. Lu <hongjiu...@intel.com> * config/tc-i386.c (x86_cons): Handle GOT/PLT relocations only diff --git a/gas/testsuite/gas/bpf/atomic-be.d b/gas/testsuite/gas/bpf/atomic-be.d index 04161e08ac..c8806ee3f2 100644 --- a/gas/testsuite/gas/bpf/atomic-be.d +++ b/gas/testsuite/gas/bpf/atomic-be.d @@ -8,5 +8,15 @@ Disassembly of section .text: 0+ <.text>: - 0: db 12 1e ef 00 00 00 00 xadddw \[%r1\+0x1eef\],%r2 - 8: c3 12 1e ef 00 00 00 00 xaddw \[%r1\+0x1eef\],%r2 + 0: db 12 1e ef 00 00 00 01 xadddw \[%r1\+0x1eef\],%r2 + 8: c3 12 1e ef 00 00 00 01 xaddw \[%r1\+0x1eef\],%r2 + 10: db 12 1e ef 00 00 00 41 xordw \[%r1\+0x1eef\],%r2 + 18: c3 12 1e ef 00 00 00 41 xorw \[%r1\+0x1eef\],%r2 + 20: db 12 1e ef 00 00 00 51 xanddw \[%r1\+0x1eef\],%r2 + 28: c3 12 1e ef 00 00 00 51 xandw \[%r1\+0x1eef\],%r2 + 30: db 12 1e ef 00 00 00 a1 xxordw \[%r1\+0x1eef\],%r2 + 38: c3 12 1e ef 00 00 00 a1 xxorw \[%r1\+0x1eef\],%r2 + 40: db 12 1e ef 00 00 00 e1 xchgdw \[%r1\+0x1eef\],%r2 + 48: c3 12 1e ef 00 00 00 e1 xchgw \[%r1\+0x1eef\],%r2 + 50: db 12 1e ef 00 00 00 f1 xcmpdw \[%r1\+0x1eef\],%r2 + 58: c3 12 1e ef 00 00 00 f1 xcmpw \[%r1\+0x1eef\],%r2 diff --git a/gas/testsuite/gas/bpf/atomic.d b/gas/testsuite/gas/bpf/atomic.d index 1c83cb582a..d7be14908d 100644 --- a/gas/testsuite/gas/bpf/atomic.d +++ b/gas/testsuite/gas/bpf/atomic.d @@ -7,5 +7,15 @@ Disassembly of section .text: 0+ <.text>: - 0: db 21 ef 1e 00 00 00 00 xadddw \[%r1\+0x1eef\],%r2 - 8: c3 21 ef 1e 00 00 00 00 xaddw \[%r1\+0x1eef\],%r2 + 0: db 21 ef 1e 01 00 00 00 xadddw \[%r1\+0x1eef\],%r2 + 8: c3 21 ef 1e 01 00 00 00 xaddw \[%r1\+0x1eef\],%r2 + 10: db 21 ef 1e 41 00 00 00 xordw \[%r1\+0x1eef\],%r2 + 18: c3 21 ef 1e 41 00 00 00 xorw \[%r1\+0x1eef\],%r2 + 20: db 21 ef 1e 51 00 00 00 xanddw \[%r1\+0x1eef\],%r2 + 28: c3 21 ef 1e 51 00 00 00 xandw \[%r1\+0x1eef\],%r2 + 30: db 21 ef 1e a1 00 00 00 xxordw \[%r1\+0x1eef\],%r2 + 38: c3 21 ef 1e a1 00 00 00 xxorw \[%r1\+0x1eef\],%r2 + 40: db 21 ef 1e e1 00 00 00 xchgdw \[%r1\+0x1eef\],%r2 + 48: c3 21 ef 1e e1 00 00 00 xchgw \[%r1\+0x1eef\],%r2 + 50: db 21 ef 1e f1 00 00 00 xcmpdw \[%r1\+0x1eef\],%r2 + 58: c3 21 ef 1e f1 00 00 00 xcmpw \[%r1\+0x1eef\],%r2 diff --git a/gas/testsuite/gas/bpf/atomic.s b/gas/testsuite/gas/bpf/atomic.s index 0119b24c8b..4c26c46037 100644 --- a/gas/testsuite/gas/bpf/atomic.s +++ b/gas/testsuite/gas/bpf/atomic.s @@ -2,4 +2,13 @@ .text xadddw [%r1+0x1eef], %r2 xaddw [%r1+0x1eef], %r2 - + xordw [%r1+0x1eef], %r2 + xorw [%r1+0x1eef], %r2 + xanddw [%r1+0x1eef], %r2 + xandw [%r1+0x1eef], %r2 + xxordw [%r1+0x1eef], %r2 + xxorw [%r1+0x1eef], %r2 + xchgdw [%r1+0x1eef], %r2 + xchgw [%r1+0x1eef], %r2 + xcmpdw [%r1+0x1eef], %r2 + xcmpw [%r1+0x1eef], %r2 diff --git a/include/ChangeLog b/include/ChangeLog index 27c5e29449..e0ccf4fbaa 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2021-08-27 Guillermo E. Martinez <guillermo.e.marti...@oracle.com> + + * opcode/cgen.h: Replace data type CGEN_INSN_INT by CGEN_INSN_LGUINT. + 2021-06-02 Shahab Vahedi <sha...@synopsys.com> * dis-asm.h (disassembler_options_arc): New prototype. diff --git a/include/opcode/cgen.h b/include/opcode/cgen.h index 8b7d2a4b54..cb0e10f446 100644 --- a/include/opcode/cgen.h +++ b/include/opcode/cgen.h @@ -914,7 +914,7 @@ typedef struct Each insn's value is stored with the insn. The first step in recognizing an insn for disassembly is (opcode & mask) == value. */ - CGEN_INSN_INT mask; + CGEN_INSN_LGUINT mask; #define CGEN_IFMT_MASK(ifmt) ((ifmt)->mask) /* Instruction fields. @@ -928,7 +928,7 @@ typedef struct typedef struct { /* The opcode portion of the base insn. */ - CGEN_INSN_INT base_value; + CGEN_INSN_LGUINT base_value; #ifdef CGEN_MAX_EXTRA_OPCODE_OPERANDS /* Extra opcode values beyond base_value. */ @@ -1186,7 +1186,7 @@ extern CGEN_INSN_LIST * cgen_asm_lookup_insn instruction (the actually hashing done is up to the target). */ extern CGEN_INSN_LIST * cgen_dis_lookup_insn - (CGEN_CPU_DESC, const char *, CGEN_INSN_INT); + (CGEN_CPU_DESC, const char *, CGEN_INSN_LGUINT); /* FIXME: delete these two */ #define CGEN_DIS_LOOKUP_INSN(cd, buf, value) cgen_dis_lookup_insn ((cd), (buf), (value)) #define CGEN_DIS_NEXT_INSN(insn) ((insn)->next) @@ -1449,7 +1449,7 @@ extern int CGEN_SYM (get_mach) (const char *); /* Operand index computation. */ extern const CGEN_INSN * cgen_lookup_insn (CGEN_CPU_DESC, const CGEN_INSN * insn_, - CGEN_INSN_INT int_value_, unsigned char *bytes_value_, + CGEN_INSN_LGUINT int_value_, unsigned char *bytes_value_, int length_, CGEN_FIELDS *fields_, int alias_p_); extern void cgen_get_insn_operands (CGEN_CPU_DESC, const CGEN_INSN * insn_, @@ -1461,10 +1461,10 @@ extern const CGEN_INSN * cgen_lookup_get_insn_operands /* Cover fns to bfd_get/set. */ -extern CGEN_INSN_INT cgen_get_insn_value +extern CGEN_INSN_LGUINT cgen_get_insn_value (CGEN_CPU_DESC, unsigned char *, int, int); extern void cgen_put_insn_value - (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT, int); + (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_LGUINT, int); extern CGEN_INSN_INT cgen_get_base_insn_value (CGEN_CPU_DESC, unsigned char *, int); diff --git a/opcodes/bpf-desc.c b/opcodes/bpf-desc.c index 35c6dcd9f2..0ee8edd5be 100644 --- a/opcodes/bpf-desc.c +++ b/opcodes/bpf-desc.c @@ -176,6 +176,7 @@ const CGEN_HW_ENTRY bpf_cgen_hw_table[] = { "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { "h-gpr", HW_H_GPR, CGEN_ASM_KEYWORD, (PTR) & bpf_cgen_opval_h_gpr, { 0, { { { (1<<MACH_BPF)|(1<<MACH_XBPF), 0 } }, { { 1, "\xf0" } } } } }, { "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, + { "h-r0", HW_H_R0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { "h-sint64", HW_H_SINT64, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { 0, 0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x80" } } } } } }; @@ -196,6 +197,7 @@ const CGEN_IFLD bpf_cgen_ifld_table[] = { BPF_F_OP_CLASS, "f-op-class", 0, 8, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { BPF_F_OP_MODE, "f-op-mode", 0, 8, 7, 3, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { BPF_F_OP_SIZE, "f-op-size", 0, 8, 4, 2, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, + { BPF_F_OP_ATOMIC, "f-op-atomic", 32, 64, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } }, { BPF_F_DSTLE, "f-dstle", 8, 8, 3, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } }, { BPF_F_SRCLE, "f-srcle", 8, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } }, { BPF_F_DSTBE, "f-dstbe", 8, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } }, @@ -1530,11 +1532,21 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] = BPF_INSN_JSLE32RBE, "jsle32rbe", "jsle32", 64, { 0|A(COND_CTI), { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } }, +/* call $disp32 */ + { + BPF_INSN_CALLCLE, "callcle", "call", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, /* call $disp32 */ { BPF_INSN_CALLLE, "callle", "call", 64, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } }, +/* call $disp32 */ + { + BPF_INSN_CALLCBE, "callcbe", "call", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, /* call $disp32 */ { BPF_INSN_CALLBE, "callbe", "call", 64, @@ -1570,6 +1582,56 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] = BPF_INSN_XADDWLE, "xaddwle", "xaddw", 64, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } }, +/* xordw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XORDWLE, "xordwle", "xordw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xorw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XORWLE, "xorwle", "xorw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xanddw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XANDDWLE, "xanddwle", "xanddw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xandw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XANDWLE, "xandwle", "xandw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xxordw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XXORDWLE, "xxordwle", "xxordw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xxorw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XXORWLE, "xxorwle", "xxorw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xchgdw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XCHGDWLE, "xchgdwle", "xchgdw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xchgw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XCHGWLE, "xchgwle", "xchgw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xcmpdw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XCMPDWLE, "xcmpdwle", "xcmpdw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, +/* xcmpw [$dstle+$offset16],$srcle */ + { + BPF_INSN_XCMPWLE, "xcmpwle", "xcmpw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } } + }, /* xadddw [$dstbe+$offset16],$srcbe */ { BPF_INSN_XADDDWBE, "xadddwbe", "xadddw", 64, @@ -1580,6 +1642,56 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] = BPF_INSN_XADDWBE, "xaddwbe", "xaddw", 64, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } }, +/* xordw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XORDWBE, "xordwbe", "xordw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xorw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XORWBE, "xorwbe", "xorw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xanddw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XANDDWBE, "xanddwbe", "xanddw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xandw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XANDWBE, "xandwbe", "xandw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xxordw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XXORDWBE, "xxordwbe", "xxordw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xxorw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XXORWBE, "xxorwbe", "xxorw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xchgdw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XCHGDWBE, "xchgdwbe", "xchgdw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xchgw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XCHGWBE, "xchgwbe", "xchgw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xcmpdw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XCMPDWBE, "xcmpdwbe", "xcmpdw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, +/* xcmpw [$dstbe+$offset16],$srcbe */ + { + BPF_INSN_XCMPWBE, "xcmpwbe", "xcmpw", 64, + { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } } + }, /* brkpt */ { BPF_INSN_BRKPT, "brkpt", "brkpt", 64, diff --git a/opcodes/bpf-desc.h b/opcodes/bpf-desc.h index 1e3bebbda5..90f35b1f18 100644 --- a/opcodes/bpf-desc.h +++ b/opcodes/bpf-desc.h @@ -85,10 +85,22 @@ typedef enum insn_op_class { , OP_CLASS_ALU, OP_CLASS_JMP, OP_CLASS_JMP32, OP_CLASS_ALU64 } INSN_OP_CLASS; +/* Enum declaration for eBPF atomic insn. */ +typedef enum insn_atomic_op_le { + OP_ATOMIC_LE_ADD = 1, OP_ATOMIC_LE_OR = 65, OP_ATOMIC_LE_AND = 81, OP_ATOMIC_LE_XOR = 161 + , OP_ATOMIC_LE_CHG = 225, OP_ATOMIC_LE_CMP = 241 +} INSN_ATOMIC_OP_LE; + +/* Enum declaration for eBPF atomic insn. */ +typedef enum insn_atomic_op_be { + OP_ATOMIC_BE_ADD = 16777216, OP_ATOMIC_BE_OR = 1090519040, OP_ATOMIC_BE_AND = 1358954496, OP_ATOMIC_BE_XOR = 0xa1000000 + , OP_ATOMIC_BE_CHG = 0xe1000000, OP_ATOMIC_BE_CMP = 0xf1000000 +} INSN_ATOMIC_OP_BE; + /* Enum declaration for eBPF load/store instruction modes. */ typedef enum insn_op_mode { OP_MODE_IMM = 0, OP_MODE_ABS = 1, OP_MODE_IND = 2, OP_MODE_MEM = 3 - , OP_MODE_XADD = 6 + , OP_MODE_ATOMIC = 6 } INSN_OP_MODE; /* Enum declaration for eBPF load/store instruction sizes. */ @@ -140,10 +152,10 @@ typedef enum cgen_ifld_attr { /* Enum declaration for bpf ifield types. */ typedef enum ifield_type { BPF_F_NIL, BPF_F_ANYOF, BPF_F_OP_CODE, BPF_F_OP_SRC - , BPF_F_OP_CLASS, BPF_F_OP_MODE, BPF_F_OP_SIZE, BPF_F_DSTLE - , BPF_F_SRCLE, BPF_F_DSTBE, BPF_F_SRCBE, BPF_F_REGS - , BPF_F_OFFSET16, BPF_F_IMM32, BPF_F_IMM64_A, BPF_F_IMM64_B - , BPF_F_IMM64_C, BPF_F_IMM64, BPF_F_MAX + , BPF_F_OP_CLASS, BPF_F_OP_MODE, BPF_F_OP_SIZE, BPF_F_OP_ATOMIC + , BPF_F_DSTLE, BPF_F_SRCLE, BPF_F_DSTBE, BPF_F_SRCBE + , BPF_F_REGS, BPF_F_OFFSET16, BPF_F_IMM32, BPF_F_IMM64_A + , BPF_F_IMM64_B, BPF_F_IMM64_C, BPF_F_IMM64, BPF_F_MAX } IFIELD_TYPE; #define MAX_IFLD ((int) BPF_F_MAX) @@ -171,8 +183,8 @@ typedef enum cgen_hw_attr { /* Enum declaration for bpf hardware types. */ typedef enum cgen_hw_type { HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR - , HW_H_IADDR, HW_H_GPR, HW_H_PC, HW_H_SINT64 - , HW_MAX + , HW_H_IADDR, HW_H_GPR, HW_H_PC, HW_H_R0 + , HW_H_SINT64, HW_MAX } CGEN_HW_TYPE; #define MAX_HW ((int) HW_MAX) diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c index 8c460c729b..26a9bc8f39 100644 --- a/opcodes/bpf-dis.c +++ b/opcodes/bpf-dis.c @@ -367,7 +367,7 @@ print_insn (CGEN_CPU_DESC cd, bfd_byte *buf, unsigned int buflen) { - CGEN_INSN_INT insn_value; + CGEN_INSN_LGUINT insn_value; const CGEN_INSN_LIST *insn_list; CGEN_EXTRACT_INFO ex_info; int basesize; diff --git a/opcodes/bpf-opc.c b/opcodes/bpf-opc.c index b8b76ee899..633c5de7c6 100644 --- a/opcodes/bpf-opc.c +++ b/opcodes/bpf-opc.c @@ -50,99 +50,107 @@ static const CGEN_IFMT ifmt_empty ATTRIBUTE_UNUSED = { }; static const CGEN_IFMT ifmt_addile ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_addrle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffffffff00ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_negle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfffffffffffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_addibe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_addrbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffffffff00ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_negbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffffffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_endlele ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_endlebe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_lddwle ATTRIBUTE_UNUSED = { - 64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 128, 0xfffff0ff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_lddwbe ATTRIBUTE_UNUSED = { - 64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 128, 0xffff0fff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ldabsw ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ldindwle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ldindwbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ldxwle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ldxwbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_stble ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xf0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_stbbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_jeqile ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xf0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_jeqrle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_jeqibe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xfff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_jeqrbe ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; -static const CGEN_IFMT ifmt_callle ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } +static const CGEN_IFMT ifmt_callcle ATTRIBUTE_UNUSED = { + 64, 64, 0xffffffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_ja ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffff0000ffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } }; static const CGEN_IFMT ifmt_exit ATTRIBUTE_UNUSED = { - 64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } + 64, 64, 0xffffffffffffffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } } +}; + +static const CGEN_IFMT ifmt_xadddwle ATTRIBUTE_UNUSED = { + 64, 64, 0xffffffff000000ff, { { F (F_OP_ATOMIC) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } } +}; + +static const CGEN_IFMT ifmt_xadddwbe ATTRIBUTE_UNUSED = { + 64, 64, 0xffffffff000000ff, { { F (F_OP_ATOMIC) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } } }; #undef F @@ -1640,13 +1648,25 @@ static const CGEN_OPCODE bpf_cgen_insn_opcode_table[MAX_INSNS] = { { 0, 0, 0, 0 }, { { MNEM, ' ', OP (DISP32), 0 } }, - & ifmt_callle, { 0x85 } + & ifmt_callcle, { 0x85 } + }, +/* call $disp32 */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', OP (DISP32), 0 } }, + & ifmt_callcle, { 0x1085 } + }, +/* call $disp32 */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', OP (DISP32), 0 } }, + & ifmt_callcle, { 0x85 } }, /* call $disp32 */ { { 0, 0, 0, 0 }, { { MNEM, ' ', OP (DISP32), 0 } }, - & ifmt_callle, { 0x85 } + & ifmt_callcle, { 0x185 } }, /* call $dstle */ { @@ -1676,25 +1696,145 @@ static const CGEN_OPCODE bpf_cgen_insn_opcode_table[MAX_INSNS] = { { 0, 0, 0, 0 }, { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, - & ifmt_ldxwle, { 0xdb } + & ifmt_xadddwle, { 0x1000000db } }, /* xaddw [$dstle+$offset16],$srcle */ { { 0, 0, 0, 0 }, { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, - & ifmt_ldxwle, { 0xc3 } + & ifmt_xadddwle, { 0x1000000c3 } + }, +/* xordw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0x41000000db } + }, +/* xorw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0x41000000c3 } + }, +/* xanddw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0x51000000db } + }, +/* xandw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0x51000000c3 } + }, +/* xxordw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xa1000000db } + }, +/* xxorw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xa1000000c3 } + }, +/* xchgdw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xe1000000db } + }, +/* xchgw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xe1000000c3 } + }, +/* xcmpdw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xf1000000db } + }, +/* xcmpw [$dstle+$offset16],$srcle */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } }, + & ifmt_xadddwle, { 0xf1000000c3 } }, /* xadddw [$dstbe+$offset16],$srcbe */ { { 0, 0, 0, 0 }, { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, - & ifmt_ldxwbe, { 0xdb } + & ifmt_xadddwbe, { 0x1000000000000db } }, /* xaddw [$dstbe+$offset16],$srcbe */ { { 0, 0, 0, 0 }, { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, - & ifmt_ldxwbe, { 0xc3 } + & ifmt_xadddwbe, { 0x1000000000000c3 } + }, +/* xordw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0x41000000000000db } + }, +/* xorw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0x41000000000000c3 } + }, +/* xanddw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0x51000000000000db } + }, +/* xandw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0x51000000000000c3 } + }, +/* xxordw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xa1000000000000db } + }, +/* xxorw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xa1000000000000c3 } + }, +/* xchgdw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xe1000000000000db } + }, +/* xchgw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xe1000000000000c3 } + }, +/* xcmpdw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xf1000000000000db } + }, +/* xcmpw [$dstbe+$offset16],$srcbe */ + { + { 0, 0, 0, 0 }, + { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } }, + & ifmt_xadddwbe, { 0xf1000000000000c3 } }, /* brkpt */ { diff --git a/opcodes/bpf-opc.h b/opcodes/bpf-opc.h index c161f0d525..e8ad6b3c2b 100644 --- a/opcodes/bpf-opc.h +++ b/opcodes/bpf-opc.h @@ -109,10 +109,15 @@ typedef enum cgen_insn_type { , BPF_INSN_JSGTRBE, BPF_INSN_JSGT32IBE, BPF_INSN_JSGT32RBE, BPF_INSN_JSGEIBE , BPF_INSN_JSGERBE, BPF_INSN_JSGE32IBE, BPF_INSN_JSGE32RBE, BPF_INSN_JSLTIBE , BPF_INSN_JSLTRBE, BPF_INSN_JSLT32IBE, BPF_INSN_JSLT32RBE, BPF_INSN_JSLEIBE - , BPF_INSN_JSLERBE, BPF_INSN_JSLE32IBE, BPF_INSN_JSLE32RBE, BPF_INSN_CALLLE - , BPF_INSN_CALLBE, BPF_INSN_CALLRLE, BPF_INSN_CALLRBE, BPF_INSN_JA - , BPF_INSN_EXIT, BPF_INSN_XADDDWLE, BPF_INSN_XADDWLE, BPF_INSN_XADDDWBE - , BPF_INSN_XADDWBE, BPF_INSN_BRKPT + , BPF_INSN_JSLERBE, BPF_INSN_JSLE32IBE, BPF_INSN_JSLE32RBE, BPF_INSN_CALLCLE + , BPF_INSN_CALLLE, BPF_INSN_CALLCBE, BPF_INSN_CALLBE, BPF_INSN_CALLRLE + , BPF_INSN_CALLRBE, BPF_INSN_JA, BPF_INSN_EXIT, BPF_INSN_XADDDWLE + , BPF_INSN_XADDWLE, BPF_INSN_XORDWLE, BPF_INSN_XORWLE, BPF_INSN_XANDDWLE + , BPF_INSN_XANDWLE, BPF_INSN_XXORDWLE, BPF_INSN_XXORWLE, BPF_INSN_XCHGDWLE + , BPF_INSN_XCHGWLE, BPF_INSN_XCMPDWLE, BPF_INSN_XCMPWLE, BPF_INSN_XADDDWBE + , BPF_INSN_XADDWBE, BPF_INSN_XORDWBE, BPF_INSN_XORWBE, BPF_INSN_XANDDWBE + , BPF_INSN_XANDWBE, BPF_INSN_XXORDWBE, BPF_INSN_XXORWBE, BPF_INSN_XCHGDWBE + , BPF_INSN_XCHGWBE, BPF_INSN_XCMPDWBE, BPF_INSN_XCMPWBE, BPF_INSN_BRKPT } CGEN_INSN_TYPE; /* Index of `invalid' insn place holder. */ @@ -132,6 +137,7 @@ struct cgen_fields long f_op_class; long f_op_mode; long f_op_size; + long f_op_atomic; long f_dstle; long f_srcle; long f_dstbe; diff --git a/opcodes/cgen-dis.c b/opcodes/cgen-dis.c index 6a93060edd..02ca395fdc 100644 --- a/opcodes/cgen-dis.c +++ b/opcodes/cgen-dis.c @@ -39,9 +39,9 @@ static void add_insn_to_hash_chain (CGEN_INSN_LIST *, static int count_decodable_bits (const CGEN_INSN *insn) { - unsigned mask = CGEN_INSN_BASE_MASK (insn); + CGEN_INSN_LGUINT mask = CGEN_INSN_BASE_MASK (insn); int bits = 0; - unsigned m; + CGEN_INSN_LGUINT m; for (m = 1; m != 0; m <<= 1) { @@ -228,7 +228,7 @@ build_dis_hash_table (CGEN_CPU_DESC cd) /* Return the first entry in the hash list for INSN. */ CGEN_INSN_LIST * -cgen_dis_lookup_insn (CGEN_CPU_DESC cd, const char * buf, CGEN_INSN_INT value) +cgen_dis_lookup_insn (CGEN_CPU_DESC cd, const char * buf, CGEN_INSN_LGUINT value) { unsigned int hash; diff --git a/opcodes/cgen-dis.in b/opcodes/cgen-dis.in index 91d5173966..15c8663c48 100644 --- a/opcodes/cgen-dis.in +++ b/opcodes/cgen-dis.in @@ -202,7 +202,7 @@ print_insn (CGEN_CPU_DESC cd, bfd_byte *buf, unsigned int buflen) { - CGEN_INSN_INT insn_value; + CGEN_INSN_LGUINT insn_value; const CGEN_INSN_LIST *insn_list; CGEN_EXTRACT_INFO ex_info; int basesize; diff --git a/opcodes/cgen-opc.c b/opcodes/cgen-opc.c index 9fdbc6e118..7816ae78f1 100644 --- a/opcodes/cgen-opc.c +++ b/opcodes/cgen-opc.c @@ -355,13 +355,13 @@ cgen_macro_insn_count (CGEN_CPU_DESC cd) /* Cover function to read and properly byteswap an insn value. */ -CGEN_INSN_INT +CGEN_INSN_LGUINT cgen_get_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length, int endian) { int big_p = (endian == CGEN_ENDIAN_BIG); int insn_chunk_bitsize = cd->insn_chunk_bitsize; - CGEN_INSN_INT value = 0; + CGEN_INSN_LGUINT value = 0; if (insn_chunk_bitsize != 0 && insn_chunk_bitsize < length) { @@ -397,7 +397,7 @@ void cgen_put_insn_value (CGEN_CPU_DESC cd, unsigned char *buf, int length, - CGEN_INSN_INT value, + CGEN_INSN_LGUINT value, int endian) { int big_p = (endian == CGEN_ENDIAN_BIG); @@ -446,7 +446,7 @@ cgen_put_insn_value (CGEN_CPU_DESC cd, const CGEN_INSN * cgen_lookup_insn (CGEN_CPU_DESC cd, const CGEN_INSN *insn, - CGEN_INSN_INT insn_int_value, + CGEN_INSN_LGUINT insn_int_value, /* ??? CGEN_INSN_BYTES would be a nice type name to use here. */ unsigned char *insn_bytes_value, int length, -- 2.30.2