public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] bpf: pseudo-c assembly dialect support
@ 2023-07-21 11:48 Cupertino Miranda
  2023-07-21 13:09 ` Jose E. Marchesi
  0 siblings, 1 reply; 7+ messages in thread
From: Cupertino Miranda @ 2023-07-21 11:48 UTC (permalink / raw)
  To: gcc-patches; +Cc: elena.zannoni, jose.marchesi, david.faust, Cupertino Miranda

Hi everyone,

Looking forward to all your reviews.

Best regards,
Cupertino

New pseudo-c BPF assembly dialect already supported by clang and widely
used in the linux kernel.

gcc/ChangeLog:

	* config/bpf/bpf.opt: Added option -masm=<dialect>.
	* config/bpf/bpf-opts.h: Likewize.
	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
	  dialect support.
	* config/bpf/bpf.h: Likewise.
	* config/bpf/bpf.md: Added pseudo-c templates.
---
 gcc/config/bpf/bpf-opts.h |  6 +++
 gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
 gcc/config/bpf/bpf.h      |  5 +-
 gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
 gcc/config/bpf/bpf.opt    | 14 ++++++
 5 files changed, 114 insertions(+), 54 deletions(-)

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)
-- 
2.30.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] bpf: pseudo-c assembly dialect support
  2023-07-21 11:48 [PATCH] bpf: pseudo-c assembly dialect support Cupertino Miranda
@ 2023-07-21 13:09 ` Jose E. Marchesi
  2023-07-21 14:05   ` [PATCH v2] " Cupertino Miranda
  0 siblings, 1 reply; 7+ messages in thread
From: Jose E. Marchesi @ 2023-07-21 13:09 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, elena.zannoni, david.faust


Hello Cuper.

Thanks for the patch.

We will need an update for the "eBPF Options" section in the GCC manual,
documenting -masm=@var{dialect} and the supported values.  Can you
please add it and re-submit?


> Hi everyone,
>
> Looking forward to all your reviews.
>
> Best regards,
> Cupertino
>
> New pseudo-c BPF assembly dialect already supported by clang and widely
> used in the linux kernel.
>
> gcc/ChangeLog:
>
> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
> 	* config/bpf/bpf-opts.h: Likewize.
> 	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
> 	  dialect support.
> 	* config/bpf/bpf.h: Likewise.
> 	* config/bpf/bpf.md: Added pseudo-c templates.
> ---
>  gcc/config/bpf/bpf-opts.h |  6 +++
>  gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
>  gcc/config/bpf/bpf.h      |  5 +-
>  gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
>  gcc/config/bpf/bpf.opt    | 14 ++++++
>  5 files changed, 114 insertions(+), 54 deletions(-)
>
> 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)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] bpf: pseudo-c assembly dialect support
  2023-07-21 13:09 ` Jose E. Marchesi
@ 2023-07-21 14:05   ` Cupertino Miranda
  2023-07-21 14:19     ` Jose E. Marchesi
  0 siblings, 1 reply; 7+ messages in thread
From: Cupertino Miranda @ 2023-07-21 14:05 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: gcc-patches, elena.zannoni, david.faust

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]


Hi Jose,

Thanks for the review.
New patch is inline attached.

Regards,
Cupertino

Jose E. Marchesi writes:

> Hello Cuper.
>
> Thanks for the patch.
>
> We will need an update for the "eBPF Options" section in the GCC manual,
> documenting -masm=@var{dialect} and the supported values.  Can you
> please add it and re-submit?
>
>
>> Hi everyone,
>>
>> Looking forward to all your reviews.
>>
>> Best regards,
>> Cupertino



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v2-0001-bpf-pseudo-c-assembly-dialect-support.patch --]
[-- Type: text/x-diff, Size: 16094 bytes --]

From fa227fefd84e6eaaf8edafed698e9960d7b115e6 Mon Sep 17 00:00:00 2001
From: Cupertino Miranda <cupertino.miranda@oracle.com>
Date: Mon, 17 Jul 2023 17:42:42 +0100
Subject: [PATCH v2] bpf: pseudo-c assembly dialect support

New pseudo-c BPF assembly dialect already supported by clang and widely
used in the linux kernel.

gcc/ChangeLog:

	* config/bpf/bpf.opt: Added option -masm=<dialect>.
	* config/bpf/bpf-opts.h: Likewize.
	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
	  dialect support.
	* config/bpf/bpf.h: Likewise.
	* config/bpf/bpf.md: Added pseudo-c templates.
	* doc/invoke.texi: (-masm=DIALECT) New eBPF option item.
