bpf: pseudo-c assembly dialect support
Checks
Commit Message
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(-)
Comments
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)
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
> 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
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.
>
> 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
>> 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 !
@@ -60,4 +60,10 @@ enum bpf_isa_version
ISA_V3,
};
+enum bpf_asm_dialect
+{
+ ASM_NORMAL,
+ ASM_PSEUDOC
+};
+
#endif /* ! BPF_OPTS_H */
@@ -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. */
@@ -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 */
@@ -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")])
@@ -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)