Message ID | 20230721114835.23667-1-cupertino.miranda@oracle.com |
---|---|
State | New |
Headers | show |
Series | bpf: pseudo-c assembly dialect support | expand |
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 !
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)