---
 gcc/config/bpf/bpf-opts.h |  6 +++
 gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
 gcc/config/bpf/bpf.h      |  5 +-
 gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
 gcc/config/bpf/bpf.opt    | 14 ++++++
 gcc/doc/invoke.texi       | 21 ++++++++-
 6 files changed, 133 insertions(+), 56 deletions(-)

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)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3063e71c8906..b3be65d3efae 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{eBPF Options}
 @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
--mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
--mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
+-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
+-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}}
 
 @emph{FR30 Options}
 @gccoptlist{-msmall-model  -mno-lsim}
@@ -24736,6 +24736,23 @@ the restrictions imposed by the BPF architecture:
 @item Save and restore callee-saved registers at function entry and
 exit, respectively.
 @end itemize
+
+@opindex masm=@var{dialect}
+@item -masm=@var{dialect}
+Outputs assembly instructions using eBPF selected @var{dialect}.  The default
+is @samp{normal}.
+
+Supported values for @var{dialect} are:
+
+@table @samp
+@item normal
+Outputs normal assembly dialect.
+
+@item pseudoc
+Outputs pseudo-c assembly dialect.
+
+@end table
+
 @end table
 
 @node FR30 Options
-- 
2.38.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] bpf: pseudo-c assembly dialect support
  2023-07-21 14:05   ` [PATCH v2] " Cupertino Miranda
@ 2023-07-21 14:19     ` Jose E. Marchesi
  2023-07-21 14:56       ` [PATCH v3] " Cupertino Miranda
  0 siblings, 1 reply; 7+ messages in thread
From: Jose E. Marchesi @ 2023-07-21 14:19 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, elena.zannoni, david.faust


> gcc/ChangeLog:
>
> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
> 	* config/bpf/bpf-opts.h: Likewize.
> 	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
> 	  dialect support.
> 	* config/bpf/bpf.h: Likewise.
> 	* config/bpf/bpf.md: Added pseudo-c templates.
> 	* doc/invoke.texi: (-masm=DIALECT) New eBPF option item.

I think the ChangeLog could be made more useful, and the syntax of the
last entry is not entirely right.  I suggest something like:

	* config/bpf/bpf.opt: Added option -masm=<dialect>.
	* config/bpf/bpf-opts.h (enum bpf_asm_dialect): New type.
	* config/bpf/bpf.cc (bpf_print_register): New function.
	(bpf_print_register): Support pseudo-c syntax for registers.
	(bpf_print_operand_address): Likewise.
	* config/bpf/bpf.h (ASM_SPEC): handle -msasm.
	(ASSEMBLER_DIALECT): Define.
	* config/bpf/bpf.md: Added pseudo-c templates.
	* doc/invoke.texi (-masm=DIALECT): New eBPF option item.

Please make sure to run the contrib/gcc-changelog/git_check-commit.py
script.

> ---
>  gcc/config/bpf/bpf-opts.h |  6 +++
>  gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
>  gcc/config/bpf/bpf.h      |  5 +-
>  gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
>  gcc/config/bpf/bpf.opt    | 14 ++++++
>  gcc/doc/invoke.texi       | 21 ++++++++-
>  6 files changed, 133 insertions(+), 56 deletions(-)
>
> 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)
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 3063e71c8906..b3be65d3efae 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}.
>  
>  @emph{eBPF Options}
>  @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
> --mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
> --mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
> +-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
> +-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}}
>  
>  @emph{FR30 Options}
>  @gccoptlist{-msmall-model  -mno-lsim}
> @@ -24736,6 +24736,23 @@ the restrictions imposed by the BPF architecture:
>  @item Save and restore callee-saved registers at function entry and
>  exit, respectively.
>  @end itemize
> +
> +@opindex masm=@var{dialect}
> +@item -masm=@var{dialect}
> +Outputs assembly instructions using eBPF selected @var{dialect}.  The default
> +is @samp{normal}.
> +
> +Supported values for @var{dialect} are:
> +
> +@table @samp
> +@item normal
> +Outputs normal assembly dialect.
> +
> +@item pseudoc
> +Outputs pseudo-c assembly dialect.
> +
> +@end table
> +
>  @end table
>  
>  @node FR30 Options

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] bpf: pseudo-c assembly dialect support
  2023-07-21 14:19     ` Jose E. Marchesi
@ 2023-07-21 14:56       ` Cupertino Miranda
  2023-07-21 15:10         ` Jose E. Marchesi
  0 siblings, 1 reply; 7+ messages in thread
From: Cupertino Miranda @ 2023-07-21 14:56 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: gcc-patches, elena.zannoni, david.faust

