diff --git a/gcc/config/bpf/bpf-opts.h b/gcc/config/bpf/bpf-opts.h
index 8282351cf045..92db01ec4d54 100644
--- a/gcc/config/bpf/bpf-opts.h
+++ b/gcc/config/bpf/bpf-opts.h
@@ -60,4 +60,10 @@ enum bpf_isa_version
   ISA_V3,
 };
 
+enum bpf_asm_dialect
+{
+  ASM_NORMAL,
+  ASM_PSEUDOC
+};
+
 #endif /* ! BPF_OPTS_H */
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index e0324e1e0e08..1d3936871d60 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -873,16 +873,47 @@ bpf_output_call (rtx target)
   return "";
 }
 
+/* Print register name according to assembly dialect.
+   In normal syntax registers are printed like %rN where N is the
+   register number.
+   In pseudoc syntax, the register names do not feature a '%' prefix.
+   Additionally, the code 'w' denotes that the register should be printed
+   as wN instead of rN, where N is the register number, but only when the
+   value stored in the operand OP is 32-bit wide.  */
+static void
+bpf_print_register (FILE *file, rtx op, int code)
+{
+  if(asm_dialect == ASM_NORMAL)
+    fprintf (file, "%s", reg_names[REGNO (op)]);
+  else
+    {
+      if (code == 'w' && GET_MODE (op) == SImode)
+	{
+	  if (REGNO (op) == BPF_FP)
+	    fprintf (file, "w10");
+	  else
+	    fprintf (file, "w%s", reg_names[REGNO (op)]+2);
+	}
+      else
+	{
+	  if (REGNO (op) == BPF_FP)
+	    fprintf (file, "r10");
+	  else
+	    fprintf (file, "%s", reg_names[REGNO (op)]+1);
+	}
+    }
+}
+
 /* Print an instruction operand.  This function is called in the macro
    PRINT_OPERAND defined in bpf.h */
 
 void
-bpf_print_operand (FILE *file, rtx op, int code ATTRIBUTE_UNUSED)
+bpf_print_operand (FILE *file, rtx op, int code)
 {
   switch (GET_CODE (op))
     {
     case REG:
-      fprintf (file, "%s", reg_names[REGNO (op)]);
+      bpf_print_register (file, op, code);
       break;
     case MEM:
       output_address (GET_MODE (op), XEXP (op, 0));
@@ -936,7 +967,9 @@ bpf_print_operand_address (FILE *file, rtx addr)
   switch (GET_CODE (addr))
     {
     case REG:
-      fprintf (file, "[%s+0]", reg_names[REGNO (addr)]);
+      fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+      bpf_print_register (file, addr, 0);
+      fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)");
       break;
     case PLUS:
       {
@@ -945,9 +978,11 @@ bpf_print_operand_address (FILE *file, rtx addr)
 
 	if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
 	  {
-	    fprintf (file, "[%s+", reg_names[REGNO (op0)]);
+	    fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+	    bpf_print_register (file, op0, 0);
+	    fprintf (file, "+");
 	    output_addr_const (file, op1);
-	    fputs ("]", file);
+	    fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")");
 	  }
 	else
 	  fatal_insn ("invalid address in operand", addr);
@@ -1816,7 +1851,6 @@ handle_attr_preserve (function *fn)
     }
 }
 
-
 /* This pass finds accesses to structures marked with the BPF target attribute
    __attribute__((preserve_access_index)). For every such access, a CO-RE
    relocation record is generated, to be output in the .BTF.ext section.  */
diff --git a/gcc/config/bpf/bpf.h b/gcc/config/bpf/bpf.h
index 344aca02d1bb..9561bf59b800 100644
--- a/gcc/config/bpf/bpf.h
+++ b/gcc/config/bpf/bpf.h
@@ -22,7 +22,8 @@
 
 /**** Controlling the Compilation Driver.  */
 
-#define ASM_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL} %{mxbpf:-mxbpf}"
+#define ASM_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL} %{mxbpf:-mxbpf} " \
+  "%{masm=pseudoc:-mdialect=pseudoc}"
 #define LINK_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL}"
 #define LIB_SPEC ""
 #define STARTFILE_SPEC ""
@@ -503,4 +504,6 @@ enum reg_class
 #define DO_GLOBAL_DTORS_BODY			\
   do { } while (0)
 
