[PATCH v2] Add support to eBPF atomic instructions

Guillermo E. Martinez guillermo.e.martinez@oracle.com
Tue Oct 26 01:53:39 GMT 2021


Hello people,

This is the v2 for eBPF atomics patch, it has as major
improvement an option -mno-atomics intended to restrict the
use of `add + fetch' and the rest of atomic instructions,
and so, generate code running in old/new kernel versions.

Please let me know your comments, 

Thanks!,
Guillermo


   eBPF atomic instructions supported are: ADD, OR, AND,
   XOR, CHG, CMP (compare and exchange). To keep backward
   compatibility, atomic instructions uses the same op-mode
   that exchange and add instruction.

   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
   instruction 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.

 In order to restrict the use of `add + fetch' and the rest of
 atomic instructions the -mno-atomics was added.

 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,
    to be used with atomic abpf-isas.
    (arch bpf): Add abpf mach and isas.
    (define-abpf-isa): New pmacro.
    (all-isas): Add abpfle,abpfbe.
    (mach abpf): New.
    (model abpf-def): Likewise.
    (h-gpr): Add abpf isas.
    (f-dstle,f-srcle,f-dstbe,f-srcbe): Likewise.
    (dstle,srcle,dstbe,srcbe): Likewise.
    (h-r0):  Used by sim in compare and exchange eBPF atomic instruction
    (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.
    * bpf.opc: (bpf_parse_options) add support to parse argument
    to eBPF backend.
    (disassemble_init_bpf): Move logic related to BPF from
    disassemble_init_for_target.

 gas/
    * testsuite/gas/bpf/atomic.s: Adding eBPF atomic instructions.
    * testsuite/gas/bpf/atomic-be.d: Likewise.
    * testsuite/gas/bpf/atomic.d: Likewise.
    * testsuite/gas/bpf/atomic-add-no-fetch.s: Add case to
    non-fetching atomic add instruction.
    * testsuite/gas/bpf/atomic-add-no-fetch.d: Likewise.
    * testsuite/gas/bpf/atomic-add-no-fetch-be.d: Likewise.
    * config/tc-bpf.c: Add -mno-atomics option to disable use of
    atomic instructions.

 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                                 |  23 ++
 cpu/bpf.cpu                                   | 245 ++++++++++++++----
 cpu/bpf.opc                                   |  61 +++++
 gas/ChangeLog                                 |  12 +
 gas/config/tc-bpf.c                           |  31 ++-
 .../gas/bpf/atomic-add-no-fetch-be.d          |  12 +
 gas/testsuite/gas/bpf/atomic-add-no-fetch.d   |  11 +
 gas/testsuite/gas/bpf/atomic-add-no-fetch.s   |   4 +
 gas/testsuite/gas/bpf/atomic-be.d             |  14 +-
 gas/testsuite/gas/bpf/atomic.d                |  16 +-
 gas/testsuite/gas/bpf/atomic.s                |  17 +-
 gas/testsuite/gas/bpf/bpf.exp                 |   4 +
 gas/testsuite/gas/bpf/ftest-no-atomics.d      |   7 +
 include/ChangeLog                             |   4 +
 include/dis-asm.h                             |   1 +
 include/opcode/cgen.h                         |  12 +-
 opcodes/bpf-desc.c                            | 227 ++++++++++++----
 opcodes/bpf-desc.h                            |  33 ++-
 opcodes/bpf-dis.c                             |  63 ++++-
 opcodes/bpf-opc.c                             | 218 ++++++++++++++--
 opcodes/bpf-opc.h                             |  15 +-
 opcodes/cgen-dis.c                            |   6 +-
 opcodes/cgen-dis.in                           |   2 +-
 opcodes/cgen-opc.c                            |   8 +-
 opcodes/disassemble.c                         |  18 +-
 25 files changed, 887 insertions(+), 177 deletions(-)
 create mode 100644 gas/testsuite/gas/bpf/atomic-add-no-fetch-be.d
 create mode 100644 gas/testsuite/gas/bpf/atomic-add-no-fetch.d
 create mode 100644 gas/testsuite/gas/bpf/atomic-add-no-fetch.s
 create mode 100644 gas/testsuite/gas/bpf/ftest-no-atomics.d

diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index 2739df0edd..c98564128d 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,3 +1,26 @@
+2021-10-25  Guillermo E. Martinez  <guillermo.e.martinez@oracle.com>
+
+	* bpf.cpu (f-op-atomic): Define field for eBPF atomic (extra) opcodes,
+	to be used with atomic abpf-isas.
+	(arch bpf): Add abpf mach and isas.
+	(define-abpf-isa): New pmacro.
+	(all-isas): Add abpfle,abpfbe.
+	(mach abpf): New.
+	(model abpf-def): Likewise.
+	(h-gpr): Add abpf isas.
+	(f-dstle,f-srcle,f-dstbe,f-srcbe): Likewise.
+	(dstle,srcle,dstbe,srcbe): Likewise.
+	(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.
+	* bpf.opc: (bpf_parse_options) add support to parse argument
+	to eBPF backend.
+	(disassemble_init_bpf): Move logic related to BPF from
+	disassemble_init_for_target.
+
 2021-05-06  Stafford Horne  <shorne@gmail.com>
 
 	PR 21464
diff --git a/cpu/bpf.cpu b/cpu/bpf.cpu
index 13dde7094c..132f3f2b19 100644
--- a/cpu/bpf.cpu
+++ b/cpu/bpf.cpu
@@ -36,8 +36,8 @@
   ;; It is confusing that the simulator follows the emulated memory
   ;; access conventions for fetching instructions by pieces...
   (default-alignment unaligned)
-  (machs bpf xbpf)
-  (isas ebpfle ebpfbe xbpfle xbpfbe))
+  (machs bpf xbpf abpf)
+  (isas ebpfle ebpfbe xbpfle xbpfbe abpfle abpfbe))
 
 ;;;; The ISAs
 