[-- Attachment #1: Type: text/plain, Size: 1127 bytes --]


Thanks for the suggestions/fixes in changelog.
Inlined new patch.

Cupertino

>> gcc/ChangeLog:
>>
>> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
>> 	* config/bpf/bpf-opts.h: Likewize.
>> 	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
>> 	  dialect support.
>> 	* config/bpf/bpf.h: Likewise.
>> 	* config/bpf/bpf.md: Added pseudo-c templates.
>> 	* doc/invoke.texi: (-masm=DIALECT) New eBPF option item.
>
> I think the ChangeLog could be made more useful, and the syntax of the
> last entry is not entirely right.  I suggest something like:
>
> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
> 	* config/bpf/bpf-opts.h (enum bpf_asm_dialect): New type.
> 	* config/bpf/bpf.cc (bpf_print_register): New function.
> 	(bpf_print_register): Support pseudo-c syntax for registers.
> 	(bpf_print_operand_address): Likewise.
> 	* config/bpf/bpf.h (ASM_SPEC): handle -msasm.
> 	(ASSEMBLER_DIALECT): Define.
> 	* config/bpf/bpf.md: Added pseudo-c templates.
> 	* doc/invoke.texi (-masm=DIALECT): New eBPF option item.
>
> Please make sure to run the contrib/gcc-changelog/git_check-commit.py
> script.
>


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3-0001-bpf-pseudo-c-assembly-dialect-support.patch --]
[-- Type: text/x-diff, Size: 16234 bytes --]

From 6ebe3229a59b32ffb2ed24b3a2cf8c360a807c31 Mon Sep 17 00:00:00 2001
From: Cupertino Miranda <cupertino.miranda@oracle.com>
Date: Mon, 17 Jul 2023 17:42:42 +0100
Subject: [PATCH v3] bpf: pseudo-c assembly dialect support

New pseudo-c BPF assembly dialect already supported by clang and widely
used in the linux kernel.

gcc/ChangeLog:

	* config/bpf/bpf.opt: Added option -masm=<dialect>.
	* config/bpf/bpf-opts.h (enum bpf_asm_dialect): New type.
	* config/bpf/bpf.cc (bpf_print_register): New function.
	(bpf_print_register): Support pseudo-c syntax for registers.
	(bpf_print_operand_address): Likewise.
	* config/bpf/bpf.h (ASM_SPEC): handle -msasm.
	(ASSEMBLER_DIALECT): Define.
	* config/bpf/bpf.md: Added pseudo-c templates.
	* doc/invoke.texi (-masm=): New eBPF option item.
---
 gcc/config/bpf/bpf-opts.h |  6 +++
 gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
 gcc/config/bpf/bpf.h      |  5 +-
 gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
 gcc/config/bpf/bpf.opt    | 14 ++++++
 gcc/doc/invoke.texi       | 21 ++++++++-
 6 files changed, 133 insertions(+), 56 deletions(-)

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)
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3063e71c8906..b3be65d3efae 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}.
 
 @emph{eBPF Options}
 @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
--mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
--mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
+-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
+-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}}
 
 @emph{FR30 Options}
 @gccoptlist{-msmall-model  -mno-lsim}
@@ -24736,6 +24736,23 @@ the restrictions imposed by the BPF architecture:
 @item Save and restore callee-saved registers at function entry and
 exit, respectively.
 @end itemize
+
+@opindex masm=@var{dialect}
+@item -masm=@var{dialect}
+Outputs assembly instructions using eBPF selected @var{dialect}.  The default
+is @samp{normal}.
+
+Supported values for @var{dialect} are:
+
+@table @samp
+@item normal
+Outputs normal assembly dialect.
+
+@item pseudoc
+Outputs pseudo-c assembly dialect.
+
+@end table
+
 @end table
 
 @node FR30 Options