+#define ASSEMBLER_DIALECT ((int) asm_dialect)
+
 #endif /* ! GCC_BPF_H */
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index f6be0a212345..0b8f409db687 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -77,6 +77,8 @@
 
 (define_mode_attr mop [(QI "b") (HI "h") (SI "w") (DI "dw")
                        (SF "w") (DF "dw")])
+(define_mode_attr smop [(QI "u8") (HI "u16") (SI "u32") (DI "u64")
+                       (SF "u32") (DF "u64")])
 (define_mode_attr mtype [(SI "alu32") (DI "alu")])
 (define_mode_attr msuffix [(SI "32") (DI "")])
 
@@ -110,7 +112,7 @@
         (plus:AM (match_operand:AM 1 "register_operand"   " 0,0")
                  (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
   "1"
-  "add<msuffix>\t%0,%2"
+  "{add<msuffix>\t%0,%2|%w0 += %w1}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Subtraction
@@ -123,15 +125,15 @@
         (minus:AM (match_operand:AM 1 "register_operand" " 0")
                   (match_operand:AM 2 "register_operand" " r")))]
   ""
-  "sub<msuffix>\t%0,%2"
+  "{sub<msuffix>\t%0,%2|%w0 -= %w1}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Negation
 (define_insn "neg<AM:mode>2"
-  [(set (match_operand:AM 0 "register_operand" "=r")
-        (neg:AM (match_operand:AM 1 "register_operand" " 0")))]
+  [(set (match_operand:AM         0 "register_operand"   "=r,r")
+        (neg:AM (match_operand:AM 1 "reg_or_imm_operand" " r,I")))]
   ""
-  "neg<msuffix>\t%0"
+  "{neg<msuffix>\t%0,%1|%w0 = -%w1}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Multiplication
@@ -140,7 +142,7 @@
         (mult:AM (match_operand:AM 1 "register_operand"   " 0,0")
                  (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
   ""
-  "mul<msuffix>\t%0,%2"
+  "{mul<msuffix>\t%0,%2|%w0 *= %w2}"
   [(set_attr "type" "<mtype>")])
 
 (define_insn "*mulsidi3_zeroextend"
@@ -149,7 +151,7 @@
          (mult:SI (match_operand:SI 1 "register_operand" "0,0")
                   (match_operand:SI 2 "reg_or_imm_operand" "r,I"))))]
   ""
-  "mul32\t%0,%2"
+  "{mul32\t%0,%2|%w0 *= %w2}"
   [(set_attr "type" "alu32")])
 
 ;;; Division
