> + > +(define_memory_constraint "Qmx" > + "@internal > + An address valid for GPR." > + (and (match_code "mem") > + (match_test "!riscv_legitimize_address_index_p ( > + XEXP (op, 0), GET_MODE (op), false)")))
Check TARGET_XTHEADFMEMIDX, and I don't quite understand why it comes with `!` for the riscv_legitimize_address_index_p, but saying it's an address valid for GPR? According to the comment it sounds like (mem (reg)) but seems like not? > diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h > index 019a0e08285..ba53bf710d7 100644 > --- a/gcc/config/riscv/riscv-protos.h > +++ b/gcc/config/riscv/riscv-protos.h > @@ -77,6 +77,8 @@ extern const char * > riscv_output_move_index (rtx x, machine_mode mode, bool ldr); > extern const char * > riscv_output_move_modify (rtx x, machine_mode mode, bool ldi); > +extern const char * > +riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr); > > extern bool > riscv_legitimize_address_index_p (rtx x, machine_mode mode, bool uindex); > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index 2980dbd69f9..caa30eed8d6 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -1316,7 +1316,7 @@ riscv_classify_address_index (struct riscv_address_info > *info, rtx x, > rtx index; > int shift = 0; > > - if (!TARGET_XTHEADMEMIDX) > + if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX)) > return false; > > if (!TARGET_64BIT && mode == DImode) > @@ -1326,6 +1326,8 @@ riscv_classify_address_index (struct riscv_address_info > *info, rtx x, > { > if (!TARGET_HARD_FLOAT) > return false; > + if (!(TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX)) > + return false; > if (GET_MODE_SIZE (mode).to_constant () == 2) > return false; > } > @@ -1422,7 +1424,7 @@ riscv_classify_address_modify (struct > riscv_address_info *info, rtx x, > ? (SHIFT) + 1 \ > : 0) > > - if (!TARGET_XTHEADMEMIDX) > + if (!(TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX)) > return false; > > if (!(INTEGRAL_MODE_P (mode) && GET_MODE_SIZE (mode).to_constant () <= 8)) > @@ -1562,6 +1564,42 @@ riscv_output_move_index (rtx x, machine_mode mode, > bool ldr) > return buf; > } > > +const char * > +riscv_output_move_index_float (rtx x, machine_mode mode, bool ldr) > +{ > + static char buf[128] = {0}; > + > + int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ()); > + if (!IN_RANGE (index, 2, 3)) > + return NULL; > + > + if (!riscv_legitimize_address_index_p (x, mode, false)) > + return NULL; > + > + bool uindex = riscv_legitimize_address_index_p (x, mode, true); > + > + /* Not using index, 0, 1, as they are not implemented > + for xtheadfmemidx yet. */ > + const char *const insn[][4] = { > + { > + "th.fs%srb\t%%z1,%%0", > + "th.fs%srh\t%%z1,%%0", > + "th.fs%srw\t%%z1,%%0", > + "th.fs%srd\t%%z1,%%0" > + }, > + { > + "th.fl%srb\t%%0,%%1", > + "th.fl%srh\t%%0,%%1", > + "th.fl%srw\t%%0,%%1", > + "th.fl%srd\t%%0,%%1" > + } > + }; > + > + snprintf (buf, sizeof (buf), insn[ldr][index], uindex ? "u" : ""); > + > + return buf; > +} > + > /* Emit an instruction of the form (set TARGET SRC). */ > > static rtx > @@ -2739,7 +2777,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int > outer_code, int opno ATTRIBUTE_UN > } > /* bit extraction pattern (xtheadmemidx, xtheadfmemidx). */ > if (outer_code == SET > - && TARGET_XTHEADMEMIDX) > + && (TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX)) > { > *total = COSTS_N_INSNS (SINGLE_SHIFT_COST); > return true; > @@ -3071,6 +3109,20 @@ riscv_split_64bit_move_p (rtx dest, rtx src) > if (TARGET_64BIT) > return false; > > + if (TARGET_XTHEADFMEMIDX) > + { > + if (MEM_P (src) && SCALAR_FLOAT_MODE_P (GET_MODE (src)) > + && riscv_legitimize_address_index_p (XEXP (src, 0), > + GET_MODE (src), false) > + && FP_REG_RTX_P (dest)) > + return false; > + if (MEM_P (dest) && SCALAR_FLOAT_MODE_P (GET_MODE (dest)) > + && riscv_legitimize_address_index_p (XEXP (dest, 0), > + GET_MODE (dest), false) > + && FP_REG_RTX_P (src)) > + return false; > + } > + > /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case > of zeroing an FPR with FCVT.D.W. */ > if (TARGET_DOUBLE_FLOAT > @@ -3269,6 +3321,12 @@ riscv_output_move (rtx dest, rtx src) > > if (dest_code == MEM) > { > + const char *insn = NULL; > + insn = riscv_output_move_index_float (XEXP (dest, 0), > + GET_MODE (dest), false); > + if (insn) > + return insn; > + > switch (width) > { > case 2: > @@ -3284,6 +3342,12 @@ riscv_output_move (rtx dest, rtx src) > { > if (src_code == MEM) > { > + const char *insn = NULL; > + insn = riscv_output_move_index_float (XEXP (src, 0), > + GET_MODE (src), true); > + if (insn) > + return insn; > + > switch (width) > { > case 2: > diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h > index 199bb30162e..13764d60257 100644 > --- a/gcc/config/riscv/riscv.h > +++ b/gcc/config/riscv/riscv.h > @@ -535,7 +535,7 @@ enum reg_class > factor or added to another register (as well as added to a > displacement). */ > > -#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX) ? \ > +#define INDEX_REG_CLASS ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \ > GR_REGS : NO_REGS) > > /* We generally want to put call-clobbered registers ahead of > @@ -707,7 +707,7 @@ typedef struct { > /* Addressing modes, and classification of registers for them. */ > > #define REGNO_OK_FOR_INDEX_P(REGNO) \ > - ((TARGET_XTHEADMEMIDX) ? \ > + ((TARGET_XTHEADMEMIDX || TARGET_XTHEADFMEMIDX) ? \ > riscv_regno_mode_ok_for_base_p (REGNO, VOIDmode, 1) : 0) > > #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md > index df31a1fffff..9d0207b8d6f 100644 > --- a/gcc/config/riscv/riscv.md > +++ b/gcc/config/riscv/riscv.md > @@ -1866,6 +1866,20 @@ (define_insn "*movsf_hardfloat" > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") > (set_attr "mode" "SF")]) > > +(define_insn "*movsf_hardfloat" > + [(set (match_operand:SF 0 > + "nonimmediate_operand" "=f,f,f,m,Qmx,*f,*r, *r,*r,*Qmx") > + (match_operand:SF 1 > + "move_operand" " f,G,m,f,G,*r,*f,*G*r,*Qmx,*r"))] > + "!TARGET_64BIT > + && TARGET_XTHEADFMEMIDX > + && (register_operand (operands[0], SFmode) > + || reg_or_0_operand (operands[1], SFmode))" > + { return riscv_output_move (operands[0], operands[1]); } > + [(set_attr "move_type" > + "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") > + (set_attr "mode" "SF")]) > + Plz move to thead.md and named with prefix *th > (define_insn "*movsf_softfloat" > [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m") > (match_operand:SF 1 "move_operand" " Gr,m,r"))] > @@ -1900,6 +1914,20 @@ (define_insn "*movdf_hardfloat_rv32" > "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") > (set_attr "mode" "DF")]) > > +(define_insn "*movdf_hardfloat_rv32" > + [(set (match_operand:DF 0 > + "nonimmediate_operand" "=f,f,f,m,Qmx, *r,*r,*Qmx") > + (match_operand:DF 1 > + "move_operand" " f,G,m,f,G,*r*G,*Qmx,*r"))] > + "!TARGET_64BIT && TARGET_DOUBLE_FLOAT > + && TARGET_XTHEADFMEMIDX > + && (register_operand (operands[0], DFmode) > + || reg_or_0_operand (operands[1], DFmode))" > + { return riscv_output_move (operands[0], operands[1]); } > + [(set_attr "move_type" > + "fmove,mtc,fpload,fpstore,store,move,load,store") > + (set_attr "mode" "DF")]) > + Ditto