===================================================================
@@ -28,6 +28,7 @@ enum riscv_symbol_type {
SYMBOL_ABSOLUTE,
SYMBOL_PCREL,
SYMBOL_GOT_DISP,
+ SYMBOL_GPREL,
SYMBOL_TLS,
SYMBOL_TLS_LE,
SYMBOL_TLS_IE,
===================================================================
@@ -559,7 +559,13 @@ riscv_classify_symbol (const_rtx x)
if (GET_CODE (x) == SYMBOL_REF && flag_pic && !riscv_symbol_binds_local_p (x))
return SYMBOL_GOT_DISP;
- return riscv_cmodel == CM_MEDLOW ? SYMBOL_ABSOLUTE : SYMBOL_PCREL;
+ if (riscv_cmodel == CM_MEDLOW)
+ return SYMBOL_ABSOLUTE;
+
+ if (LABEL_REF_P (x) || (SYMBOL_REF_P (x) && SYMBOL_REF_FUNCTION_P (x)))
+ return SYMBOL_PCREL;
+
+ return TARGET_GPREL ? SYMBOL_GPREL : SYMBOL_PCREL;
}
/* Classify the base of symbolic expression X. */
@@ -604,6 +610,7 @@ riscv_symbolic_constant_p (rtx x, enum r
case SYMBOL_ABSOLUTE:
case SYMBOL_PCREL:
case SYMBOL_TLS_LE:
+ case SYMBOL_GPREL:
/* GAS rejects offsets outside the range [-2^31, 2^31-1]. */
return sext_hwi (INTVAL (offset), 32) == INTVAL (offset);
@@ -622,6 +629,7 @@ static int riscv_symbol_insns (enum risc
case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference. */
case SYMBOL_PCREL: return 2; /* AUIPC + the reference. */
case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference. */
+ case SYMBOL_GPREL: return 3; /* LUI + ADD GP + the reference. */
case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */
default: gcc_unreachable ();
}
@@ -735,7 +743,9 @@ riscv_split_symbol_type (enum riscv_symb
if (!TARGET_EXPLICIT_RELOCS)
return false;
- return symbol_type == SYMBOL_ABSOLUTE || symbol_type == SYMBOL_PCREL;
+ return (symbol_type == SYMBOL_ABSOLUTE
+ || symbol_type == SYMBOL_PCREL
+ || symbol_type == SYMBOL_GPREL);
}
/* Return true if a LO_SUM can address a value of mode MODE when the
@@ -1241,6 +1251,17 @@ riscv_split_symbol (rtx temp, rtx addr,
}
break;
+ case SYMBOL_GPREL:
+ {
+ rtx high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
+ rtx gp = gen_rtx_REG (Pmode, GP_REGNUM);
+ high = riscv_force_temporary (temp, high, in_splitter);
+ rtx reg = gen_rtx_PLUS (Pmode, high, gp);
+ reg = riscv_force_temporary (temp, reg, in_splitter);
+ *low_out = gen_rtx_LO_SUM (Pmode, reg, addr);
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -2030,6 +2051,7 @@ riscv_output_move (rtx dest, rtx src)
case SYMBOL_GOT_DISP: return "la\t%0,%1";
case SYMBOL_ABSOLUTE: return "lla\t%0,%1";
case SYMBOL_PCREL: return "lla\t%0,%1";
+ case SYMBOL_GPREL: return "la\t%0,%1";
default: gcc_unreachable ();
}
}
@@ -3290,6 +3312,10 @@ riscv_print_operand_reloc (FILE *file, r
reloc = hi_reloc ? "%tprel_hi" : "%tprel_lo";
break;
+ case SYMBOL_GPREL:
+ reloc = hi_reloc ? "%gprel_hi" : "%gprel_lo";
+ break;
+
default:
output_operand_lossage ("invalid use of '%%%c'", hi_reloc ? 'h' : 'R');
return;
@@ -4735,7 +4761,7 @@ riscv_option_override (void)
/* We get better code with explicit relocs for CM_MEDLOW, but
worse code for the others (for now). Pick the best default. */
if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
- if (riscv_cmodel == CM_MEDLOW)
+ if (riscv_cmodel == CM_MEDLOW || TARGET_GPREL)
target_flags |= MASK_EXPLICIT_RELOCS;
/* Require that the ISA supports the requested floating-point ABI. */
===================================================================
@@ -28,6 +28,7 @@
UNSPEC_ADDRESS_FIRST
UNSPEC_PCREL
UNSPEC_LOAD_GOT
+ UNSPEC_GPREL
UNSPEC_TLS
UNSPEC_TLS_LE
UNSPEC_TLS_IE
===================================================================
@@ -179,3 +179,7 @@ Use the given offset for addressing the
TargetVariable
long riscv_stack_protector_guard_offset = 0
+
+mgprel
+Target Report Mask(GPREL)
+Use GP-relative sequences for data accesses.