-- 
2.38.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] bpf: pseudo-c assembly dialect support
  2023-07-21 14:56       ` [PATCH v3] " Cupertino Miranda
@ 2023-07-21 15:10         ` Jose E. Marchesi
  2023-07-21 19:06           ` Cupertino Miranda
  0 siblings, 1 reply; 7+ messages in thread
From: Jose E. Marchesi @ 2023-07-21 15:10 UTC (permalink / raw)
  To: Cupertino Miranda; +Cc: gcc-patches, elena.zannoni, david.faust


> Thanks for the suggestions/fixes in changelog.
> Inlined new patch.
>
> Cupertino
>
>>> gcc/ChangeLog:
>>>
>>> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
>>> 	* config/bpf/bpf-opts.h: Likewize.
>>> 	* config/bpf/bpf.cc: Changed it to conform with new pseudoc
>>> 	  dialect support.
>>> 	* config/bpf/bpf.h: Likewise.
>>> 	* config/bpf/bpf.md: Added pseudo-c templates.
>>> 	* doc/invoke.texi: (-masm=DIALECT) New eBPF option item.
>>
>> I think the ChangeLog could be made more useful, and the syntax of the
>> last entry is not entirely right.  I suggest something like:
>>
>> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
>> 	* config/bpf/bpf-opts.h (enum bpf_asm_dialect): New type.
>> 	* config/bpf/bpf.cc (bpf_print_register): New function.
>> 	(bpf_print_register): Support pseudo-c syntax for registers.
>> 	(bpf_print_operand_address): Likewise.
>> 	* config/bpf/bpf.h (ASM_SPEC): handle -msasm.
>> 	(ASSEMBLER_DIALECT): Define.
>> 	* config/bpf/bpf.md: Added pseudo-c templates.
>> 	* doc/invoke.texi (-masm=DIALECT): New eBPF option item.
>>
>> Please make sure to run the contrib/gcc-changelog/git_check-commit.py
>> script.
>>
>
> From 6ebe3229a59b32ffb2ed24b3a2cf8c360a807c31 Mon Sep 17 00:00:00 2001
> From: Cupertino Miranda <cupertino.miranda@oracle.com>
> Date: Mon, 17 Jul 2023 17:42:42 +0100
> Subject: [PATCH v3] bpf: pseudo-c assembly dialect support
>
> New pseudo-c BPF assembly dialect already supported by clang and widely
> used in the linux kernel.
>
> gcc/ChangeLog:
>
> 	* config/bpf/bpf.opt: Added option -masm=<dialect>.
> 	* config/bpf/bpf-opts.h (enum bpf_asm_dialect): New type.
> 	* config/bpf/bpf.cc (bpf_print_register): New function.
> 	(bpf_print_register): Support pseudo-c syntax for registers.
> 	(bpf_print_operand_address): Likewise.
> 	* config/bpf/bpf.h (ASM_SPEC): handle -msasm.
> 	(ASSEMBLER_DIALECT): Define.
> 	* config/bpf/bpf.md: Added pseudo-c templates.
> 	* doc/invoke.texi (-masm=): New eBPF option item.
> ---
>  gcc/config/bpf/bpf-opts.h |  6 +++
>  gcc/config/bpf/bpf.cc     | 46 ++++++++++++++++---
>  gcc/config/bpf/bpf.h      |  5 +-
>  gcc/config/bpf/bpf.md     | 97 ++++++++++++++++++++-------------------
>  gcc/config/bpf/bpf.opt    | 14 ++++++
>  gcc/doc/invoke.texi       | 21 ++++++++-
>  6 files changed, 133 insertions(+), 56 deletions(-)
>
> 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)
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 3063e71c8906..b3be65d3efae 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}.
>  
>  @emph{eBPF Options}
>  @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
> --mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
> --mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
> +-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
> +-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}}

There is a spurious > character there.

Other than that, the patch is OK.
Thanks!

>  
>  @emph{FR30 Options}
>  @gccoptlist{-msmall-model  -mno-lsim}
> @@ -24736,6 +24736,23 @@ the restrictions imposed by the BPF architecture:
>  @item Save and restore callee-saved registers at function entry and
>  exit, respectively.
>  @end itemize
> +
> +@opindex masm=@var{dialect}
> +@item -masm=@var{dialect}
> +Outputs assembly instructions using eBPF selected @var{dialect}.  The default
> +is @samp{normal}.
> +
> +Supported values for @var{dialect} are:
> +
> +@table @samp
> +@item normal
> +Outputs normal assembly dialect.
> +
> +@item pseudoc
> +Outputs pseudo-c assembly dialect.
> +
> +@end table
> +
>  @end table
>  
>  @node FR30 Options

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3] bpf: pseudo-c assembly dialect support
  2023-07-21 15:10         ` Jose E. Marchesi
@ 2023-07-21 19:06           ` Cupertino Miranda
  0 siblings, 0 replies; 7+ messages in thread
From: Cupertino Miranda @ 2023-07-21 19:06 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: gcc-patches, elena.zannoni, david.faust



>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index 3063e71c8906..b3be65d3efae 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}.
>>
>>  @emph{eBPF Options}
>>  @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
>> --mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re
>> --mjmpext -mjmp32 -malu32 -mcpu=@var{version}}
>> +-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
>> +-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}}
>
> There is a spurious > character there.
>
> Other than that, the patch is OK.
> Thanks!

Fixed the extra character and committed.
Thanks !

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-07-21 19:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-21 11:48 [PATCH] bpf: pseudo-c assembly dialect support Cupertino Miranda
2023-07-21 13:09 ` Jose E. Marchesi
2023-07-21 14:05   ` [PATCH v2] " Cupertino Miranda
2023-07-21 14:19     ` Jose E. Marchesi
2023-07-21 14:56       ` [PATCH v3] " Cupertino Miranda
2023-07-21 15:10         ` Jose E. Marchesi
2023-07-21 19:06           ` Cupertino Miranda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).