@@ -116,8 +116,20 @@
 (define-xbpf-isa le)
 (define-xbpf-isa be)
 
-(define-pmacro all-isas () (ISA ebpfle,ebpfbe,xbpfle,xbpfbe))
+(define-pmacro (define-abpf-isa x-endian)
+  (define-isa
+    (name (.sym abpf x-endian))
+    (comment "The atomic BPF instruction set")
+    (default-insn-word-bitsize 64)
+    (default-insn-bitsize 64)
+    (base-insn-bitsize 64)))
+
+(define-abpf-isa le)
+(define-abpf-isa be)
+
+(define-pmacro all-isas () (ISA ebpfle,ebpfbe,xbpfle,xbpfbe,abpfle,abpfbe))
 (define-pmacro xbpf-isas () (ISA xbpfle,xbpfbe))
+(define-pmacro abpf-isas () (ISA abpfle,abpfbe))
 
 (define-pmacro (endian-isas x-endian)
   ((ISA (.sym ebpf x-endian) (.sym xbpf x-endian))))
@@ -128,10 +140,11 @@
 ;;         bpf            architecture
 ;;          |
 ;;        bpfbf           cpu-family
-;;      /       \
-;;     bpf     xbpf       machine
-;;      |       |
-;;   bpf-def  xbpf-def    model
+;;      /   |   \
+;;    bpf  abpf xbpf      machine
+;;     |    |    |
+;;  bpf-def | xbpf-def    model
+;;       abpf-def
 
 (define-cpu
   (name bpfbf)
@@ -177,6 +190,25 @@
     () ; profile action (default)
     ))
 
+(define-mach
+  (name abpf)
+  (comment "Atomic BPF")
+  (cpu bpfbf)
+  (isas abpfle abpfbe))
+
+(define-model
+  (name abpf-def)
+  (comment "aBPF default model")
+  (mach abpf)
+  (unit u-exec "execution unit" ()
+    1 ; issue
+    1 ; done
+    () ; state
+    () ; inputs
+    () ; outputs
+    () ; profile action (default)
+    ))
+
 ;;;; Hardware Elements
 
 ;; eBPF programs can access 10 general-purpose registers which are
@@ -185,7 +217,7 @@
 (define-hardware
   (name h-gpr)
   (comment "General Purpose Registers")
-  (attrs all-isas (MACH bpf xbpf))
+  (attrs all-isas (MACH bpf xbpf abpf))
   (type register DI (16))
   (indices keyword "%"
            ;; XXX the frame pointer fp is read-only, so it should
@@ -206,7 +238,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 +318,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" (abpf-isas) 32 64 31 32 UINT)
+
+(define-normal-insn-enum insn-atomic-op-le "eBPF atomic insn"
+    ((ISA abpfle)) 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 abpfbe)) 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
@@ -295,11 +376,11 @@
 ;; NOT use registers, where endianness is irrelevant i.e. f-regs is a
 ;; constant 0 opcode.
 
-(dwf f-dstle "eBPF dst register field" ((ISA ebpfle xbpfle)) 8 8 3 4 UINT)
-(dwf f-srcle "eBPF source register field" ((ISA ebpfle xbpfle)) 8 8 7 4 UINT)
+(dwf f-dstle "eBPF dst register field" ((ISA ebpfle xbpfle abpfle)) 8 8 3 4 UINT)
+(dwf f-srcle "eBPF source register field" ((ISA ebpfle xbpfle abpfle)) 8 8 7 4 UINT)
 
-(dwf f-dstbe "eBPF dst register field" ((ISA ebpfbe xbpfbe)) 8 8 7 4 UINT)
-(dwf f-srcbe "eBPF source register field" ((ISA ebpfbe xbpfbe)) 8 8 3 4 UINT)
+(dwf f-dstbe "eBPF dst register field" ((ISA ebpfbe xbpfbe abpfbe)) 8 8 7 4 UINT)
+(dwf f-srcbe "eBPF source register field" ((ISA ebpfbe xbpfbe abpfbe)) 8 8 3 4 UINT)
 
 (dwf f-regs "eBPF registers field" (all-isas) 8 8 7 8 UINT)
 
@@ -339,11 +420,11 @@
 ;; A couple of source and destination register operands are defined
 ;; for each ISA: ebpfle and ebpfbe.
 
-(dno dstle "destination register" ((ISA ebpfle xbpfle)) h-gpr f-dstle)
-(dno srcle "source register" ((ISA ebpfle xbpfle)) h-gpr f-srcle)
+(dno dstle "destination register" ((ISA ebpfle xbpfle abpfle)) h-gpr f-dstle)
+(dno srcle "source register" ((ISA ebpfle xbpfle abpfle)) h-gpr f-srcle)
 
-(dno dstbe "destination register" ((ISA ebpfbe xbpfbe)) h-gpr f-dstbe)
-(dno srcbe "source register" ((ISA ebpfbe xbpfbe)) h-gpr f-srcbe)
+(dno dstbe "destination register" ((ISA ebpfbe xbpfbe abpfbe)) h-gpr f-dstbe)
+(dno srcbe "source register" ((ISA ebpfbe xbpfbe abpfbe)) h-gpr f-srcbe)
 
 ;; Jump instructions have a 16-bit PC-relative address.
 ;; CALL instructions have a 32-bit PC-relative address.
@@ -758,24 +839,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'.
 
-(define-call-insn le)
-(define-call-insn be)
+    (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-callc-call-insn le)
+(define-callc-call-insn be)
 
 (define-pmacro (define-callr-insn x-endian)
   (dni (.sym callr x-endian)
@@ -808,38 +907,94 @@
      (c-call VOID "bpfbf_exit")
      ())
 
-;;; Atomic instructions
+;;; Legacy atomic xadd{w,dw} instruction
 
-;; The atomic exchange-and-add 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-add 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)))))
 
