+Mon Nov 23 17:40:37 1998 Gavin Romig-Koch <gavin@cygnus.com>
+
+ * config/mips/abi.h: Use ABI_O64, duplicating ABI_32 usage.
+ * config/mips/iris6.h: Same.
+ * config/mips/mips.md: Same.
+ * config/mips/mips.c: Same; also add "-mabi=o64" option.
+ * config/mips/mips.h: Same; also define ABI_O64.
+
Mon Nov 23 17:02:27 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* configure.in: Use AC_PREREQ(2.12.1).
#undef STACK_BOUNDARY
#define STACK_BOUNDARY \
- ((mips_abi == ABI_32 || mips_abi == ABI_EABI) ? 64 : 128)
+ ((mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI) \
+ ? 64 : 128)
#undef MIPS_STACK_ALIGN
-#define MIPS_STACK_ALIGN(LOC) \
- ((mips_abi == ABI_32 || mips_abi == ABI_EABI) \
- ? ((LOC) + 7) & ~7 \
+#define MIPS_STACK_ALIGN(LOC) \
+ ((mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI) \
+ ? ((LOC) + 7) & ~7 \
: ((LOC) + 15) & ~15)
#undef GP_ARG_LAST
-#define GP_ARG_LAST (mips_abi == ABI_32 ? GP_REG_FIRST + 7 : GP_REG_FIRST + 11)
+#define GP_ARG_LAST ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
+ ? GP_REG_FIRST + 7 : GP_REG_FIRST + 11)
#undef FP_ARG_LAST
-#define FP_ARG_LAST (mips_abi == ABI_32 ? FP_REG_FIRST + 15 : FP_REG_FIRST + 19)
+#define FP_ARG_LAST ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
+ ? FP_REG_FIRST + 15 : FP_REG_FIRST + 19)
#undef SUBTARGET_CONDITIONAL_REGISTER_USAGE
#define SUBTARGET_CONDITIONAL_REGISTER_USAGE \
}
#undef MAX_ARGS_IN_REGISTERS
-#define MAX_ARGS_IN_REGISTERS (mips_abi == ABI_32 ? 4 : 8)
+#define MAX_ARGS_IN_REGISTERS ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
+ ? 4 : 8)
#undef REG_PARM_STACK_SPACE
#define REG_PARM_STACK_SPACE(FNDECL) \
- (mips_abi == ABI_32 \
+ ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
? (MAX_ARGS_IN_REGISTERS*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL) \
: 0)
? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
&& int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT))\
: (GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY \
- && (mips_abi == ABI_32 || mips_abi == ABI_EABI \
+ && (mips_abi == ABI_32 \
+ || mips_abi == ABI_O64 \
+ || mips_abi == ABI_EABI \
|| GET_MODE_CLASS (MODE) == MODE_INT))) \
? downward : upward))
#undef RETURN_IN_MEMORY
#define RETURN_IN_MEMORY(TYPE) \
- (mips_abi == ABI_32 \
+ ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
? TYPE_MODE (TYPE) == BLKmode \
: (int_size_in_bytes (TYPE) \
> (mips_abi == ABI_EABI ? 2 * UNITS_PER_WORD : 16)))
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
{ int mips_off = (! current_function_varargs) && (! (CUM).last_arg_fp); \
int mips_fp_off = (! current_function_varargs) && ((CUM).last_arg_fp); \
- if ((mips_abi != ABI_32 \
+ if (((mips_abi != ABI_32 && mips_abi != ABI_O64) \
&& (CUM).arg_words < MAX_ARGS_IN_REGISTERS - mips_off) \
|| (mips_abi == ABI_EABI \
&& ! TARGET_SOFT_FLOAT \
} \
}
-#define STRICT_ARGUMENT_NAMING (mips_abi != ABI_32)
+#define STRICT_ARGUMENT_NAMING (mips_abi != ABI_32 && mips_abi != ABI_O64)
/* A C expression that indicates when an argument must be passed by
reference. If nonzero for an argument, a copy of that argument is
{ \
if (in_section != in_rdata) \
{ \
- if (mips_abi != ABI_32) \
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64) \
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_64); \
else \
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_32); \
#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
do \
{ \
- if (mips_abi != ABI_32) \
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64) \
{ \
fprintf (STREAM, "%s\n", BSS_SECTION_ASM_OP); \
mips_declare_object (STREAM, NAME, "", ":\n", 0); \
} while (0)
#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX (mips_abi == ABI_32 ? "$" : ".")
+#define LOCAL_LABEL_PREFIX ((mips_abi == ABI_32 || mips_abi == ABI_O64) \
+ ? "$" : ".")
/* Profiling is supported via libprof1.a not -lc_p as in Irix 3. */
/* ??? If no mabi=X option give, but a mipsX option is, then should depend
return 1;
/* ??? li.s does not work right with SGI's Irix 6 assembler. */
- if (mips_abi != ABI_32 && mips_abi != ABI_EABI)
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64 && mips_abi != ABI_EABI)
return 0;
REAL_VALUE_FROM_CONST_DOUBLE (d, op);
switch (mode)
{
case SFmode:
- if (mips_abi == ABI_32)
+ if (mips_abi == ABI_32 || mips_abi == ABI_O64)
{
if (cum->gp_reg_found || cum->arg_number >= 2 || TARGET_SOFT_FLOAT)
regbase = GP_ARG_FIRST;
cum->arg_words += cum->arg_words & 1;
}
- if (mips_abi == ABI_32)
+ if (mips_abi == ABI_32 || mips_abi == ABI_O64)
regbase = ((cum->gp_reg_found
|| TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT
|| cum->arg_number >= 2)
abort ();
if (! type || TREE_CODE (type) != RECORD_TYPE || mips_abi == ABI_32
- || mips_abi == ABI_EABI || ! named)
+ || mips_abi == ABI_EABI || mips_abi == ABI_O64 || ! named)
ret = gen_rtx (REG, mode, regbase + *arg_words + bias);
else
{
}
#ifdef MIPS_ABI_DEFAULT
- /* Get the ABI to use. Currently this code is only used for Irix 6. */
+ /* Get the ABI to use. */
if (mips_abi_string == (char *) 0)
mips_abi = MIPS_ABI_DEFAULT;
else if (! strcmp (mips_abi_string, "32"))
mips_abi = ABI_32;
+ else if (! strcmp (mips_abi_string, "o64"))
+ mips_abi = ABI_O64;
else if (! strcmp (mips_abi_string, "n32"))
mips_abi = ABI_N32;
else if (! strcmp (mips_abi_string, "64"))
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)
+ if (mips_abi_string == 0 && mips_isa_string
+ && mips_abi != ABI_EABI && mips_abi != ABI_O64)
{
if (mips_isa <= 2)
mips_abi = ABI_32;
}
/* A specified ABI defaults the ISA if it was not specified. */
- else if (mips_isa_string == 0 && mips_abi_string && mips_abi != ABI_EABI)
+ else if (mips_isa_string == 0 && mips_abi_string
+ && mips_abi != ABI_EABI && mips_abi != ABI_O64)
{
if (mips_abi == ABI_32)
mips_isa = 1;
/* If both ABI and ISA were specified, check for conflicts. */
else if (mips_isa_string && mips_abi_string)
{
- if ((mips_isa <= 2 && (mips_abi == ABI_N32 || mips_abi == ABI_64))
+ if ((mips_isa <= 2 && (mips_abi == ABI_N32 || mips_abi == ABI_64
+ || mips_abi == ABI_O64))
|| (mips_isa >= 3 && mips_abi == ABI_32))
error ("-mabi=%s does not support -mips%d", mips_abi_string, mips_isa);
}
fatal ("Only MIPS-III or MIPS-IV CPUs can support 64 bit gp registers");
}
- if (mips_abi != ABI_32)
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64)
flag_pcc_struct_return = 0;
/* Tell halfpic.c that we have half-pic code if we do. */
/* Start a section, so that the first .popsection directive is guaranteed
to have a previously defined section to pop back to. */
- if (mips_abi != ABI_32 && mips_abi != ABI_EABI)
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64 && mips_abi != ABI_EABI)
fprintf (stream, "\t.section\t.text\n");
/* This code exists so that we can put all externs before all symbol
The gp reg is callee saved in the 64 bit ABI, so all routines must
save the gp reg. This is not a leaf routine if -p, because of the
call to mcount. */
- if (total_size == extra_size && (mips_abi == ABI_32 || mips_abi == ABI_EABI)
+ if (total_size == extra_size
+ && (mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI)
&& ! profile_flag)
total_size = extra_size = 0;
else if (TARGET_ABICALLS)
/* Add in space reserved on the stack by the callee for storing arguments
passed in registers. */
- if (mips_abi != ABI_32)
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64)
total_size += MIPS_STACK_ALIGN (current_function_pretend_args_size);
/* The entry pseudo instruction will allocate 32 bytes on the stack. */
insn = emit_move_insn (mem_rtx, reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
- else if (!TARGET_ABICALLS || mips_abi != ABI_32
+ else if (!TARGET_ABICALLS
+ || (mips_abi != ABI_32 && mips_abi != ABI_O64)
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
{
emit_move_insn (reg_rtx, mem_rtx);
}
else
{
- if (store_p || !TARGET_ABICALLS || mips_abi != ABI_32
+ if (store_p || !TARGET_ABICALLS
+ || (mips_abi != ABI_32 && mips_abi != ABI_O64)
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
{
int r = regno;
fprintf (file, "\n");
}
- if (TARGET_ABICALLS && mips_abi == ABI_32)
+ if (TARGET_ABICALLS && (mips_abi == ABI_32 || mips_abi == ABI_O64))
{
char *sp_str = reg_names[STACK_POINTER_REGNUM];
/* If this function is a varargs function, store any registers that
would normally hold arguments ($4 - $7) on the stack. */
- if (mips_abi == ABI_32
+ if ((mips_abi == ABI_32 || mips_abi == ABI_O64)
&& (! mips_entry || mips_can_use_return_insn ())
&& ((TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
/* If we are doing svr4-abi, sp move is done by
function_prologue. In mips16 mode with a large frame, we
save the registers before adjusting the stack. */
- if ((!TARGET_ABICALLS || mips_abi != ABI_32)
+ if ((!TARGET_ABICALLS || (mips_abi != ABI_32 && mips_abi != ABI_O64))
&& (!TARGET_MIPS16 || tsize <= 32767))
{
rtx insn;
else if (reg_18_save != NULL_RTX)
emit_insn (reg_18_save);
- if ((!TARGET_ABICALLS || mips_abi != ABI_32)
+ if ((!TARGET_ABICALLS || (mips_abi != ABI_32 && mips_abi != ABI_O64))
&& TARGET_MIPS16
&& tsize > 32767)
{
instructions when using the frame pointer by pointing the
frame pointer ahead of the argument space allocated on
the stack. */
- if ((! TARGET_ABICALLS || mips_abi != ABI_32)
+ if ((! TARGET_ABICALLS || (mips_abi != ABI_32 && mips_abi != ABI_O64))
&& TARGET_MIPS16
&& tsize > 32767)
{
RTX_FRAME_RELATED_P (insn) = 1;
}
- if (TARGET_ABICALLS && mips_abi != ABI_32)
+ if (TARGET_ABICALLS && (mips_abi != ABI_32 && mips_abi != ABI_O64))
emit_insn (gen_loadgp (XEXP (DECL_RTL (current_function_decl), 0),
gen_rtx (REG, DImode, 25)));
}
/* The GP/PIC register is implicitly used by all SYMBOL_REFs, so if we
are going to restore it, then we must emit a blockage insn to
prevent the scheduler from moving the restore out of the epilogue. */
- else if (TARGET_ABICALLS && mips_abi != ABI_32
+ else if (TARGET_ABICALLS && mips_abi != ABI_32 && mips_abi != ABI_O64
&& (current_frame_info.mask
& (1L << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))))
emit_insn (gen_blockage ());
}
else if (TREE_CODE (valtype) == RECORD_TYPE
- && mips_abi != ABI_32 && mips_abi != ABI_EABI)
+ && mips_abi != ABI_32
+ && mips_abi != ABI_O64
+ && mips_abi != ABI_EABI)
{
/* A struct with only one or two floating point fields is returned in
the floating point registers. */
int gparg, fparg;
unsigned int f;
- /* This code only works for the original 32 bit ABI. */
- if (mips_abi != ABI_32)
+ /* This code only works for the original 32 bit ABI and the O64 ABI. */
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64)
abort ();
if (from_fp_p)
&& strncmp (XSTR (fn, 0), "__mips16_", 9) == 0)
return 0;
- /* This code will only work for the standard ABI. The other ABI's
+ /* This code will only work for o32 and o64 abis. The other ABI's
require more sophisticated support. */
- if (mips_abi != ABI_32)
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64)
abort ();
/* We can only handle SFmode and DFmode floating point return
#define mips_cpu_attr ((enum attr_cpu)mips_cpu)
/* Which ABI to use. These are constants because abi64.h must check their
- value at preprocessing time. */
+ value at preprocessing time.
+
+ ABI_32 (original 32, or o32), ABI_N32 (n32), ABI_64 (n64) are all
+ defined by SGI. ABI_O64 is o32 extended to work on a 64 bit machine. */
#define ABI_32 0
#define ABI_N32 1
#define ABI_64 2
#define ABI_EABI 3
+#define ABI_O64 4
#ifndef MIPS_ABI_DEFAULT
/* We define this away so that there is no extra runtime cost if the target
&& (TO) == HARD_FRAME_POINTER_REGNUM) \
(OFFSET) = (current_frame_info.total_size \
- current_function_outgoing_args_size \
- - ((mips_abi != ABI_32 && mips_abi != ABI_EABI) \
+ - ((mips_abi != ABI_32 \
+ && mips_abi != ABI_O64 \
+ && mips_abi != ABI_EABI) \
? current_function_pretend_args_size \
: 0)); \
else if ((FROM) == ARG_POINTER_REGNUM) \
(OFFSET) = (current_frame_info.total_size \
- - ((mips_abi != ABI_32 && mips_abi != ABI_EABI) \
+ - ((mips_abi != ABI_32 \
+ && mips_abi != ABI_O64 \
+ && mips_abi != ABI_EABI) \
? current_function_pretend_args_size \
: 0)); \
/* Some ABIs store 64 bits to the stack, but Pmode is 32 bits, \
/* ??? Reject combining an address with a register for the MIPS \
64 bit ABI, because the SGI assembler can not handle this. */ \
if (!TARGET_DEBUG_A_MODE \
- && (mips_abi == ABI_32 || mips_abi == ABI_EABI) \
+ && (mips_abi == ABI_32 \
+ || mips_abi == ABI_O64 \
+ || mips_abi == ABI_EABI) \
&& CONSTANT_ADDRESS_P (xplus1) \
&& ! mips_split_addresses \
&& (!TARGET_EMBEDDED_PIC \
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \
|| (GET_CODE (X) == CONST \
&& ! (flag_pic && pic_address_needs_scratch (X)) \
- && (mips_abi == ABI_32 || mips_abi == ABI_EABI))) \
+ && (mips_abi == ABI_32 \
+ || mips_abi == ABI_O64 \
+ || mips_abi == ABI_EABI))) \
&& (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X)))
/* Define this, so that when PIC, reload won't try to reload invalid
((GET_CODE (X) != CONST_DOUBLE \
|| mips_const_double_ok (X, GET_MODE (X))) \
&& ! (GET_CODE (X) == CONST \
- && mips_abi != ABI_32 && mips_abi != ABI_EABI) \
+ && mips_abi != ABI_32 \
+ && mips_abi != ABI_O64 \
+ && mips_abi != ABI_EABI) \
&& (! TARGET_MIPS16 || mips16_constant (X, GET_MODE (X), 0, 0)))
/* A C compound statement that attempts to replace X with a valid
if (GET_CODE (xinsn) == CONST \
&& ((flag_pic && pic_address_needs_scratch (xinsn)) \
/* ??? SGI's Irix 6 assembler can't handle CONST. */ \
- || (mips_abi != ABI_32 && mips_abi != ABI_EABI))) \
+ || (mips_abi != ABI_32 \
+ && mips_abi != ABI_O64 \
+ && mips_abi != ABI_EABI))) \
{ \
rtx ptr_reg = gen_reg_rtx (Pmode); \
rtx constant = XEXP (XEXP (xinsn, 0), 1); \
fprintf (STREAM, "\t%s\t%sL%d-%sLS%d\n", \
Pmode == DImode ? ".dword" : ".word", \
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
- else if (mips_abi == ABI_32) \
+ else if (mips_abi == ABI_32 || mips_abi == ABI_O64) \
fprintf (STREAM, "\t%s\t%sL%d\n", \
Pmode == DImode ? ".gpdword" : ".gpword", \
LOCAL_LABEL_PREFIX, VALUE); \
/* See mips_expand_prologue's use of loadgp for when this should be
true. */
-#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS && mips_abi != ABI_32)
+#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS \
+ && mips_abi != ABI_32 \
+ && mips_abi != ABI_O64)
\f
/* In mips16 mode, we need to look through the function to check for
PC relative loads that are out of range. */
/* ??? I don't know why this is necessary. This works around an
assembler problem that appears when a label is defined, then referenced
in a switch table, then used in a `j' instruction. */
- else if (mips_abi != ABI_32)
+ else if (mips_abi != ABI_32 && mips_abi != ABI_O64)
return \"%*b\\t%l0\";
else
return \"%*j\\t%l0\";
"*
{
/* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */
- if (mips_abi == ABI_32)
+ if (mips_abi == ABI_32 || mips_abi == ABI_O64)
output_asm_insn (\".cpadd\\t%0\", operands);
return \"%*j\\t%0\";
}"