From fa227fefd84e6eaaf8edafed698e9960d7b115e6 Mon Sep 17 00:00:00 2001 From: Cupertino Miranda Date: Mon, 17 Jul 2023 17:42:42 +0100 Subject: [PATCH v2] bpf: pseudo-c assembly dialect support New pseudo-c BPF assembly dialect already supported by clang and widely used in the linux kernel. gcc/ChangeLog: * config/bpf/bpf.opt: Added option -masm=. * config/bpf/bpf-opts.h: Likewize. * config/bpf/bpf.cc: Changed it to conform with new pseudoc dialect support. * config/bpf/bpf.h: Likewise. * config/bpf/bpf.md: Added pseudo-c templates. * doc/invoke.texi: (-masm=DIALECT) New eBPF option item. --- gcc/config/bpf/bpf-opts.h | 6 +++ gcc/config/bpf/bpf.cc | 46 ++++++++++++++++--- gcc/config/bpf/bpf.h | 5 +- gcc/config/bpf/bpf.md | 97 ++++++++++++++++++++------------------- gcc/config/bpf/bpf.opt | 14 ++++++ gcc/doc/invoke.texi | 21 ++++++++- 6 files changed, 133 insertions(+), 56 deletions(-) diff --git a/gcc/config/bpf/bpf-opts.h b/gcc/config/bpf/bpf-opts.h index 8282351cf045..92db01ec4d54 100644 --- a/gcc/config/bpf/bpf-opts.h +++ b/gcc/config/bpf/bpf-opts.h @@ -60,4 +60,10 @@ enum bpf_isa_version ISA_V3, }; +enum bpf_asm_dialect +{ + ASM_NORMAL, + ASM_PSEUDOC +}; + #endif /* ! BPF_OPTS_H */ diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc index e0324e1e0e08..1d3936871d60 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -873,16 +873,47 @@ bpf_output_call (rtx target) return ""; } +/* Print register name according to assembly dialect. + In normal syntax registers are printed like %rN where N is the + register number. + In pseudoc syntax, the register names do not feature a '%' prefix. + Additionally, the code 'w' denotes that the register should be printed + as wN instead of rN, where N is the register number, but only when the + value stored in the operand OP is 32-bit wide. */ +static void +bpf_print_register (FILE *file, rtx op, int code) +{ + if(asm_dialect == ASM_NORMAL) + fprintf (file, "%s", reg_names[REGNO (op)]); + else + { + if (code == 'w' && GET_MODE (op) == SImode) + { + if (REGNO (op) == BPF_FP) + fprintf (file, "w10"); + else + fprintf (file, "w%s", reg_names[REGNO (op)]+2); + } + else + { + if (REGNO (op) == BPF_FP) + fprintf (file, "r10"); + else + fprintf (file, "%s", reg_names[REGNO (op)]+1); + } + } +} + /* Print an instruction operand. This function is called in the macro PRINT_OPERAND defined in bpf.h */ void -bpf_print_operand (FILE *file, rtx op, int code ATTRIBUTE_UNUSED) +bpf_print_operand (FILE *file, rtx op, int code) { switch (GET_CODE (op)) { case REG: - fprintf (file, "%s", reg_names[REGNO (op)]); + bpf_print_register (file, op, code); break; case MEM: output_address (GET_MODE (op), XEXP (op, 0)); @@ -936,7 +967,9 @@ bpf_print_operand_address (FILE *file, rtx addr) switch (GET_CODE (addr)) { case REG: - fprintf (file, "[%s+0]", reg_names[REGNO (addr)]); + fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "("); + bpf_print_register (file, addr, 0); + fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)"); break; case PLUS: { @@ -945,9 +978,11 @@ bpf_print_operand_address (FILE *file, rtx addr) if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT) { - fprintf (file, "[%s+", reg_names[REGNO (op0)]); + fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "("); + bpf_print_register (file, op0, 0); + fprintf (file, "+"); output_addr_const (file, op1); - fputs ("]", file); + fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")"); } else fatal_insn ("invalid address in operand", addr); @@ -1816,7 +1851,6 @@ handle_attr_preserve (function *fn) } } - /* This pass finds accesses to structures marked with the BPF target attribute __attribute__((preserve_access_index)). For every such access, a CO-RE relocation record is generated, to be output in the .BTF.ext section. */ diff --git a/gcc/config/bpf/bpf.h b/gcc/config/bpf/bpf.h index 344aca02d1bb..9561bf59b800 100644 --- a/gcc/config/bpf/bpf.h +++ b/gcc/config/bpf/bpf.h @@ -22,7 +22,8 @@ /**** Controlling the Compilation Driver. */ -#define ASM_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL} %{mxbpf:-mxbpf}" +#define ASM_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL} %{mxbpf:-mxbpf} " \ + "%{masm=pseudoc:-mdialect=pseudoc}" #define LINK_SPEC "%{mbig-endian:-EB} %{!mbig-endian:-EL}" #define LIB_SPEC "" #define STARTFILE_SPEC "" @@ -503,4 +504,6 @@ enum reg_class #define DO_GLOBAL_DTORS_BODY \ do { } while (0) +#define ASSEMBLER_DIALECT ((int) asm_dialect) + #endif /* ! GCC_BPF_H */ diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md index f6be0a212345..0b8f409db687 100644 --- a/gcc/config/bpf/bpf.md +++ b/gcc/config/bpf/bpf.md @@ -77,6 +77,8 @@ (define_mode_attr mop [(QI "b") (HI "h") (SI "w") (DI "dw") (SF "w") (DF "dw")]) +(define_mode_attr smop [(QI "u8") (HI "u16") (SI "u32") (DI "u64") + (SF "u32") (DF "u64")]) (define_mode_attr mtype [(SI "alu32") (DI "alu")]) (define_mode_attr msuffix [(SI "32") (DI "")]) @@ -110,7 +112,7 @@ (plus:AM (match_operand:AM 1 "register_operand" " 0,0") (match_operand:AM 2 "reg_or_imm_operand" " r,I")))] "1" - "add\t%0,%2" + "{add\t%0,%2|%w0 += %w1}" [(set_attr "type" "")]) ;;; Subtraction @@ -123,15 +125,15 @@ (minus:AM (match_operand:AM 1 "register_operand" " 0") (match_operand:AM 2 "register_operand" " r")))] "" - "sub\t%0,%2" + "{sub\t%0,%2|%w0 -= %w1}" [(set_attr "type" "")]) ;;; Negation (define_insn "neg2" - [(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\t%0" + "{neg\t%0,%1|%w0 = -%w1}" [(set_attr "type" "")]) ;;; 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\t%0,%2" + "{mul\t%0,%2|%w0 *= %w2}" [(set_attr "type" "")]) (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\t%0,%2" + "{div\t%0,%2|%w0 /= %w2}" [(set_attr "type" "")]) ;; 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\t%0,%2" + "{sdiv\t%0,%2|%w0 s/= %w2}" [(set_attr "type" "")]) ;;; 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\t%0,%2" + "{mod\t%0,%2|%w0 %%= %w2}" [(set_attr "type" "")]) ;; 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\t%0,%2" + "{smod\t%0,%2|%w0 s%%= %w2}" [(set_attr "type" "")]) ;;; 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\t%0,%2" + "{and\t%0,%2|%w0 &= %w2}" [(set_attr "type" "")]) ;;; 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\t%0,%2" + "{or\t%0,%2|%w0 %|= %w2}" [(set_attr "type" "")]) ;;; 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\t%0,%2" + "{xor\t%0,%2|%w0 ^= %w2}" [(set_attr "type" "")]) ;;;; 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\t%0,%1 - mov\t%0,%1 - lddw\t%0,%1 - stx\t%0,%1 - st\t%0,%1" + {ldx\t%0,%1|%0 = *( *) %1} + {mov\t%0,%1|%0 = %1} + {lddw\t%0,%1|%0 = %1 ll} + {stx\t%0,%1|*( *) %0 = %1} + {st\t%0,%1|*( *) %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\t%0,%2" + "{arsh\t%0,%2|%w0 s>>= %w2}" [(set_attr "type" "")]) (define_insn "ashl3" @@ -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\t%0,%2" + "{lsh\t%0,%2|%w0 <<= %w2}" [(set_attr "type" "")]) (define_insn "lshr3" @@ -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\t%0,%2" + "{rsh\t%0,%2|%w0 >>= %w2}" [(set_attr "type" "")]) ;;;; Endianness conversion @@ -352,9 +354,9 @@ "" { if (TARGET_BIG_ENDIAN) - return "endle\t%0, "; + return "{endle\t%0, |%0 = le %0}"; else - return "endbe\t%0, "; + return "{endbe\t%0, |%0 = be %0}"; } [(set_attr "type" "end")]) @@ -393,16 +395,16 @@ switch (code) { - case EQ: return "jeq\t%0,%1,%2"; break; - case NE: return "jne\t%0,%1,%2"; break; - case LT: return "jslt\t%0,%1,%2"; break; - case LE: return "jsle\t%0,%1,%2"; break; - case GT: return "jsgt\t%0,%1,%2"; break; - case GE: return "jsge\t%0,%1,%2"; break; - case LTU: return "jlt\t%0,%1,%2"; break; - case LEU: return "jle\t%0,%1,%2"; break; - case GTU: return "jgt\t%0,%1,%2"; break; - case GEU: return "jge\t%0,%1,%2"; break; + case EQ: return "{jeq\t%0,%1,%2|if %w0 == %w1 goto %2}"; break; + case NE: return "{jne\t%0,%1,%2|if %w0 != %w1 goto %2}"; break; + case LT: return "{jslt\t%0,%1,%2|if %w0 s< %w1 goto %2}"; break; + case LE: return "{jsle\t%0,%1,%2|if %w0 s<= %w1 goto %2}"; break; + case GT: return "{jsgt\t%0,%1,%2|if %w0 s> %w1 goto %2}"; break; + case GE: return "{jsge\t%0,%1,%2|if %w0 s>= %w1 goto %2}"; break; + case LTU: return "{jlt\t%0,%1,%2|if %w0 < %w1 goto %2}"; break; + case LEU: return "{jle\t%0,%1,%2|if %w0 <= %w1 goto %2}"; break; + case GTU: return "{jgt\t%0,%1,%2|if %w0 > %w1 goto %2}"; break; + case GEU: return "{jge\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" [(set (reg:LDM R0_REGNUM) @@ -513,7 +516,7 @@ (clobber (reg:DI R3_REGNUM)) (clobber (reg:DI R4_REGNUM))] "" - "ldind\t%0,%1" + "{ldind\t%0,%1|r0 = *( *) skb[%0 + %1]}" [(set_attr "type" "ld")]) (define_insn "ldabs" @@ -526,7 +529,7 @@ (clobber (reg:DI R3_REGNUM)) (clobber (reg:DI R4_REGNUM))] "" - "ldabs\t%0" + "{ldabs\t%0|r0 = *( *) skb[%0]}" [(set_attr "type" "ld")]) ;;;; Atomic increments @@ -541,5 +544,5 @@ (match_operand:SI 2 "const_int_operand")] ;; Memory model. UNSPEC_XADD))] "" - "xadd\t%0,%1" + "{xadd\t%0,%1|*( *) %0 += %1}" [(set_attr "type" "xadd")]) diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt index fe3ad355e4bd..ff805f9e083c 100644 --- a/gcc/config/bpf/bpf.opt +++ b/gcc/config/bpf/bpf.opt @@ -160,3 +160,17 @@ Enum(bpf_isa) String(v2) Value(ISA_V2) EnumValue Enum(bpf_isa) String(v3) Value(ISA_V3) + +masm= +Target RejectNegative Joined Var(asm_dialect) Enum(asm_dialect) Init(ASM_NORMAL) +Use given assembler dialect. + +Enum +Name(asm_dialect) Type(enum bpf_asm_dialect) +Known assembler dialects (for use with the -masm= option) + +EnumValue +Enum(asm_dialect) String(normal) Value(ASM_NORMAL) + +EnumValue +Enum(asm_dialect) String(pseudoc) Value(ASM_PSEUDOC) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 3063e71c8906..b3be65d3efae 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -946,8 +946,8 @@ Objective-C and Objective-C++ Dialects}. @emph{eBPF Options} @gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version} --mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re --mjmpext -mjmp32 -malu32 -mcpu=@var{version}} +-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext +-mjmp32 -malu32 -mcpu=@var{version} -masm=@var{dialect>}} @emph{FR30 Options} @gccoptlist{-msmall-model -mno-lsim} @@ -24736,6 +24736,23 @@ the restrictions imposed by the BPF architecture: @item Save and restore callee-saved registers at function entry and exit, respectively. @end itemize + +@opindex masm=@var{dialect} +@item -masm=@var{dialect} +Outputs assembly instructions using eBPF selected @var{dialect}. The default +is @samp{normal}. + +Supported values for @var{dialect} are: + +@table @samp +@item normal +Outputs normal assembly dialect. + +@item pseudoc +Outputs pseudo-c assembly dialect. + +@end table + @end table @node FR30 Options -- 2.38.1