-(define-pmacro (define-atomic-insns x-endian)
+(define-pmacro (define-atomic-add-insn 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)
+            offset16 OP_MODE_ATOMIC OP_SIZE_DW OP_CLASS_STX)
+         (sem-exchange-and-add 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)
+            offset16 OP_MODE_ATOMIC OP_SIZE_W OP_CLASS_STX)
+         (sem-exchange-and-add add x-endian SI)
          ())))
 
+(define-atomic-add-insn le)
+(define-atomic-add-insn be)
+
+;;; Atomic instructions
+
+;; 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-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))
+            (set x-mode tmp (mem x-mode (add DI (.sym dst x-endian) offset16)))
+            (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)
+          ((ISA (.sym abpf 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
+    (dais addf (.if (.eq x-endian le) OP_ATOMIC_LE_ADD OP_ATOMIC_BE_ADD)
+          x-endian sem-exchange-and-add)
+    (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/cpu/bpf.opc b/cpu/bpf.opc
index e70ee04841..f2003d6356 100644
--- a/cpu/bpf.opc
+++ b/cpu/bpf.opc
@@ -186,6 +186,67 @@ print_endsize (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   (*info->fprintf_func) (info->stream, "%lu", value);
 }
 
+/* BPF options bitset. */
+static unsigned long bpf_opt;
+
+enum {
+  /*
+   * Disable support for atomic instructions, allowing
+   * just to use xadd non-fetch instruction.
+   */
+  OPT_BPF_NOATOMIC = (1 << 0),
+};
+
+/* Handle -M options for BPF target passed by command line */
+static void
+bpf_parse_options (struct disassemble_info *info);
+
+static void
+bpf_parse_options (struct disassemble_info *info)
+{
+  const char *opts = info->disassembler_options;
+
+  while (opts != NULL)
+    {
+      if (startswith (opts, "no-atomics"))
+        bpf_opt |= OPT_BPF_NOATOMIC;
+
+      opts = strchr (opts, ',');
+      if (opts)
+        opts++;
+    }
+}
+
+void
+disassemble_init_bpf (struct disassemble_info *info)
+{
+  info->endian_code = BFD_ENDIAN_LITTLE;
+
+  if (!info->private_data)
+    {
+      info->private_data = cgen_bitset_create (ISA_MAX);
+      bpf_parse_options (info);
+
+      if (info->endian == BFD_ENDIAN_BIG)
+        {
+          cgen_bitset_set (info->private_data, ISA_EBPFBE);
+          if (info->mach == bfd_mach_xbpf)
+            cgen_bitset_set (info->private_data, ISA_XBPFBE);
+
+          if (!(bpf_opt & OPT_BPF_NOATOMIC))
+            cgen_bitset_add (info->private_data, ISA_ABPFBE);
+        }
+      else
+        {
+          cgen_bitset_set (info->private_data, ISA_EBPFLE);
+          if (info->mach == bfd_mach_xbpf)
+            cgen_bitset_set (info->private_data, ISA_XBPFLE);
+
+          if (!(bpf_opt & OPT_BPF_NOATOMIC))
+            cgen_bitset_add (info->private_data, ISA_ABPFLE);
+        }
+    }
+}
 
 /* -- */
 
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 6bcb035621..2ad4fe4b1b 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,15 @@
+2021-10-25  Guillermo E. Martinez  <guillermo.e.martinez@oracle.com>
+
+	* testsuite/gas/bpf/atomic.s: Adding eBPF atomic instructions.
+	* testsuite/gas/bpf/atomic-be.d: Likewise.
+	* testsuite/gas/bpf/atomic.d: Likewise.
+	* testsuite/gas/bpf/atomic-add-no-fetch.s: Add case to
+	non-fetching atomic add instruction.
+	* testsuite/gas/bpf/atomic-add-no-fetch.d: Likewise.
+	* testsuite/gas/bpf/atomic-add-no-fetch-be.d: Likewise.
+	* config/tc-bpf.c: Add -mno-atomics option to disable use of
+	atomic instructions.
+
 2021-06-11  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* config/tc-i386.c (x86_cons): Handle GOT/PLT relocations only
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index 48a0ebc48c..6238aff6c5 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -98,7 +98,13 @@ enum options
 {
   OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
   OPTION_BIG_ENDIAN,
-  OPTION_XBPF
+  OPTION_XBPF,
+
+  /*
+   * Disable full support for atomic instructions,
+   * just legacy xadd instruction will be enabled.
+   */
+  OPTION_DISABLE_ABPF,
 };
 
 struct option md_longopts[] =
@@ -106,6 +112,7 @@ struct option md_longopts[] =
   { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
   { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
   { "mxbpf", no_argument, NULL, OPTION_XBPF },
+  { "mno-atomics", no_argument, NULL, OPTION_DISABLE_ABPF },
   { NULL,          no_argument, NULL, 0 },
 };
 
@@ -123,6 +130,8 @@ static int target_xbpf = 0;
 
 static int set_xbpf = 0;
 
+static int set_abpf = 1;
+
 int
 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
 {
@@ -140,6 +149,9 @@ md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
       set_xbpf = 1;
       target_xbpf = 1;
       break;
+    case OPTION_DISABLE_ABPF:
+      set_abpf = 0;
+      break;
     default:
       return 0;
     }
@@ -154,7 +166,8 @@ md_show_usage (FILE * stream)
   fprintf (stream, _("\
   --EL			generate code for a little endian machine\n\
   --EB			generate code for a big endian machine\n\
-  -mxbpf                generate xBPF instructions\n"));
+  -mxbpf                generate xBPF instructions\n\
+  -mno-atomics          disable eBPF atomics instructions\n"));
 }
 
 
@@ -184,16 +197,22 @@ md_begin (void)
   if (target_big_endian)
     {
       if (target_xbpf)
-	cgen_bitset_set (bpf_isa, ISA_XBPFBE);
+        cgen_bitset_set (bpf_isa, ISA_XBPFBE);
       else
-	cgen_bitset_set (bpf_isa, ISA_EBPFBE);
+        cgen_bitset_set (bpf_isa, ISA_EBPFBE);
+
+      if (set_abpf)
+        cgen_bitset_add (bpf_isa, ISA_ABPFBE);
     }
   else
     {
       if (target_xbpf)
-	cgen_bitset_set (bpf_isa, ISA_XBPFLE);
+        cgen_bitset_set (bpf_isa, ISA_XBPFLE);
       else
-	cgen_bitset_set (bpf_isa, ISA_EBPFLE);
+        cgen_bitset_set (bpf_isa, ISA_EBPFLE);
+
+      if (set_abpf)
+        cgen_bitset_add (bpf_isa, ISA_ABPFLE);
     }
 
   /* Set the machine number and endian.  */
diff --git a/gas/testsuite/gas/bpf/atomic-add-no-fetch-be.d b/gas/testsuite/gas/bpf/atomic-add-no-fetch-be.d
new file mode 100644
index 0000000000..56a4ac1cfc
--- /dev/null
+++ b/gas/testsuite/gas/bpf/atomic-add-no-fetch-be.d
@@ -0,0 +1,12 @@
+#as: --EB -mno-atomics
+#source: atomic-add-no-fetch.s
+#objdump: -dr
+#name: eBPF atomic add non-fetch instruction, big endian
+
+.*: +file format .*bpf.*
+
+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
diff --git a/gas/testsuite/gas/bpf/atomic-add-no-fetch.d b/gas/testsuite/gas/bpf/atomic-add-no-fetch.d
new file mode 100644
index 0000000000..f93391b885
--- /dev/null
+++ b/gas/testsuite/gas/bpf/atomic-add-no-fetch.d
@@ -0,0 +1,11 @@
+#as: --EL -mno-atomics
+#objdump: -dr
+#name: eBPF atomic add non-fetch instruction, little endian
+
+.*: +file format .*bpf.*
+
+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
diff --git a/gas/testsuite/gas/bpf/atomic-add-no-fetch.s b/gas/testsuite/gas/bpf/atomic-add-no-fetch.s
new file mode 100644
index 0000000000..7dab9aa0cb
--- /dev/null
+++ b/gas/testsuite/gas/bpf/atomic-add-no-fetch.s
@@ -0,0 +1,4 @@
+        # Test for eBPF atomic xadd{w,dw} instructions
+        .text
+        xadddw	[%r1+0x1eef], %r2
+        xaddw	[%r1+0x1eef], %r2
diff --git a/gas/testsuite/gas/bpf/atomic-be.d b/gas/testsuite/gas/bpf/atomic-be.d
index 04161e08ac..f711bea5ca 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 	xaddfdw \[%r1\+0x1eef\],%r2
+   8:	c3 12 1e ef 00 00 00 01 	xaddfw \[%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..3a8f27a406 100644
--- a/gas/testsuite/gas/bpf/atomic.d
+++ b/gas/testsuite/gas/bpf/atomic.d
@@ -1,11 +1,21 @@
 #as: --EL
 #objdump: -dr
-#name: eBPF atomic instructions
+#name: eBPF atomic instructions, little endian
 
 .*: +file format .*bpf.*
 
 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 	xaddfdw \[%r1\+0x1eef\],%r2
+   8:	c3 21 ef 1e 01 00 00 00 	xaddfw \[%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..8f657e0513 100644
--- a/gas/testsuite/gas/bpf/atomic.s
+++ b/gas/testsuite/gas/bpf/atomic.s
@@ -1,5 +1,14 @@
-        # Test for eBPF ADDW and ADDDW instructions
+        # Test for eBPF atomic instructions
         .text
-        xadddw	[%r1+0x1eef], %r2
-        xaddw	[%r1+0x1eef], %r2
-        
+        xaddfdw [%r1+0x1eef], %r2
+        xaddfw  [%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/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp
index 8486024c3f..a81536cd0e 100644
--- a/gas/testsuite/gas/bpf/bpf.exp
+++ b/gas/testsuite/gas/bpf/bpf.exp
@@ -27,6 +27,7 @@ if {[istarget bpf*-*-*]} {
     run_dump_test call
     run_dump_test exit
     run_dump_test atomic
+    run_dump_test atomic-add-no-fetch
     run_dump_test data
 
     run_dump_test lddw-be
@@ -37,6 +38,7 @@ if {[istarget bpf*-*-*]} {
     run_dump_test call-be
     run_dump_test exit-be
     run_dump_test atomic-be
+    run_dump_test atomic-add-no-fetch-be
     run_dump_test data-be
 
     run_dump_test indcall-1
@@ -44,4 +46,6 @@ if {[istarget bpf*-*-*]} {
 
     run_dump_test alu-xbpf
     run_dump_test alu32-xbpf
+
+    run_dump_test ftest-no-atomics
 }
diff --git a/gas/testsuite/gas/bpf/ftest-no-atomics.d b/gas/testsuite/gas/bpf/ftest-no-atomics.d
new file mode 100644
index 0000000000..9d0e97d1fa
--- /dev/null
+++ b/gas/testsuite/gas/bpf/ftest-no-atomics.d
@@ -0,0 +1,7 @@
+#as: --EL -mno-atomics
+#source: atomic.s
+#objdump: -dr
+#xfail: bpf*-*-*
+#name: eBPF no-atomics, little endian
+
+.*: +file format .*bpf.*
diff --git a/include/ChangeLog b/include/ChangeLog
index 27c5e29449..f5099afa0d 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2021-10-25  Guillermo E. Martinez  <guillermo.e.martinez@oracle.com>
+
+	* opcode/cgen.h: Replace data type CGEN_INSN_INT by CGEN_INSN_LGUINT.
+
 2021-06-02  Shahab Vahedi  <shahab@synopsys.com>
 
 	* dis-asm.h (disassembler_options_arc): New prototype.
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 0b91ab47ff..ee311fd40d 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -315,6 +315,7 @@ extern void disassemble_init_powerpc (struct disassemble_info *);
 extern void disassemble_init_s390 (struct disassemble_info *);
 extern void disassemble_init_wasm32 (struct disassemble_info *);
 extern void disassemble_init_nds32 (struct disassemble_info *);
+extern void disassemble_init_bpf (struct disassemble_info *);
 extern const disasm_options_and_args_t *disassembler_options_arc (void);
 extern const disasm_options_and_args_t *disassembler_options_arm (void);
 extern const disasm_options_and_args_t *disassembler_options_mips (void);
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..25db5099a6 100644
--- a/opcodes/bpf-desc.c
+++ b/opcodes/bpf-desc.c
@@ -26,6 +26,7 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
 #include "sysdep.h"
 #include <stdio.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include "ansidecl.h"
 #include "bfd.h"
 #include "symcat.h"
@@ -49,6 +50,7 @@ static const CGEN_ATTR_ENTRY MACH_attr[] ATTRIBUTE_UNUSED =
   { "base", MACH_BASE },
   { "bpf", MACH_BPF },
   { "xbpf", MACH_XBPF },
+  { "abpf", MACH_ABPF },
   { "max", MACH_MAX },
   { 0, 0 }
 };
@@ -59,6 +61,8 @@ static const CGEN_ATTR_ENTRY ISA_attr[] ATTRIBUTE_UNUSED =
   { "ebpfbe", ISA_EBPFBE },
   { "xbpfle", ISA_XBPFLE },
   { "xbpfbe", ISA_XBPFBE },
+  { "abpfle", ISA_ABPFLE },
+  { "abpfbe", ISA_ABPFBE },
   { "max", ISA_MAX },
   { 0, 0 }
 };
@@ -126,6 +130,8 @@ static const CGEN_ISA bpf_cgen_isa_table[] = {
   { "ebpfbe", 64, 64, 64, 128 },
   { "xbpfle", 64, 64, 64, 128 },
   { "xbpfbe", 64, 64, 64, 128 },
+  { "abpfle", 64, 64, 64, 64 },
+  { "abpfbe", 64, 64, 64, 64 },
   { 0, 0, 0, 0, 0 }
 };
 
@@ -134,6 +140,7 @@ static const CGEN_ISA bpf_cgen_isa_table[] = {
 static const CGEN_MACH bpf_cgen_mach_table[] = {
   { "bpf", "bpf", MACH_BPF, 0 },
   { "xbpf", "xbpf", MACH_XBPF, 0 },
+  { "abpf", "abpf", MACH_ABPF, 0 },
   { 0, 0, 0, 0 }
 };
 
@@ -169,14 +176,15 @@ CGEN_KEYWORD bpf_cgen_opval_h_gpr =
 
 const CGEN_HW_ENTRY bpf_cgen_hw_table[] =
 {
-  { "h-memory", HW_H_MEMORY, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } },
-  { "h-sint", HW_H_SINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } },
-  { "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } },
-  { "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } },
-  { "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-sint64", HW_H_SINT64, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } } },
+  { "h-memory", HW_H_MEMORY, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-sint", HW_H_SINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-gpr", HW_H_GPR, CGEN_ASM_KEYWORD, (PTR) & bpf_cgen_opval_h_gpr, { 0, { { { (1<<MACH_BPF)|(1<<MACH_XBPF)|(1<<MACH_ABPF), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-r0", HW_H_R0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
+  { "h-sint64", HW_H_SINT64, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } } },
   { 0, 0, CGEN_ASM_NONE, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x80" } } } } }
 };
 
@@ -189,24 +197,25 @@ const CGEN_HW_ENTRY bpf_cgen_hw_table[] =
 
 const CGEN_IFLD bpf_cgen_ifld_table[] =
 {
-  { BPF_F_NIL, "f-nil", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_ANYOF, "f-anyof", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_OP_CODE, "f-op-code", 0, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_OP_SRC, "f-op-src", 0, 8, 3, 1, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { 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_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" } } } }  },
-  { BPF_F_SRCBE, "f-srcbe", 8, 8, 3, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } }  },
-  { BPF_F_REGS, "f-regs", 8, 8, 7, 8, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_OFFSET16, "f-offset16", 16, 16, 15, 16, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_IMM32, "f-imm32", 32, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_IMM64_A, "f-imm64-a", 32, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_IMM64_B, "f-imm64-b", 64, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_IMM64_C, "f-imm64-c", 96, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
-  { BPF_F_IMM64, "f-imm64", 0, 0, 0, 0,{ 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+  { BPF_F_NIL, "f-nil", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_ANYOF, "f-anyof", 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_CODE, "f-op-code", 0, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_SRC, "f-op-src", 0, 8, 3, 1, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_CLASS, "f-op-class", 0, 8, 2, 3, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_MODE, "f-op-mode", 0, 8, 7, 3, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_SIZE, "f-op-size", 0, 8, 4, 2, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OP_ATOMIC, "f-op-atomic", 32, 64, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xc" } } } }  },
+  { BPF_F_DSTLE, "f-dstle", 8, 8, 3, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa8" } } } }  },
+  { BPF_F_SRCLE, "f-srcle", 8, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa8" } } } }  },
+  { BPF_F_DSTBE, "f-dstbe", 8, 8, 7, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x54" } } } }  },
+  { BPF_F_SRCBE, "f-srcbe", 8, 8, 3, 4, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x54" } } } }  },
+  { BPF_F_REGS, "f-regs", 8, 8, 7, 8, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_OFFSET16, "f-offset16", 16, 16, 15, 16, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_IMM32, "f-imm32", 32, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_IMM64_A, "f-imm64-a", 32, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_IMM64_B, "f-imm64-b", 64, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_IMM64_C, "f-imm64-c", 96, 32, 31, 32, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
+  { BPF_F_IMM64, "f-imm64", 0, 0, 0, 0,{ 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
   { 0, 0, 0, 0, 0, 0, { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x80" } } } } }
 };
 
@@ -239,47 +248,47 @@ const CGEN_OPERAND bpf_cgen_operand_table[] =
 /* pc: program counter */
   { "pc", BPF_OPERAND_PC, HW_H_PC, 0, 0,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_NIL] } },
-    { 0|A(SEM_ONLY), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0|A(SEM_ONLY), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* dstle: destination register */
   { "dstle", BPF_OPERAND_DSTLE, HW_H_GPR, 3, 4,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_DSTLE] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa8" } } } }  },
 /* srcle: source register */
   { "srcle", BPF_OPERAND_SRCLE, HW_H_GPR, 7, 4,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_SRCLE] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa0" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xa8" } } } }  },
 /* dstbe: destination register */
   { "dstbe", BPF_OPERAND_DSTBE, HW_H_GPR, 7, 4,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_DSTBE] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x54" } } } }  },
 /* srcbe: source register */
   { "srcbe", BPF_OPERAND_SRCBE, HW_H_GPR, 3, 4,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_SRCBE] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x54" } } } }  },
 /* disp16: 16-bit PC-relative address */
   { "disp16", BPF_OPERAND_DISP16, HW_H_SINT, 15, 16,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_OFFSET16] } },
-    { 0|A(PCREL_ADDR), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0|A(PCREL_ADDR), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* disp32: 32-bit PC-relative address */
   { "disp32", BPF_OPERAND_DISP32, HW_H_SINT, 31, 32,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_IMM32] } },
-    { 0|A(PCREL_ADDR), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0|A(PCREL_ADDR), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* imm32: 32-bit immediate */
   { "imm32", BPF_OPERAND_IMM32, HW_H_SINT, 31, 32,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_IMM32] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* offset16: 16-bit offset */
   { "offset16", BPF_OPERAND_OFFSET16, HW_H_SINT, 15, 16,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_OFFSET16] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* imm64: 64-bit immediate */
   { "imm64", BPF_OPERAND_IMM64, HW_H_SINT64, 31, 96,
     { 3, { (const PTR) &BPF_F_IMM64_MULTI_IFIELD[0] } },
-    { 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0|A(VIRTUAL), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* endsize: endianness size immediate: 16, 32 or 64 */
   { "endsize", BPF_OPERAND_ENDSIZE, HW_H_UINT, 31, 32,
     { 0, { (const PTR) &bpf_cgen_ifld_table[BPF_F_IMM32] } },
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }  },
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }  },
 /* sentinel */
   { 0, 0, 0, 0, 0,
     { 0, { (const PTR) 0 } },
@@ -913,22 +922,22 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] =
 /* ldabsw $imm32 */
   {
     BPF_INSN_LDABSW, "ldabsw", "ldabsw", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* ldabsh $imm32 */
   {
     BPF_INSN_LDABSH, "ldabsh", "ldabsh", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* ldabsb $imm32 */
   {
     BPF_INSN_LDABSB, "ldabsb", "ldabsb", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* ldabsdw $imm32 */
   {
     BPF_INSN_LDABSDW, "ldabsdw", "ldabsdw", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* ldindw $srcle,$imm32 */
   {
@@ -1530,11 +1539,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,
@@ -1553,12 +1572,12 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] =
 /* ja $disp16 */
   {
     BPF_INSN_JA, "ja", "ja", 64,
-    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0|A(UNCOND_CTI), { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* exit */
   {
     BPF_INSN_EXIT, "exit", "exit", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 /* xadddw [$dstle+$offset16],$srcle */
   {
@@ -1580,10 +1599,130 @@ static const CGEN_IBASE bpf_cgen_insn_table[MAX_INSNS] =
     BPF_INSN_XADDWBE, "xaddwbe", "xaddw", 64,
     { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x50" } } } }
   },
+/* xaddfdw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XADDFDWLE, "xaddfdwle", "xaddfdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xaddfw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XADDFWLE, "xaddfwle", "xaddfw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xordw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XORDWLE, "xordwle", "xordw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xorw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XORWLE, "xorwle", "xorw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xanddw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XANDDWLE, "xanddwle", "xanddw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xandw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XANDWLE, "xandwle", "xandw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xxordw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XXORDWLE, "xxordwle", "xxordw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xxorw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XXORWLE, "xxorwle", "xxorw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xchgdw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XCHGDWLE, "xchgdwle", "xchgdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xchgw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XCHGWLE, "xchgwle", "xchgw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xcmpdw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XCMPDWLE, "xcmpdwle", "xcmpdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xcmpw [$dstle+$offset16],$srcle */
+  {
+    BPF_INSN_XCMPWLE, "xcmpwle", "xcmpw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x8" } } } }
+  },
+/* xaddfdw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XADDFDWBE, "xaddfdwbe", "xaddfdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xaddfw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XADDFWBE, "xaddfwbe", "xaddfw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xordw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XORDWBE, "xordwbe", "xordw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xorw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XORWBE, "xorwbe", "xorw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xanddw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XANDDWBE, "xanddwbe", "xanddw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xandw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XANDWBE, "xandwbe", "xandw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xxordw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XXORDWBE, "xxordwbe", "xxordw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xxorw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XXORWBE, "xxorwbe", "xxorw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xchgdw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XCHGDWBE, "xchgdwbe", "xchgdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xchgw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XCHGWBE, "xchgwbe", "xchgw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xcmpdw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XCMPDWBE, "xcmpdwbe", "xcmpdw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
+/* xcmpw [$dstbe+$offset16],$srcbe */
+  {
+    BPF_INSN_XCMPWBE, "xcmpwbe", "xcmpw", 64,
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\x4" } } } }
+  },
 /* brkpt */
   {
     BPF_INSN_BRKPT, "brkpt", "brkpt", 64,
-    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xf0" } } } }
+    { 0, { { { (1<<MACH_BASE), 0 } }, { { 1, "\xfc" } } } }
   },
 };
 
diff --git a/opcodes/bpf-desc.h b/opcodes/bpf-desc.h
index 1e3bebbda5..8bc8140dfc 100644
--- a/opcodes/bpf-desc.h
+++ b/opcodes/bpf-desc.h
@@ -50,7 +50,7 @@ extern "C" {
 #define CGEN_INT_INSN_P 0
 
 /* Maximum number of syntax elements in an instruction.  */
-#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 16
+#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 17
 
 /* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands.
    e.g. In "b,a foo" the ",a" is an operand.  If mnemonics have operands
@@ -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.  */
@@ -100,13 +112,14 @@ typedef enum insn_op_size {
 
 /* Enum declaration for machine type selection.  */
 typedef enum mach_attr {
-  MACH_BASE, MACH_BPF, MACH_XBPF, MACH_MAX
+  MACH_BASE, MACH_BPF, MACH_XBPF, MACH_ABPF
+ , MACH_MAX
 } MACH_ATTR;
 
 /* Enum declaration for instruction set selection.  */
 typedef enum isa_attr {
   ISA_EBPFLE, ISA_EBPFBE, ISA_XBPFLE, ISA_XBPFBE
- , ISA_MAX
+ , ISA_ABPFLE, ISA_ABPFBE, ISA_MAX
 } ISA_ATTR;
 
 /* Number of architecture variants.  */
@@ -140,10 +153,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 +184,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..06834496a3 100644
--- a/opcodes/bpf-dis.c
+++ b/opcodes/bpf-dis.c
@@ -132,6 +132,67 @@ print_endsize (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
   (*info->fprintf_func) (info->stream, "%lu", value);
 }
 
+/* BPF options bitset. */
+static unsigned long bpf_opt;
+
+enum {
+  /*
+   * Disable support for atomic instructions, allowing
+   * just to use xadd non-fetch instruction.
+   */
+  OPT_BPF_NOATOMIC = (1 << 0),
+};
+
+/* Handle -M options for BPF target passed by command line */
+static void
+bpf_parse_options (struct disassemble_info *info);
+
+static void
+bpf_parse_options (struct disassemble_info *info)
+{
+  const char *opts = info->disassembler_options;
+
+  while (opts != NULL)
+    {
+      if (startswith (opts, "no-atomics"))
+        bpf_opt |= OPT_BPF_NOATOMIC;
+
+      opts = strchr (opts, ',');
+      if (opts)
+        opts++;
+    }
+}
+
+void
+disassemble_init_bpf (struct disassemble_info *info)
+{
+  info->endian_code = BFD_ENDIAN_LITTLE;
+
+  if (!info->private_data)
+    {
+      info->private_data = cgen_bitset_create (ISA_MAX);
+      bpf_parse_options (info);
+
+      if (info->endian == BFD_ENDIAN_BIG)
+        {
+          cgen_bitset_set (info->private_data, ISA_EBPFBE);
+          if (info->mach == bfd_mach_xbpf)
+            cgen_bitset_set (info->private_data, ISA_XBPFBE);
+
+          if (!(bpf_opt & OPT_BPF_NOATOMIC))
+            cgen_bitset_add (info->private_data, ISA_ABPFBE);
+        }
+      else
+        {
+          cgen_bitset_set (info->private_data, ISA_EBPFLE);
+          if (info->mach == bfd_mach_xbpf)
+            cgen_bitset_set (info->private_data, ISA_XBPFLE);
+
+          if (!(bpf_opt & OPT_BPF_NOATOMIC))
+            cgen_bitset_add (info->private_data, ISA_ABPFLE);
+        }
+    }
+}
 
 /* -- */
 
@@ -367,7 +428,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..04c3a265b6 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_xaddfdwle 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_xaddfdwbe 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 */
   {
@@ -1696,6 +1716,150 @@ static const CGEN_OPCODE bpf_cgen_insn_opcode_table[MAX_INSNS] =
     { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
     & ifmt_ldxwbe, { 0xc3 }
   },
+/* xaddfdw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x1000000db }
+  },
+/* xaddfw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x1000000c3 }
+  },
+/* xordw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x41000000db }
+  },
+/* xorw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x41000000c3 }
+  },
+/* xanddw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x51000000db }
+  },
+/* xandw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0x51000000c3 }
+  },
+/* xxordw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xa1000000db }
+  },
+/* xxorw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xa1000000c3 }
+  },
+/* xchgdw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xe1000000db }
+  },
+/* xchgw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xe1000000c3 }
+  },
+/* xcmpdw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xf1000000db }
+  },
+/* xcmpw [$dstle+$offset16],$srcle */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTLE), '+', OP (OFFSET16), ']', ',', OP (SRCLE), 0 } },
+    & ifmt_xaddfdwle, { 0xf1000000c3 }
+  },
+/* xaddfdw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x1000000000000db }
+  },
+/* xaddfw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x1000000000000c3 }
+  },
+/* xordw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x41000000000000db }
+  },
+/* xorw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x41000000000000c3 }
+  },
+/* xanddw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x51000000000000db }
+  },
+/* xandw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0x51000000000000c3 }
+  },
+/* xxordw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xa1000000000000db }
+  },
+/* xxorw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xa1000000000000c3 }
+  },
+/* xchgdw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xe1000000000000db }
+  },
+/* xchgw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xe1000000000000c3 }
+  },
+/* xcmpdw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xf1000000000000db }
+  },
+/* xcmpw [$dstbe+$offset16],$srcbe */
+  {
+    { 0, 0, 0, 0 },
+    { { MNEM, ' ', '[', OP (DSTBE), '+', OP (OFFSET16), ']', ',', OP (SRCBE), 0 } },
+    & ifmt_xaddfdwbe, { 0xf1000000000000c3 }
+  },
 /* brkpt */
   {
     { 0, 0, 0, 0 },
diff --git a/opcodes/bpf-opc.h b/opcodes/bpf-opc.h
index c161f0d525..77b2109317 100644
--- a/opcodes/bpf-opc.h
+++ b/opcodes/bpf-opc.h
@@ -109,10 +109,16 @@ 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_XADDDWBE, BPF_INSN_XADDWBE, BPF_INSN_XADDFDWLE
+ , BPF_INSN_XADDFWLE, 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_XADDFDWBE
+ , BPF_INSN_XADDFWBE, 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 +138,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,
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 8590e945c5..318d359847 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -660,23 +660,7 @@ disassemble_init_for_target (struct disassemble_info * info)
 #endif
 #ifdef ARCH_bpf
     case bfd_arch_bpf:
-      info->endian_code = BFD_ENDIAN_LITTLE;
-      if (!info->private_data)
-	{
-	  info->private_data = cgen_bitset_create (ISA_MAX);
-	  if (info->endian == BFD_ENDIAN_BIG)
-	    {
-	      cgen_bitset_set (info->private_data, ISA_EBPFBE);
-	      if (info->mach == bfd_mach_xbpf)
-		cgen_bitset_set (info->private_data, ISA_XBPFBE);
-	    }
-	  else
-	    {
-	      cgen_bitset_set (info->private_data, ISA_EBPFLE);
-	      if (info->mach == bfd_mach_xbpf)
-		cgen_bitset_set (info->private_data, ISA_XBPFLE);
-	    }
-	}
+      disassemble_init_bpf (info);
       break;
 #endif
 #ifdef ARCH_pru
-- 
2.33.0



More information about the Binutils mailing list