summaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.c')
-rw-r--r--gcc/config/mips/mips.c167
1 files changed, 145 insertions, 22 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 483cc23b8ae..dee6503ee54 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1383,7 +1383,7 @@ mips_legitimate_address_p (mode, xinsn, strict)
(set (blah:DI) (plus x y)). */
&& (!TARGET_64BIT
|| (code1 == CONST_INT
- && trunc_int_for_mode (INTVAL (xplus1),
+ && trunc_int_for_mode (INTVAL (xplus1),
SImode) == INTVAL (xplus1)))
&& !TARGET_MIPS16)
return 1;
@@ -3536,7 +3536,9 @@ output_block_move (insn, operands, num_regs, move_type)
constant addresses into registers when generating N32/N64 code, just
in case we might emit an unaligned load instruction. */
if (num_regs > 2 && (bytes > 2 * align || move_type != BLOCK_MOVE_NORMAL
- || mips_abi == ABI_N32 || mips_abi == ABI_64))
+ || mips_abi == ABI_MEABI
+ || mips_abi == ABI_N32
+ || mips_abi == ABI_64))
{
if (CONSTANT_P (src_reg))
{
@@ -3994,6 +3996,11 @@ function_arg (cum, mode, type, named)
arg_words = &cum->fp_arg_words;
regbase = FP_ARG_FIRST;
}
+ /* The MIPS eabi says only structures containing doubles get passed in a
+ fp register, so force a structure containing a float to be passed in
+ the integer registers. */
+ else if (mips_abi == ABI_MEABI && struct_p)
+ regbase = GP_ARG_FIRST;
else
regbase = (TARGET_SOFT_FLOAT || ! named ? GP_ARG_FIRST : FP_ARG_FIRST);
break;
@@ -4063,11 +4070,30 @@ function_arg (cum, mode, type, named)
if (regbase == -1)
abort ();
- if (! type || TREE_CODE (type) != RECORD_TYPE || mips_abi == ABI_32
- || mips_abi == ABI_EABI || mips_abi == ABI_O64 || ! named
+ if (! type || TREE_CODE (type) != RECORD_TYPE
+ || mips_abi == ABI_32 || mips_abi == ABI_EABI
+ || mips_abi == ABI_O64 || mips_abi == ABI_MEABI
+ || ! named
|| ! TYPE_SIZE_UNIT (type)
|| ! host_integerp (TYPE_SIZE_UNIT (type), 1))
- ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
+ {
+
+ unsigned int arg_reg = (regbase + *arg_words + bias);
+ ret = gen_rtx_REG (mode, arg_reg);
+ if (mips_abi == ABI_MEABI
+ && regbase == FP_ARG_FIRST
+ && ! cum->prototype)
+ {
+ /* To make K&R varargs work we need to pass floating
+ point arguments in both integer and FP registers. */
+ ret = gen_rtx_PARALLEL (mode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode,
+ arg_reg + GP_ARG_FIRST - FP_ARG_FIRST),
+ const0_rtx), gen_rtx_EXPR_LIST (VOIDmode, ret, const0_rtx)));
+ }
+ }
else
{
/* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the
@@ -4124,6 +4150,7 @@ function_arg (cum, mode, type, named)
if (field
&& int_bit_position (field) == bitpos
&& TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ && !TARGET_SOFT_FLOAT
&& TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
reg = gen_rtx_REG (DFmode,
regno + FP_ARG_FIRST - GP_ARG_FIRST);
@@ -4164,7 +4191,9 @@ function_arg (cum, mode, type, named)
calling convention for now. */
if (struct_p && int_size_in_bytes (type) < UNITS_PER_WORD
- && ! TARGET_64BIT && mips_abi != ABI_EABI)
+ && ! TARGET_64BIT
+ && mips_abi != ABI_EABI
+ && mips_abi != ABI_MEABI)
{
rtx amount = GEN_INT (BITS_PER_WORD
- int_size_in_bytes (type) * BITS_PER_UNIT);
@@ -4454,6 +4483,8 @@ mips_va_start (stdarg_p, valist, nextarg)
and both iris5.h and iris6.h define _MIPS_SIM. */
if (mips_abi == ABI_N32 || mips_abi == ABI_64)
ofs = (int_arg_words >= 8 ? -UNITS_PER_WORD : 0);
+ else if (mips_abi == ABI_MEABI)
+ ofs = (int_arg_words >= 8 ? -UNITS_PER_WORD : 0);
else
ofs = -UNITS_PER_WORD;
}
@@ -4764,7 +4795,10 @@ override_options ()
mips_isa = MIPS_ISA_DEFAULT;
}
}
- else if (mips_isa < 1 || mips_isa > 4)
+ else if (mips_isa < 1
+ || (mips_isa > 4
+ && mips_isa != 32
+ && mips_isa != 64))
{
error ("-mips%d not supported", mips_isa);
mips_isa = 1;
@@ -4791,17 +4825,26 @@ override_options ()
mips_abi = ABI_64;
else if (! strcmp (mips_abi_string, "eabi"))
mips_abi = ABI_EABI;
+ else if (! strcmp (mips_abi_string, "meabi"))
+ mips_abi = ABI_MEABI;
else
error ("bad value (%s) for -mabi= switch", mips_abi_string);
/* A specified ISA defaults the ABI if it was not specified. */
if (mips_abi_string == 0 && mips_isa_string
- && mips_abi != ABI_EABI && mips_abi != ABI_O64)
+ && mips_abi != ABI_EABI
+ && mips_abi != ABI_O64
+ && mips_abi != ABI_MEABI)
{
- if (! ISA_HAS_64BIT_REGS)
- mips_abi = ABI_32;
+ if (mips_isa == 64)
+ mips_abi = ABI_O64;
else
- mips_abi = ABI_64;
+ {
+ if (! ISA_HAS_64BIT_REGS)
+ mips_abi = ABI_32;
+ else
+ mips_abi = ABI_64;
+ }
}
#ifdef MIPS_CPU_STRING_DEFAULT
@@ -4894,6 +4937,14 @@ override_options ()
mips_arch_string = "8000";
mips_arch = PROCESSOR_R8000;
break;
+ case 32:
+ mips_arch_string = "4kc";
+ mips_arch = PROCESSOR_R4KC;
+ break;
+ case 64:
+ mips_arch_string = "5kc";
+ mips_arch = PROCESSOR_R5KC;
+ break;
}
}
else
@@ -4930,6 +4981,14 @@ override_options ()
mips_tune_string = "8000";
mips_tune = PROCESSOR_R8000;
break;
+ case 32:
+ mips_arch_string = "4kc";
+ mips_arch = PROCESSOR_R4KC;
+ break;
+ case 64:
+ mips_arch_string = "5kc";
+ mips_arch = PROCESSOR_R5KC;
+ break;
}
}
@@ -4943,16 +5002,22 @@ override_options ()
}
}
- /* Handle processor configuration based on architecture. */
- if (TARGET_MIPS4100 || TARGET_MIPS3900)
- target_flags |= MASK_SOFT_FLOAT;
+ /* Handle processor configuration based on architecture. */
+ if (TARGET_MIPS4100
+ || TARGET_MIPS3900
+ || TARGET_MIPS4KC
+ || TARGET_MIPS5KC)
+ target_flags |= MASK_SOFT_FLOAT;
if ((mips_arch == PROCESSOR_R3000 && (mips_isa != 1))
+ || (mips_arch == PROCESSOR_R4KC && mips_isa != 32)
+ || ((mips_arch == PROCESSOR_R5KC
+ || mips_arch == PROCESSOR_R20KC) && mips_isa != 64)
|| (mips_arch == PROCESSOR_R6000 && mips_isa != 1 && mips_isa != 2)
|| ((mips_arch == PROCESSOR_R4000
- || mips_arch == PROCESSOR_R4100
- || mips_arch == PROCESSOR_R4300
+ || mips_arch == PROCESSOR_R4100
+ || mips_arch == PROCESSOR_R4300
|| mips_arch == PROCESSOR_R4600
|| mips_arch == PROCESSOR_R4650)
&& mips_isa != 1 && mips_isa != 2 && mips_isa != 3))
@@ -5160,7 +5225,14 @@ override_options ()
temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
else if (FP_REG_P (regno))
- temp = ((TARGET_FLOAT64 || ((regno & 1) == 0))
+ temp = ((TARGET_FLOAT64 || ((regno & 1) == 0)
+ /* I think this change is OK regardless of abi, but
+ I'm being cautions untill I can test this more.
+ HARD_REGNO_MODE_OK is about whether or not you
+ can move to and from a register without changing
+ the value, not about whether math works on the
+ register. */
+ || (mips_abi == ABI_MEABI && size <= 4))
&& (class == MODE_FLOAT
|| class == MODE_COMPLEX_FLOAT
|| (TARGET_DEBUG_H_MODE && class == MODE_INT))
@@ -5866,7 +5938,6 @@ mips_output_lineno (stream, line)
LOCAL_LABEL_PREFIX, sym_lineno, ASM_STABN_OP, N_SLINE, line,
LOCAL_LABEL_PREFIX, sym_lineno);
}
-
else
{
fprintf (stream, "\n\t%s.loc\t%d %d\n",
@@ -6021,6 +6092,8 @@ void
mips_asm_file_start (stream)
FILE *stream;
{
+ const char * abi_string = NULL;
+
ASM_OUTPUT_SOURCE_FILENAME (stream, main_input_filename);
/* Versions of the MIPS assembler before 2.20 generate errors if a branch
@@ -6031,6 +6104,35 @@ mips_asm_file_start (stream)
if (TARGET_MIPS_AS && optimize && flag_delayed_branch)
fprintf (stream, "\t.set\tnobopt\n");
+#ifdef OBJECT_FORMAT_ELF
+ /* Generate a special section to describe the ABI switches used to produce
+ the resultant binary. This used to be done by the assembler setting bits
+ in the ELF header's flags field, but we have run out of bits. GDB needs
+ this information in order to be able to correctly debug these binaries.
+ See the function mips_gdbarch_init() in gdb/mips-tdep.c. */
+ switch (mips_abi)
+ {
+ case ABI_32: abi_string = "abi32"; break;
+ case ABI_N32: abi_string = "abiN32"; break;
+ case ABI_64: abi_string = "abi64"; break;
+ case ABI_O64: abi_string = "abiO64"; break;
+ case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
+ case ABI_MEABI:abi_string = TARGET_64BIT ? "meabi64" : "meabi32"; break;
+ default:
+ abort ();
+ }
+ /* Note - we use fprintf directly rather than called named_section()
+ because in this way we can avoid creating an allocated section. We
+ do not want this section to take up any space in the running
+ executable. */
+ fprintf (stream, "\t.section .mdebug.%s\n", abi_string);
+
+ /* Restore the default section. */
+ fprintf (stream, "\t.previous\n");
+#endif
+
+
+
/* Generate the pseudo ops that System V.4 wants. */
#ifndef ABICALLS_ASM_OP
#define ABICALLS_ASM_OP "\t.abicalls"
@@ -6115,7 +6217,6 @@ copy_file_data (to, from)
{
char buffer[8192];
size_t len;
-
rewind (from);
if (ferror (from))
fatal_io_error ("can't rewind temp file");
@@ -7910,7 +8011,8 @@ function_arg_pass_by_reference (cum, mode, type, named)
to prevent it, or add code to function.c to properly handle the case. */
/* ??? cum can be NULL when called from mips_va_arg. The problem handled
here hopefully is not relevant to mips_va_arg. */
- if (cum && MUST_PASS_IN_STACK (mode, type))
+ if (cum && MUST_PASS_IN_STACK (mode, type)
+ && mips_abi != ABI_MEABI)
{
/* Don't pass the actual CUM to FUNCTION_ARG, because we would
get double copies of any offsets generated for small structs
@@ -9714,6 +9816,8 @@ mips_parse_cpu (cpu_string)
case '2':
if (!strcmp (p, "2000") || !strcmp (p, "2k") || !strcmp (p, "2K"))
cpu = PROCESSOR_R3000;
+ else if (!strcmp (p, "20kc") || !strcmp (p, "20Kc") )
+ cpu = PROCESSOR_R20KC;
break;
case '3':
@@ -9742,11 +9846,20 @@ mips_parse_cpu (cpu_string)
cpu = PROCESSOR_R4600;
else if (!strcmp (p, "4650"))
cpu = PROCESSOR_R4650;
+ /* The 4kc and 4kp processor cores are the same for
+ scheduling purposes; they both implement the MIPS32
+ ISA and only differ in their memory management
+ methods. */
+ else if (!strcmp (p, "4kc") || !strcmp (p, "4Kc")
+ || !strcmp (p, "4kp") || !strcmp (p, "4Kp") )
+ cpu = PROCESSOR_R4KC;
break;
case '5':
if (!strcmp (p, "5000") || !strcmp (p, "5k") || !strcmp (p, "5K"))
cpu = PROCESSOR_R5000;
+ else if (!strcmp (p, "5kc") || !strcmp (p, "5Kc") )
+ cpu = PROCESSOR_R5KC;
break;
case '6':
@@ -9864,6 +9977,17 @@ mips_unique_section (decl, reloc)
DECL_SECTION_NAME (decl) = build_string (len, string);
}
+unsigned int
+mips_hard_regno_nregs (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ if (! FP_REG_P (regno))
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+ else
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
+}
+
#ifdef TARGET_IRIX6
/* Output assembly to switch to section NAME with attribute FLAGS. */
@@ -9887,7 +10011,6 @@ iris6_asm_named_section_1 (name, flags, align)
sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
if (strcmp (name, ".debug_frame") == 0)
sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
-
if (flags & SECTION_DEBUG)
sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
else if (flags & SECTION_BSS)
@@ -9980,7 +10103,7 @@ iris6_asm_output_align (file, log)
but takes it from the first .section directive seen. Play yet more
file switching games so that we can emit a .section directive at the
beginning of the file with the proper alignment attached. */
-
+
void
iris6_asm_file_start (stream)
FILE *stream;