@@ -2474,6 +2474,9 @@ mips_regno_mode_ok_for_base_p (int regno, machine_mode mode,
if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM)
return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+ if (MIPS16_GP_LOADS && regno == GLOBAL_POINTER_REGNUM)
+ return (UNITS_PER_WORD > 4 ? GET_MODE_SIZE (mode) <= 4 : true);
+
return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
}
@@ -2689,7 +2692,8 @@ static bool
mips16_unextended_reference_p (machine_mode mode, rtx base,
unsigned HOST_WIDE_INT offset)
{
- if (mode != BLKmode && offset % GET_MODE_SIZE (mode) == 0)
+ if (mode != BLKmode && offset % GET_MODE_SIZE (mode) == 0
+ && REGNO (base) != GLOBAL_POINTER_REGNUM)
{
if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
return offset < 256U * GET_MODE_SIZE (mode);
@@ -3249,7 +3253,7 @@ mips16_gp_pseudo_reg (void)
rtx
mips_pic_base_register (rtx temp)
{
- if (!TARGET_MIPS16)
+ if (MIPS16_GP_LOADS ||!TARGET_MIPS16)
return pic_offset_table_rtx;
if (currently_expanding_to_rtl)
@@ -8756,7 +8760,7 @@ mips_init_relocs (void)
}
}
- if (TARGET_MIPS16)
+ if (!MIPS16_GP_LOADS && TARGET_MIPS16)
{
/* The high part is provided by a pseudo copy of $gp. */
mips_split_p[SYMBOL_GP_RELATIVE] = true;
@@ -1375,6 +1375,8 @@ struct mips_cpu_info {
/* ISA includes the pop instruction. */
#define ISA_HAS_POP (TARGET_OCTEON && !TARGET_MIPS16)
+#define MIPS16_GP_LOADS (ISA_HAS_MIPS16E2 && !TARGET_64BIT)
+
/* The CACHE instruction is available in non-MIPS16 code. */
#define TARGET_CACHE_BUILTIN (mips_isa >= MIPS_ISA_MIPS3)
@@ -2067,10 +2069,6 @@ FP_ASM_SPEC "\
function address than to call an address kept in a register. */
#define NO_FUNCTION_CSE 1
-/* The ABI-defined global pointer. Sometimes we use a different
- register in leaf functions: see PIC_OFFSET_TABLE_REGNUM. */
-#define GLOBAL_POINTER_REGNUM (GP_REG_FIRST + 28)
-
/* We normally use $28 as the global pointer. However, when generating
n32/64 PIC, it is better for leaf functions to use a call-clobbered
register instead. They can then avoid saving and restoring $28
@@ -167,6 +167,7 @@
(GET_FCSR_REGNUM 2)
(SET_FCSR_REGNUM 4)
(PIC_FUNCTION_ADDR_REGNUM 25)
+ (GLOBAL_POINTER_REGNUM 28)
(RETURN_ADDR_REGNUM 31)
(CPRESTORE_SLOT_REGNUM 76)
(GOT_VERSION_REGNUM 79)
@@ -4678,6 +4679,16 @@
[(set_attr "alu_type" "add")
(set_attr "mode" "<MODE>")])
+(define_insn "*lowsi_mips16_gp"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lo_sum:SI (reg:SI GLOBAL_POINTER_REGNUM)
+ (match_operand 1 "immediate_operand" "")))]
+ "MIPS16_GP_LOADS"
+ "addiu\t%0,$28,%R1"
+ [(set_attr "alu_type" "add")
+ (set_attr "mode" "SI")
+ (set_attr "extended_mips16" "yes")])
+
(define_insn "*low<mode>_mips16"
[(set (match_operand:P 0 "register_operand" "=d")
(lo_sum:P (match_operand:P 1 "register_operand" "0")
new file mode 100644
@@ -0,0 +1,101 @@
+/* { dg-options "-mno-abicalls -mgpopt -G8 -mabi=32 -mips16 -mmips16e2" } */
+/* { dg-skip-if "per-function expected output" { *-*-* } { "-flto" } { "" } } */
+
+/* Generate GP-relative ADDIU. */
+
+/* { dg-final { scan-assembler "test01:.*\taddiu\t\\\$2,\\\$28.*test01\n" } } */
+int arr[2];
+
+int *
+test01 (void)
+{
+ return (&arr[1]);
+}
+
+/* Test LB[GP]. */
+
+/* { dg-final { scan-assembler "test02:.*\tlb\t.*\\\$28.*test02\n" } } */
+signed char c02;
+
+signed char
+test02 (void)
+{
+ return c02;
+}
+
+/* Test LBU[GP]. */
+
+/* { dg-final { scan-assembler "test03:.*\tlbu\t.*\\\$28.*test03\n" } } */
+unsigned char uc03;
+
+unsigned char
+test03 (void)
+{
+ return uc03;
+}
+
+/* Test LH[GP]. */
+
+/* { dg-final { scan-assembler "test04:.*\tlh\t.*\\\$28.*test04\n" } } */
+short s04;
+
+short
+test04 (void)
+{
+ return s04;
+}
+
+/* Test LHU[GP]. */
+
+/* { dg-final { scan-assembler "test05:.*\tlhu\t.*\\\$28.*test05\n" } } */
+unsigned short s05;
+
+unsigned short
+test05 (void)
+{
+ return s05;
+}
+
+/* Test LW[GP]. */
+
+/* { dg-final { scan-assembler "test06:.*\tlw\t.*\\\$28.*test06\n" } } */
+int i06;
+
+int
+test06 (void)
+{
+ return i06;
+}
+
+/* Test SB[GP]. */
+
+/* { dg-final { scan-assembler "test07:.*\tsb\t.*\\\$28.*test07\n" } } */
+char c07;
+
+void
+test07 (char x)
+{
+ c07 = x;
+}
+
+/* Test SH[GP]. */
+
+/* { dg-final { scan-assembler "test08:.*\tsh\t.*\\\$28.*test08\n" } } */
+short s08;
+
+void
+test08 (short x)
+{
+ s08 = x;
+}
+
+/* Test SW[GP]. */
+
+/* { dg-final { scan-assembler "test09:.*\tsw\t.*\\\$28.*test09\n" } } */
+int i09;
+
+void
+test09 (int x)
+{
+ i09 = x;
+}