/* Subroutines for insn-output.c for MIPS
- Copyright (C) 1989, 90, 91, 93-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90, 91, 93-98, 1999 Free Software Foundation, Inc.
Contributed by A. Lichnewsky, lich@inria.inria.fr.
Changes by Michael Meissner, meissner@osf.org.
64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
be replaced with something better designed. */
#include "config.h"
-
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
+#include "system.h"
+#include <signal.h>
#include "rtl.h"
#include "regs.h"
#include "insn-attr.h"
#include "insn-codes.h"
#include "recog.h"
-#include "output.h"
+#include "toplev.h"
#undef MAX /* sys/param.h may also define these */
#undef MIN
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/file.h>
-#include <ctype.h>
#include "tree.h"
#include "expr.h"
#include "flags.h"
#include "reload.h"
-
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
+#include "output.h"
#if defined(USG) || !defined(HAVE_STAB_H)
#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
#define STAB_CODE_TYPE int
#endif
-extern void abort ();
-extern int atoi ();
-extern char *getenv ();
extern char *mktemp ();
-
-extern rtx adj_offsettable_operand ();
-extern rtx copy_to_reg ();
-extern void error ();
extern tree lookup_name ();
-extern void pfatal_with_name ();
-extern void warning ();
-
-extern FILE *asm_out_file;
/* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order
static void dump_constants PROTO ((struct constant *,
rtx));
static rtx mips_find_symbol PROTO ((rtx));
+static void abort_with_insn PROTO ((rtx, const char *))
+ ATTRIBUTE_NORETURN;
/* Global variables for machine-dependent things. */
} *extern_head = 0;
/* Name of the file containing the current function. */
-char *current_function_file = "";
+const char *current_function_file = "";
/* Warning given that Mips ECOFF can't support changing files
within a function. */
#endif
/* Strings to hold which cpu and instruction set architecture to use. */
-char *mips_cpu_string; /* for -mcpu=<xxx> */
-char *mips_isa_string; /* for -mips{1,2,3,4} */
-char *mips_abi_string; /* for -mabi={o32,32,n32,n64,64,eabi} */
+const char *mips_cpu_string; /* for -mcpu=<xxx> */
+const char *mips_isa_string; /* for -mips{1,2,3,4} */
+const char *mips_abi_string; /* for -mabi={32,n32,64,eabi} */
/* Whether we are generating mips16 code. This is a synonym for
TARGET_MIPS16, and exists for use as an attribute. */
/* This variable is set by -mno-mips16. We only care whether
-mno-mips16 appears or not, and using a string in this fashion is
just a way to avoid using up another bit in target_flags. */
-char *mips_no_mips16_string;
+const char *mips_no_mips16_string;
+
+/* This is only used to determine if an type size setting option was
+ explicitly specified (-mlong64, -mint64, -mlong32). The specs
+ set this option if such an option is used. */
+const char *mips_explicit_type_size_string;
/* Whether we are generating mips16 hard float code. In mips16 mode
we always set TARGET_SOFT_FLOAT; this variable is nonzero if
/* This variable is set by -mentry. We only care whether -mentry
appears or not, and using a string in this fashion is just a way to
avoid using up another bit in target_flags. */
-char *mips_entry_string;
+const char *mips_entry_string;
/* Whether we should entry and exit pseudo-ops in mips16 mode. */
int mips_entry;
initialized in override_options. */
REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;
+/* Mode used for saving/restoring general purpose registers. */
+static enum machine_mode gpr_mode;
+
/* Array giving truth value on whether or not a given hard register
can support a given mode. */
char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
int
small_int (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
}
int
large_int (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
HOST_WIDE_INT value;
return 0;
}
+/* Return truth value of whether OP is a register or the constant 0,
+ even in mips16 mode. */
+
+int
+true_reg_or_0_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ return INTVAL (op) == 0;
+
+ case CONST_DOUBLE:
+ return op == CONST0_RTX (mode);
+
+ case REG:
+ case SUBREG:
+ return register_operand (op, mode);
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
/* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */
int
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);
int
pc_or_label_operand (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (op == pc_rtx)
return 1;
int
call_insn_operand (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return (CONSTANT_ADDRESS_P (op)
|| (GET_CODE (op) == REG && op != arg_pointer_rtx
int
consttable_operand (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return CONSTANT_P (op);
}
int
m16_uimm3_b (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, 0x1, 0x8, 0);
}
int
m16_simm4_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x8, 0x7, 0);
}
int
m16_nsimm4_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x7, 0x8, 0);
}
int
m16_simm5_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x10, 0xf, 0);
}
int
m16_nsimm5_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0xf, 0x10, 0);
}
int
m16_uimm5_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3);
}
int
m16_nuimm5_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3);
}
int
m16_simm8_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x80, 0x7f, 0);
}
int
m16_nsimm8_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x7f, 0x80, 0);
}
int
m16_uimm8_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, 0x0, 0xff, 0);
}
int
m16_nuimm8_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0xff, 0x0, 0);
}
int
m16_uimm8_m1_1 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, - 0x1, 0xfe, 0);
}
int
m16_uimm8_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, 0x0, 0xff << 2, 3);
}
int
m16_nuimm8_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, (- 0xff) << 2, 0x0, 3);
}
int
m16_simm8_8 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7);
}
int
m16_nsimm8_8 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7);
}
int
m16_usym8_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op)
int
m16_usym5_4 (op, mode)
rtx op;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == SYMBOL_REF
&& SYMBOL_REF_FLAG (op)
/* Return the appropriate instructions to move one operand to another. */
-char *
+const char *
mips_move_1word (operands, insn, unsignedp)
rtx operands[];
rtx insn;
int unsignedp;
{
- char *ret = 0;
+ const char *ret = 0;
rtx op0 = operands[0];
rtx op1 = operands[1];
enum rtx_code code0 = GET_CODE (op0);
if (ret != (char *)0 && MEM_VOLATILE_P (op1))
{
- int i = strlen (ret);
+ size_t i = strlen (ret);
if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
abort ();
if (ret != 0 && MEM_VOLATILE_P (op0))
{
- int i = strlen (ret);
+ size_t i = strlen (ret);
if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
abort ();
\f
/* Return the appropriate instructions to move 2 words */
-char *
+const char *
mips_move_2words (operands, insn)
rtx operands[];
rtx insn;
{
- char *ret = 0;
+ const char *ret = 0;
rtx op0 = operands[0];
rtx op1 = operands[1];
enum rtx_code code0 = GET_CODE (operands[0]);
if (ret != 0 && MEM_VOLATILE_P (op1))
{
- int i = strlen (ret);
+ size_t i = strlen (ret);
if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
abort ();
if (ret != 0 && MEM_VOLATILE_P (op0))
{
- int i = strlen (ret);
+ size_t i = strlen (ret);
if (i > sizeof (volatile_buffer) - sizeof ("%{%}"))
abort ();
&& p_info->const_add != 0
&& ((p_info->unsignedp
? ((unsigned HOST_WIDE_INT) (value + p_info->const_add)
- > INTVAL (cmp1))
+ > (unsigned HOST_WIDE_INT) INTVAL (cmp1))
: (value + p_info->const_add) > INTVAL (cmp1))
!= (p_info->const_add > 0))))
cmp1 = force_reg (mode, cmp1);
we would get the wrong answer if we follow the usual path;
thus, x > 0xffffffffU would turn into x > 0U. */
if ((p_info->unsignedp
- ? (unsigned HOST_WIDE_INT) new > INTVAL (cmp1)
+ ? (unsigned HOST_WIDE_INT) new >
+ (unsigned HOST_WIDE_INT) INTVAL (cmp1)
: new > INTVAL (cmp1))
!= (p_info->const_add > 0))
{
if (TARGET_MEMCPY)
block_move_call (dest_reg, src_reg, bytes_rtx);
+ else if (constp && bytes <= 2 * MAX_MOVE_BYTES
+ && align == UNITS_PER_WORD)
+ move_by_pieces (orig_dest, orig_src, bytes, align);
+
else if (constp && bytes <= 2 * MAX_MOVE_BYTES)
emit_insn (gen_movstrsi_internal (change_address (orig_dest, BLKmode,
dest_reg),
BLOCK_MOVE_NOT_LAST Do all but the last store.
BLOCK_MOVE_LAST Do just the last store. */
-char *
+const char *
output_block_move (insn, operands, num_regs, move_type)
rtx insn;
rtx operands[];
rtx xoperands[10];
struct {
- char *load; /* load insn without nop */
- char *load_nop; /* load insn with trailing nop */
- char *store; /* store insn */
- char *final; /* if last_store used: NULL or swr */
- char *last_store; /* last store instruction */
+ const char *load; /* load insn without nop */
+ const char *load_nop; /* load insn with trailing nop */
+ const char *store; /* store insn */
+ const char *final; /* if last_store used: NULL or swr */
+ const char *last_store; /* last store instruction */
int offset; /* current offset */
enum machine_mode mode; /* mode to use on (MEM) */
} load_store[4];
the number of registers available. */
for (i = 4;
i < last_operand
- && safe_regs < (sizeof(xoperands) / sizeof(xoperands[0]));
+ && safe_regs < (int)(sizeof(xoperands) / sizeof(xoperands[0]));
i++)
if (! reg_mentioned_p (operands[i], operands[0])
&& ! reg_mentioned_p (operands[i], operands[1]))
}
}
- if (num_regs > sizeof (load_store) / sizeof (load_store[0]))
+ if (num_regs > (int)(sizeof (load_store) / sizeof (load_store[0])))
num_regs = sizeof (load_store) / sizeof (load_store[0]);
else if (num_regs < 1)
void
init_cumulative_args (cum, fntype, libname)
- CUMULATIVE_ARGS *cum; /* argument info to initialize */
- tree fntype; /* tree ptr for function decl */
- rtx libname; /* SYMBOL_REF of library name or 0 */
+ CUMULATIVE_ARGS *cum; /* argument info to initialize */
+ tree fntype; /* tree ptr for function decl */
+ rtx libname ATTRIBUTE_UNUSED; /* SYMBOL_REF of library name or 0 */
{
static CUMULATIVE_ARGS zero_cum;
tree param, next_param;
int named; /* whether or not the argument was named */
{
if (TARGET_DEBUG_E_MODE)
- fprintf (stderr,
- "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d )\n\n",
- cum->gp_reg_found, cum->arg_number, cum->arg_words,
- GET_MODE_NAME (mode), type, named);
+ {
+ fprintf (stderr,
+ "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
+ cum->gp_reg_found, cum->arg_number, cum->arg_words,
+ GET_MODE_NAME (mode));
+ fprintf (stderr, HOST_PTR_PRINTF, type);
+ fprintf (stderr, ", %d )\n\n", named);
+ }
cum->arg_number++;
switch (mode)
|| TREE_CODE (type) == QUAL_UNION_TYPE));
if (TARGET_DEBUG_E_MODE)
- fprintf (stderr,
- "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, 0x%.8x, %d ) = ",
- cum->gp_reg_found, cum->arg_number, cum->arg_words,
- GET_MODE_NAME (mode), type, named);
+ {
+ fprintf (stderr,
+ "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
+ cum->gp_reg_found, cum->arg_number, cum->arg_words,
+ GET_MODE_NAME (mode));
+ fprintf (stderr, HOST_PTR_PRINTF, type);
+ fprintf (stderr, ", %d ) = ", named);
+ }
+
cum->last_arg_fp = 0;
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)
/* Drops through. */
case BLKmode:
- if (type != (tree)0 && TYPE_ALIGN (type) > BITS_PER_WORD
+ if (type != (tree)0 && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD
&& ! TARGET_64BIT && mips_abi != ABI_EABI)
cum->arg_words += (cum->arg_words & 1);
regbase = GP_ARG_FIRST;
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
{
CUMULATIVE_ARGS *cum; /* current arg information */
enum machine_mode mode; /* current arg mode */
tree type; /* type of the argument or 0 if lib support */
- int named; /* != 0 for normal args, == 0 for ... args */
+ int named ATTRIBUTE_UNUSED;/* != 0 for normal args, == 0 for ... args */
{
if ((mode == BLKmode
|| GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
\f
/* Abort after printing out a specific insn. */
-void
+static void
abort_with_insn (insn, reason)
rtx insn;
- char *reason;
+ const char *reason;
{
error (reason);
debug_rtx (insn);
if (mips_isa_string == 0)
mips_isa = MIPS_ISA_DEFAULT;
- else if (isdigit (*mips_isa_string))
+ else if (ISDIGIT (*mips_isa_string))
{
mips_isa = atoi (mips_isa_string);
if (mips_isa == 16)
}
#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")
- || ! strcmp (mips_abi_string, "o32"))
+ 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")
- || ! strcmp (mips_abi_string, "n64"))
+ else if (! strcmp (mips_abi_string, "64"))
mips_abi = ABI_64;
else if (! strcmp (mips_abi_string, "eabi"))
mips_abi = ABI_EABI;
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);
}
if (mips_abi == ABI_32)
target_flags &= ~ (MASK_FLOAT64|MASK_64BIT);
- /* In the EABI in 64 bit mode, longs and pointers are 64 bits. Likewise
- for the SGI Irix6 N64 ABI. */
- if ((mips_abi == ABI_EABI && TARGET_64BIT)
- || mips_abi == ABI_64)
+ /* If no type size setting options (-mlong64,-mint64,-mlong32) were used
+ then set the type sizes. In the EABI in 64 bit mode, longs and
+ pointers are 64 bits. Likewise for the SGI Irix6 N64 ABI. */
+ if (mips_explicit_type_size_string == NULL
+ && ((mips_abi == ABI_EABI && TARGET_64BIT)
+ || mips_abi == ABI_64))
target_flags |= MASK_LONG64;
/* ??? This doesn't work yet, so don't let people try to use it. */
else
{
- char *p = mips_cpu_string;
+ const char *p = mips_cpu_string;
int seen_v = 0;
/* We need to cope with the various "vr" prefixes for the NEC 4300
mips_cpu = PROCESSOR_DEFAULT;
switch (*p)
{
- /* start-sanitize-tx19 */
- case '1':
- if (!strcmp (p, "1900"))
- mips_cpu = PROCESSOR_R3900;
- break;
- /* end-sanitize-tx19 */
-
case '2':
if (!strcmp (p, "2000") || !strcmp (p, "2k") || !strcmp (p, "2K"))
mips_cpu = PROCESSOR_R3000;
/* make sure sizes of ints/longs/etc. are ok */
if (mips_isa < 3)
{
- if (TARGET_INT64)
- fatal ("Only MIPS-III or MIPS-IV CPUs can support 64 bit ints");
-
- else if (TARGET_LONG64)
- fatal ("Only MIPS-III or MIPS-IV CPUs can support 64 bit longs");
-
- else if (TARGET_FLOAT64)
+ if (TARGET_FLOAT64)
fatal ("Only MIPS-III or MIPS-IV CPUs can support 64 bit fp registers");
else if (TARGET_64BIT)
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. */
mips_hard_regno_mode_ok[(int)mode][regno] = temp;
}
}
+
+ /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
+ initialized yet, so we can't use that here. */
+ gpr_mode = TARGET_64BIT ? DImode : SImode;
}
/* On the mips16, we want to allocate $24 (T_REG) before other
? compute_frame_size (get_frame_size ())
: current_frame_info.total_size;
+ /* MIPS16 frame is smaller */
+ if (frame_pointer_needed && TARGET_MIPS16)
+ frame_size -= current_function_outgoing_args_size;
+
offset = offset - frame_size;
}
int
mips_output_external (file, decl, name)
- FILE *file;
+ FILE *file ATTRIBUTE_UNUSED;
tree decl;
char *name;
{
make_temp_file ()
{
FILE *stream;
- char *base = getenv ("TMPDIR");
+ const char *base = getenv ("TMPDIR");
int len;
if (base == 0)
void
final_prescan_insn (insn, opvec, noperands)
rtx insn;
- rtx opvec[];
- int noperands;
+ rtx opvec[] ATTRIBUTE_UNUSED;
+ int noperands ATTRIBUTE_UNUSED;
{
if (dslots_number_nops > 0)
{
/* 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
fatal_io_error (temp_filename);
while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
- if (fwrite (buffer, 1, len, file) != len)
+ if ((int) fwrite (buffer, 1, len, file) != len)
pfatal_with_name (asm_file_name);
if (len < 0)
|| (GET_MODE_SIZE (DECL_MODE (DECL_RESULT (current_function_decl)))
<= 4))))
{
- gp_reg_size += UNITS_PER_WORD;
+ gp_reg_size += GET_MODE_SIZE (gpr_mode);
mask |= 1L << (regno - GP_REG_FIRST);
/* The entry and exit pseudo instructions can not save $17
fp_bits = 3;
}
- for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno += fp_inc)
+ /* This loop must iterate over the same space as its companion in
+ save_restore_regs. */
+ for (regno = (FP_REG_LAST - fp_inc + 1);
+ regno >= FP_REG_FIRST;
+ regno -= fp_inc)
{
if (regs_ever_live[regno] && !call_used_regs[regno])
{
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. */
top of the stack. */
if (! mips_entry)
offset = (args_size + extra_size + var_size
- + gp_reg_size - UNITS_PER_WORD);
+ + gp_reg_size - GET_MODE_SIZE (gpr_mode));
else
- offset = total_size - UNITS_PER_WORD;
+ offset = total_size - GET_MODE_SIZE (gpr_mode);
+
current_frame_info.gp_sp_offset = offset;
current_frame_info.gp_save_offset = offset - total_size;
}
gp_offset = current_frame_info.gp_sp_offset;
end_offset
- = gp_offset - (current_frame_info.gp_reg_size - UNITS_PER_WORD);
+ = gp_offset - (current_frame_info.gp_reg_size
+ - GET_MODE_SIZE (gpr_mode));
if (gp_offset < 0 || end_offset < 0)
fatal ("gp_offset (%ld) or end_offset (%ld) is less than zero.",
- gp_offset, end_offset);
+ (long) gp_offset, (long) end_offset);
/* If we see a large frame in mips16 mode, we save the registers
before adjusting the stack pointer, and load them afterward. */
RTX_FRAME_RELATED_P (insn) = 1;
}
else
- fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\t%s\t%s,%s,%s\n",
- reg_names[MIPS_TEMP2_REGNUM],
- base_offset, base_offset,
- Pmode == DImode ? "daddu" : "addu",
- reg_names[MIPS_TEMP2_REGNUM],
- reg_names[MIPS_TEMP2_REGNUM],
- reg_names[STACK_POINTER_REGNUM]);
+ {
+ fprintf (file, "\tli\t%s,0x%.08lx\t# ",
+ reg_names[MIPS_TEMP2_REGNUM], (long) base_offset);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, base_offset);
+ fprintf (file, "\n\t%s\t%s,%s,%s\n",
+ Pmode == DImode ? "daddu" : "addu",
+ reg_names[MIPS_TEMP2_REGNUM],
+ reg_names[MIPS_TEMP2_REGNUM],
+ reg_names[STACK_POINTER_REGNUM]);
+ }
}
/* When we restore the registers in MIPS16 mode, then if we are
{
rtx reg_rtx;
rtx mem_rtx
- = gen_rtx (MEM, word_mode,
+ = gen_rtx (MEM, gpr_mode,
gen_rtx (PLUS, Pmode, base_reg_rtx,
GEN_INT (gp_offset - base_offset)));
$31, so we load $7 instead, and work things out
in the caller. */
if (TARGET_MIPS16 && ! store_p && regno == GP_REG_FIRST + 31)
- reg_rtx = gen_rtx (REG, word_mode, GP_REG_FIRST + 7);
+ reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 7);
/* The mips16 sometimes needs to save $18. */
else if (TARGET_MIPS16
&& regno != GP_REG_FIRST + 31
&& ! M16_REG_P (regno))
{
if (! store_p)
- reg_rtx = gen_rtx (REG, word_mode, 6);
+ reg_rtx = gen_rtx (REG, gpr_mode, 6);
else
{
- reg_rtx = gen_rtx (REG, word_mode, 3);
+ reg_rtx = gen_rtx (REG, gpr_mode, 3);
emit_move_insn (reg_rtx,
- gen_rtx (REG, word_mode, regno));
+ gen_rtx (REG, gpr_mode, regno));
}
}
else
- reg_rtx = gen_rtx (REG, word_mode, regno);
+ reg_rtx = gen_rtx (REG, gpr_mode, regno);
if (store_p)
{
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);
if (TARGET_MIPS16
&& regno != GP_REG_FIRST + 31
&& ! M16_REG_P (regno))
- emit_move_insn (gen_rtx (REG, word_mode, regno),
+ emit_move_insn (gen_rtx (REG, gpr_mode, regno),
reg_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;
reg_names[r], reg_names[regno]);
}
}
- fprintf (file, "\t%s\t%s,%ld(%s)\n",
+ fprintf (file, "\t%s\t%s,",
(TARGET_64BIT
? (store_p) ? "sd" : "ld"
: (store_p) ? "sw" : "lw"),
- reg_names[r],
- gp_offset - base_offset,
- reg_names[REGNO(base_reg_rtx)]);
+ reg_names[r]);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ gp_offset - base_offset);
+ fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
if (! store_p
&& TARGET_MIPS16
&& regno != GP_REG_FIRST + 31
}
}
- gp_offset -= UNITS_PER_WORD;
+ gp_offset -= GET_MODE_SIZE (gpr_mode);
}
}
else
if (fp_offset < 0 || end_offset < 0)
fatal ("fp_offset (%ld) or end_offset (%ld) is less than zero.",
- fp_offset, end_offset);
+ (long) fp_offset, (long) end_offset);
else if (fp_offset < 32768)
base_reg_rtx = stack_pointer_rtx, base_offset = 0;
RTX_FRAME_RELATED_P (insn) = 1;
}
else
- fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\t%s\t%s,%s,%s\n",
- reg_names[MIPS_TEMP2_REGNUM],
- base_offset, base_offset,
- Pmode == DImode ? "daddu" : "addu",
- reg_names[MIPS_TEMP2_REGNUM],
- reg_names[MIPS_TEMP2_REGNUM],
- reg_names[STACK_POINTER_REGNUM]);
+ {
+ fprintf (file, "\tli\t%s,0x%.08lx\t# ",
+ reg_names[MIPS_TEMP2_REGNUM], (long) base_offset);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, base_offset);
+ fprintf (file, "\n\t%s\t%s,%s,%s\n",
+ Pmode == DImode ? "daddu" : "addu",
+ reg_names[MIPS_TEMP2_REGNUM],
+ reg_names[MIPS_TEMP2_REGNUM],
+ reg_names[STACK_POINTER_REGNUM]);
+ }
}
- for (regno = FP_REG_LAST-1; regno >= FP_REG_FIRST; regno -= fp_inc)
+ /* This loop must iterate over the same space as its companion in
+ compute_frame_size. */
+ for (regno = (FP_REG_LAST - fp_inc + 1);
+ regno >= FP_REG_FIRST;
+ regno -= fp_inc)
if (BITSET_P (fmask, regno - FP_REG_FIRST))
{
if (file == 0)
emit_move_insn (reg_rtx, mem_rtx);
}
else
- fprintf (file, "\t%s\t%s,%ld(%s)\n",
- (TARGET_SINGLE_FLOAT
- ? (store_p ? "s.s" : "l.s")
- : (store_p ? "s.d" : "l.d")),
- reg_names[regno],
- fp_offset - base_offset,
- reg_names[REGNO(base_reg_rtx)]);
+ {
+ fprintf (file, "\t%s\t%s,",
+ (TARGET_SINGLE_FLOAT
+ ? (store_p ? "s.s" : "l.s")
+ : (store_p ? "s.d" : "l.d")),
+ reg_names[regno]);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fp_offset - base_offset);
+ fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
+ }
fp_offset -= fp_size;
}
void
function_prologue (file, size)
FILE *file;
- int size;
+ int size ATTRIBUTE_UNUSED;
{
#ifndef FUNCTION_NAME_ALREADY_DECLARED
char *fnname;
if (!flag_inhibit_size_directive)
{
+ /* .frame FRAMEREG, FRAMESIZE, RETREG */
fprintf (file,
"\t.frame\t%s,%ld,%s\t\t# vars= %ld, regs= %d/%d, args= %d, extra= %ld\n",
(reg_names[(frame_pointer_needed)
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
- tsize, reg_names[31 + GP_REG_FIRST],
+ ((frame_pointer_needed && TARGET_MIPS16)
+ ? (tsize - current_function_outgoing_args_size)
+ : tsize),
+ reg_names[31 + GP_REG_FIRST],
current_frame_info.var_size,
current_frame_info.num_gp,
current_frame_info.num_fp,
current_function_outgoing_args_size,
current_frame_info.extra_size);
+ /* .mask MASK, GPOFFSET; .fmask FPOFFSET */
fprintf (file, "\t.mask\t0x%08lx,%ld\n\t.fmask\t0x%08lx,%ld\n",
current_frame_info.mask,
current_frame_info.gp_save_offset,
current_frame_info.fmask,
current_frame_info.fp_save_offset);
+
+ /* Require:
+ OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg.
+ HIGHEST_GP_SAVED == *FRAMEREG + FRAMESIZE + GPOFFSET => can find saved regs. */
}
if (mips_entry && ! mips_can_use_return_insn ())
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 (offset != 0)
ptr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (offset));
- emit_move_insn (gen_rtx (MEM, word_mode, ptr),
- gen_rtx (REG, word_mode, regno));
- offset += UNITS_PER_WORD;
+ emit_move_insn (gen_rtx (MEM, gpr_mode, ptr),
+ gen_rtx (REG, gpr_mode, regno));
+
+ offset += GET_MODE_SIZE (gpr_mode);
}
}
moment. */
if (TARGET_MIPS16 && BITSET_P (current_frame_info.mask, 18))
{
- rtx reg_rtx = gen_rtx (REG, word_mode, GP_REG_FIRST + 3);
+ rtx reg_rtx = gen_rtx (REG, gpr_mode, GP_REG_FIRST + 3);
long gp_offset, base_offset;
gp_offset = current_frame_info.gp_sp_offset;
base_offset = 0;
start_sequence ();
emit_move_insn (reg_rtx,
- gen_rtx (REG, word_mode, GP_REG_FIRST + 18));
- emit_move_insn (gen_rtx (MEM, word_mode,
+ gen_rtx (REG, gpr_mode, GP_REG_FIRST + 18));
+ emit_move_insn (gen_rtx (MEM, gpr_mode,
gen_rtx (PLUS, Pmode, stack_pointer_rtx,
GEN_INT (gp_offset
- base_offset))),
/* 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)));
}
void
function_epilogue (file, size)
- FILE *file;
- HOST_WIDE_INT size;
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
{
char *fnname;
dslots_load_total += num_regs;
fprintf (stderr,
- "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d",
+ "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3d reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d",
name, frame_pointer_needed ? 'y' : 'n',
(current_frame_info.mask & RA_MASK) != 0 ? 'n' : 'y',
current_function_calls_alloca ? 'y' : 'n',
/* 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 ());
void
mips_select_rtx_section (mode, x)
enum machine_mode mode;
- rtx x;
+ rtx x ATTRIBUTE_UNUSED;
{
if (TARGET_MIPS16)
{
}
/* Choose the section to use for DECL. RELOC is true if its value contains
- any relocatable expression. */
+ any relocatable expression.
+
+ Some of the logic used here needs to be replicated in
+ ENCODE_SECTION_INFO in mips.h so that references to these symbols
+ are done correctly. Specifically, at least all symbols assigned
+ here to rom (.text and/or .rodata) must not be referenced via
+ ENCODE_SECTION_INFO with %gprel, as the rom might be too far away.
+
+ If you need to make a change here, you probably should check
+ ENCODE_SECTION_INFO to see if it needs a similar change. */
void
mips_select_section (decl, reloc)
rtx
mips_function_value (valtype, func)
tree valtype;
- tree func;
+ tree func ATTRIBUTE_UNUSED;
{
int reg = GP_RETURN;
enum machine_mode mode = TYPE_MODE (valtype);
}
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
function_arg_pass_by_reference (cum, mode, type, named)
- CUMULATIVE_ARGS *cum;
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
enum machine_mode mode;
tree type;
- int named;
+ int named ATTRIBUTE_UNUSED;
{
int size;
to a general register, or when copying from register 0. */
if (class == HILO_REG && regno != GP_REG_FIRST + 0)
return ((! in_p
- && GP_REG_P (regno)
+ && gp_reg_p
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
- ? NO_REGS : GR_REGS);
+ ? NO_REGS : gr_regs);
else if (regno == HILO_REGNUM)
return ((in_p
- && class == GR_REGS
+ && class == gr_regs
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
- ? NO_REGS : GR_REGS);
+ ? NO_REGS : gr_regs);
/* Copying from HI or LO to anywhere other than a general register
requires a general register. */
/* We can't really copy to HI or LO at all in mips16 mode. */
return M16_REGS;
}
- return gp_reg_p ? NO_REGS : GR_REGS;
+ return gp_reg_p ? NO_REGS : gr_regs;
}
if (MD_REG_P (regno))
{
/* We can't really copy to HI or LO at all in mips16 mode. */
return M16_REGS;
}
- return class == gr_regs ? NO_REGS : GR_REGS;
+ return class == gr_regs ? NO_REGS : gr_regs;
}
/* We can only copy a value to a condition code register from a
int fp_code;
int from_fp_p;
{
- char *s;
+ const char *s;
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)
{
if ((fparg & 1) != 0)
++fparg;
- fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
- reg_names[gparg], reg_names[fparg + 1], s,
- reg_names[gparg + 1], reg_names[fparg]);
+ if (TARGET_BIG_ENDIAN)
+ fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg + 1], s,
+ reg_names[gparg + 1], reg_names[fparg]);
+ else
+ fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg], s,
+ reg_names[gparg + 1], reg_names[fparg + 1]);
++gparg;
++fparg;
}
&& 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
reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]);
else
{
- fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
- reg_names[GP_REG_FIRST + 2],
- reg_names[FP_REG_FIRST + 1]);
- fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
- reg_names[GP_REG_FIRST + 3],
- reg_names[FP_REG_FIRST + 0]);
+ if (TARGET_BIG_ENDIAN)
+ {
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 2],
+ reg_names[FP_REG_FIRST + 1]);
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 3],
+ reg_names[FP_REG_FIRST + 0]);
+ }
+ else
+ {
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 2],
+ reg_names[FP_REG_FIRST + 0]);
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 3],
+ reg_names[FP_REG_FIRST + 1]);
+ }
}
fprintf (asm_out_file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 18]);
/* As above, we can't fill the delay slot. */
int
extend_operator (x, mode)
rtx x;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (x);
return code == SIGN_EXTEND || code == ZERO_EXTEND;
int
highpart_shift_operator (x, mode)
rtx x;
- enum machine_mode mode;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
enum rtx_code code = GET_CODE (x);
return (code == LSHIFTRT