@@ -162,7 +164,7 @@
         (udiv:AM (match_operand:AM 1 "register_operand" " 0,0")
                  (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   ""
-  "div<msuffix>\t%0,%2"
+  "{div<msuffix>\t%0,%2|%w0 /= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;; However, xBPF does provide a signed division operator, sdiv.
@@ -172,7 +174,7 @@
         (div:AM (match_operand:AM 1 "register_operand" " 0,0")
                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   "TARGET_XBPF"
-  "sdiv<msuffix>\t%0,%2"
+  "{sdiv<msuffix>\t%0,%2|%w0 s/= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Modulus
@@ -185,7 +187,7 @@
         (umod:AM (match_operand:AM 1 "register_operand" " 0,0")
                  (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   ""
-  "mod<msuffix>\t%0,%2"
+  "{mod<msuffix>\t%0,%2|%w0 %%= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;; Again, xBPF provides a signed version, smod.
@@ -195,7 +197,7 @@
         (mod:AM (match_operand:AM 1 "register_operand" " 0,0")
                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   "TARGET_XBPF"
-  "smod<msuffix>\t%0,%2"
+  "{smod<msuffix>\t%0,%2|%w0 s%%= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Logical AND
@@ -204,7 +206,7 @@
         (and:AM (match_operand:AM 1 "register_operand" " 0,0")
                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   ""
-  "and<msuffix>\t%0,%2"
+  "{and<msuffix>\t%0,%2|%w0 &= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Logical inclusive-OR
@@ -213,7 +215,7 @@
         (ior:AM (match_operand:AM 1 "register_operand" " 0,0")
                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   ""
-  "or<msuffix>\t%0,%2"
+  "{or<msuffix>\t%0,%2|%w0 %|= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;; Logical exclusive-OR
@@ -222,7 +224,7 @@
         (xor:AM (match_operand:AM 1 "register_operand" " 0,0")
                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
   ""
-  "xor<msuffix>\t%0,%2"
+  "{xor<msuffix>\t%0,%2|%w0 ^= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;;; Conversions
@@ -245,9 +247,9 @@
 	(zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "0,r,q")))]
   ""
   "@
-   and\t%0,0xffff
-   mov\t%0,%1\;and\t%0,0xffff
-   ldxh\t%0,%1"
+   {and\t%0,0xffff|%0 &= 0xffff}
+   {mov\t%0,%1\;and\t%0,0xffff|%0 = %1;%0 &= 0xffff}
+   {ldxh\t%0,%1|%0 = *(u16 *) %1}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendqidi2"
@@ -255,9 +257,9 @@
 	(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "0,r,q")))]
   ""
   "@
-   and\t%0,0xff
-   mov\t%0,%1\;and\t%0,0xff
-   ldxb\t%0,%1"
+   {and\t%0,0xff|%0 &= 0xff}
+   {mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
+   {ldxh\t%0,%1|%0 = *(u8 *) %1}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendsidi2"
@@ -266,8 +268,8 @@
 	  (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
   ""
   "@
-   * return bpf_has_alu32 ? \"mov32\t%0,%1\" : \"mov\t%0,%1\;and\t%0,0xffffffff\";
-   ldxw\t%0,%1"
+   * return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : \"{mov\t%0,%1\;and\t%0,0xffffffff|%0 = %1;%0 &= 0xffffffff}\";
+   {ldxw\t%0,%1|%0 = *(u32 *) %1}"
   [(set_attr "type" "alu,ldx")])
 
 ;;; Sign-extension
@@ -306,11 +308,11 @@
         (match_operand:MM 1 "mov_src_operand"      " q,rI,B,r,I"))]
   ""
   "@
-   ldx<mop>\t%0,%1
-   mov\t%0,%1
-   lddw\t%0,%1
-   stx<mop>\t%0,%1
-   st<mop>\t%0,%1"
+   {ldx<mop>\t%0,%1|%0 = *(<smop> *) %1}
+   {mov\t%0,%1|%0 = %1}
+   {lddw\t%0,%1|%0 = %1 ll}
+   {stx<mop>\t%0,%1|*(<smop> *) %0 = %1}
+   {st<mop>\t%0,%1|*(<smop> *) %0 = %1}"
 [(set_attr "type" "ldx,alu,alu,stx,st")])
 
 ;;;; Shifts
@@ -322,7 +324,7 @@
         (ashiftrt:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
                       (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
   ""
-  "arsh<msuffix>\t%0,%2"
+  "{arsh<msuffix>\t%0,%2|%w0 s>>= %w2}"
   [(set_attr "type" "<mtype>")])
 
 (define_insn "ashl<SIM:mode>3"
@@ -330,7 +332,7 @@
         (ashift:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
                     (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
   ""
-  "lsh<msuffix>\t%0,%2"
+  "{lsh<msuffix>\t%0,%2|%w0 <<= %w2}"
   [(set_attr "type" "<mtype>")])
 
 (define_insn "lshr<SIM:mode>3"
@@ -338,7 +340,7 @@
         (lshiftrt:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
                       (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
   ""
-  "rsh<msuffix>\t%0,%2"
+  "{rsh<msuffix>\t%0,%2|%w0 >>= %w2}"
   [(set_attr "type" "<mtype>")])
 
 ;;;; Endianness conversion
@@ -352,9 +354,9 @@
   ""
 {
   if (TARGET_BIG_ENDIAN)
-    return "endle\t%0, <endmode>";
+    return "{endle\t%0, <endmode>|%0 = le<endmode> %0}";
   else
-    return "endbe\t%0, <endmode>";
+    return "{endbe\t%0, <endmode>|%0 = be<endmode> %0}";
 }
   [(set_attr "type" "end")])
 
@@ -393,16 +395,16 @@
 
   switch (code)
   {
-  case EQ: return "jeq<msuffix>\t%0,%1,%2"; break;
-  case NE: return "jne<msuffix>\t%0,%1,%2"; break;
-  case LT: return "jslt<msuffix>\t%0,%1,%2"; break;
-  case LE: return "jsle<msuffix>\t%0,%1,%2"; break;
-  case GT: return "jsgt<msuffix>\t%0,%1,%2"; break;
-  case GE: return "jsge<msuffix>\t%0,%1,%2"; break;
-  case LTU: return "jlt<msuffix>\t%0,%1,%2"; break;
-  case LEU: return "jle<msuffix>\t%0,%1,%2"; break;
-  case GTU: return "jgt<msuffix>\t%0,%1,%2"; break;
-  case GEU: return "jge<msuffix>\t%0,%1,%2"; break;
+  case EQ: return  "{jeq<msuffix>\t%0,%1,%2|if %w0 == %w1 goto %2}"; break;
+  case NE: return  "{jne<msuffix>\t%0,%1,%2|if %w0 != %w1 goto %2}"; break;
+  case LT: return  "{jslt<msuffix>\t%0,%1,%2|if %w0 s< %w1 goto %2}"; break;
+  case LE: return  "{jsle<msuffix>\t%0,%1,%2|if %w0 s<= %w1 goto %2}"; break;
+  case GT: return  "{jsgt<msuffix>\t%0,%1,%2|if %w0 s> %w1 goto %2}"; break;
+  case GE: return  "{jsge<msuffix>\t%0,%1,%2|if %w0 s>= %w1 goto %2}"; break;
+  case LTU: return "{jlt<msuffix>\t%0,%1,%2|if %w0 < %w1 goto %2}"; break;
+  case LEU: return "{jle<msuffix>\t%0,%1,%2|if %w0 <= %w1 goto %2}"; break;
+  case GTU: return "{jgt<msuffix>\t%0,%1,%2|if %w0 > %w1 goto %2}"; break;
+  case GEU: return "{jge<msuffix>\t%0,%1,%2|if %w0 >= %w1 goto %2}"; break;
   default:
     gcc_unreachable ();
     return "";
@@ -416,7 +418,7 @@
   [(set (pc)
         (label_ref (match_operand 0 "" "")))]
   ""
-  "ja\t%0"
+  "{ja\t%0|goto %0}"
 [(set_attr "type" "jmp")])
 
 ;;;; Function prologue/epilogue
@@ -495,13 +497,14 @@
   ;; operands[2] is next_arg_register
   ;; operands[3] is struct_value_size_rtx.
   ""
-  "ja\t%0"
+  "{ja\t%0|goto %0}"
   [(set_attr "type" "jmp")])
 
 ;;;; Non-generic load instructions
 
 (define_mode_iterator LDM [QI HI SI DI])
 (define_mode_attr ldop [(QI "b") (HI "h") (SI "w") (DI "dw")])
+(define_mode_attr pldop [(QI "u8") (HI "u16") (SI "u32") (DI "u64")])
 
 (define_insn "ldind<ldop>"
   [(set (reg:LDM R0_REGNUM)
@@ -513,7 +516,7 @@
    (clobber (reg:DI R3_REGNUM))
    (clobber (reg:DI R4_REGNUM))]
   ""
-  "ldind<ldop>\t%0,%1"
+  "{ldind<ldop>\t%0,%1|r0 = *(<pldop> *) skb[%0 + %1]}"
   [(set_attr "type" "ld")])
 
 (define_insn "ldabs<ldop>"
@@ -526,7 +529,7 @@
    (clobber (reg:DI R3_REGNUM))
    (clobber (reg:DI R4_REGNUM))]
   ""
-  "ldabs<ldop>\t%0"
+  "{ldabs<ldop>\t%0|r0 = *(<pldop> *) skb[%0]}"
   [(set_attr "type" "ld")])
 
 ;;;; Atomic increments
@@ -541,5 +544,5 @@
           (match_operand:SI 2 "const_int_operand")] ;; Memory model.
          UNSPEC_XADD))]
   ""
-  "xadd<mop>\t%0,%1"
+  "{xadd<mop>\t%0,%1|*(<smop> *) %0 += %1}"
   [(set_attr "type" "xadd")])
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index fe3ad355e4bd..ff805f9e083c 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -160,3 +160,17 @@ Enum(bpf_isa) String(v2) Value(ISA_V2)
 
 EnumValue
 Enum(bpf_isa) String(v3) Value(ISA_V3)
+
+masm=
+Target RejectNegative Joined Var(asm_dialect) Enum(asm_dialect) Init(ASM_NORMAL)
+Use given assembler dialect.
+
+Enum
+Name(asm_dialect) Type(enum bpf_asm_dialect)
+Known assembler dialects (for use with the -masm= option)
+
+EnumValue
+Enum(asm_dialect) String(normal) Value(ASM_NORMAL)
+
+EnumValue
+Enum(asm_dialect) String(pseudoc) Value(ASM_PSEUDOC)
