/* Subroutines for insn-output.c for MIPS
Contributed by A. Lichnewsky, lich@inria.inria.fr.
Changes by Michael Meissner, meissner@osf.org.
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
+ Brendan Eich, brendan@microunity.com.
+ Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* ??? The TARGET_FP_CALL_32 macros are intended to simulate a 32 bit
+ calling convention in 64 bit mode. It doesn't work though, and should
+ be replaced with something better designed. */
+
#include "config.h"
#include "rtl.h"
#include "regs.h"
/* Generating calls to position independent functions? */
enum mips_abicalls_type mips_abicalls;
+/* High and low marks for floating point values which we will accept
+ as legitimate constants for LEGITIMATE_CONSTANT_P. These are
+ initialized in override_options. */
+REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;
+
/* Array to RTX class classification. At present, we care about
whether the operator is an add-type operator, or a divide/modulus,
and if divide/modulus, whether it is unsigned. This is for the
char mips_sw_reg_names[][8] =
{
- "$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
- "t8", "t9", "k0", "k1", "gp", "sp", "$fp", "ra",
+ "$zero","$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
+ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
+ "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
if (((unsigned long)(value + 32768)) <= 32767) /* subu reg,$r0,value */
return FALSE;
- if ((value & 0xffff0000) == value) /* lui reg,value>>16 */
+ if ((value & 0x0000ffff) == 0 /* lui reg,value>>16 */
+ && ((value & ~2147483647) == 0 /* signed value */
+ || (value & ~2147483647) == ~2147483647))
return FALSE;
return TRUE;
return (INTVAL (op) == 0);
case CONST_DOUBLE:
- if (CONST_DOUBLE_HIGH (op) != 0 || CONST_DOUBLE_LOW (op) != 0)
+ if (op != CONST0_RTX (mode))
return FALSE;
return TRUE;
if (mode != SFmode && mode != DFmode)
return FALSE;
- if (CONST_DOUBLE_HIGH (op) == 0 && CONST_DOUBLE_LOW (op) == 0)
+ if (op == CONST0_RTX (mode))
return TRUE;
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
if (TARGET_MIPS_AS) /* gas doesn't like li.d/li.s yet */
{
- union { double d; int i[2]; } u;
- double d;
-
- u.i[0] = CONST_DOUBLE_LOW (op);
- u.i[1] = CONST_DOUBLE_HIGH (op);
- d = u.d;
-
- if (d != d)
- return FALSE; /* NAN */
+ REAL_VALUE_TYPE d;
- if (d < 0.0)
- d = - d;
+ REAL_VALUE_FROM_CONST_DOUBLE (d, op);
- /* Rather than trying to get the accuracy down to the last bit,
- just use approximate ranges. */
+ if (REAL_VALUE_ISNAN (d))
+ return FALSE;
- if (mode == DFmode && d > 1.0e-300 && d < 1.0e300)
- return TRUE;
+ if (REAL_VALUE_NEGATIVE (d))
+ d = REAL_VALUE_NEGATE (d);
- if (mode == SFmode && d > 1.0e-38 && d < 1.0e+38)
- return TRUE;
+ if (mode == DFmode)
+ {
+ if (REAL_VALUES_LESS (d, dfhigh)
+ && REAL_VALUES_LESS (dflow, d))
+ return TRUE;
+ }
+ else
+ {
+ if (REAL_VALUES_LESS (d, sfhigh)
+ && REAL_VALUES_LESS (sflow, d))
+ return TRUE;
+ }
}
-#endif
return FALSE;
}
return FALSE;
/* dword operations really put out 2 instructions, so eliminate them. */
- if (GET_MODE_SIZE (GET_MODE (op)) > (HAVE_64BIT_P () ? 8 : 4))
+ if (GET_MODE_SIZE (GET_MODE (op)) > UNITS_PER_WORD)
return FALSE;
/* Decode the address now. */
case CONST:
/* If -G 0, we can never have a GP relative memory operation.
Also, save some time if not optimizing. */
- if (mips_section_threshold == 0 || !optimize || !TARGET_GP_OPT)
+ if (!TARGET_GP_OPT)
return FALSE;
{
rtx offset = const0_rtx;
- addr = eliminate_constant_term (addr, &offset);
+ addr = eliminate_constant_term (XEXP (addr, 0), &offset);
if (GET_CODE (op) != SYMBOL_REF)
return FALSE;
/* let's be paranoid.... */
- if (INTVAL (offset) < 0 || INTVAL (offset) > 0xffff)
+ if (! SMALL_INT (offset))
return FALSE;
}
/* fall through */
mode = GET_MODE (set_reg);
dslots_number_nops = num_nops;
- mips_load_reg = set_reg;
- mips_load_reg2 = (mode == DImode || mode == DFmode)
- ? gen_rtx (REG, SImode, REGNO (set_reg) + 1)
- : (rtx)0;
+ mips_load_reg = set_reg;
+ if (GET_MODE_SIZE (mode)
+ > (FP_REG_P (set_reg) ? UNITS_PER_FPREG : UNITS_PER_WORD))
+ mips_load_reg2 = gen_rtx (REG, SImode, REGNO (set_reg) + 1);
+ else
+ mips_load_reg2 = 0;
if (type == DELAY_HILO)
{
target, so zero/sign extend can use this code as well. */
switch (GET_MODE (op1))
{
- default: break;
- case SFmode: ret = "lw\t%0,%1"; break;
- case SImode: ret = "lw\t%0,%1"; break;
- case HImode: ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; break;
- case QImode: ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; break;
+ default:
+ break;
+ case SFmode:
+ ret = "lw\t%0,%1";
+ break;
+ case SImode:
+ ret = ((unsignedp && TARGET_64BIT)
+ ? "lwu\t%0,%1"
+ : "lw\t%0,%1");
+ break;
+ case HImode:
+ ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";
+ break;
+ case QImode:
+ ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";
+ break;
}
}
else if (code1 == CONST_DOUBLE && mode == SFmode)
{
- if (CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)
+ if (op1 == CONST0_RTX (SFmode))
{
if (GP_REG_P (regno0))
ret = "move\t%0,%.";
if (INTVAL (offset) == 0)
{
delay = DELAY_LOAD;
- ret = "lw\t%0,%2";
+ ret = (unsignedp && TARGET_64BIT
+ ? "lwu\t%0,%2"
+ : "lw\t%0,%2");
}
else
{
dslots_load_total++;
operands[3] = offset;
- ret = (SMALL_INT (offset))
- ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3"
- : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]";
+ if (unsignedp && TARGET_64BIT)
+ ret = (SMALL_INT (offset))
+ ? "lwu\t%0,%2%#\n\tadd\t%0,%0,%3"
+ : "lwu\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]";
+ else
+ ret = (SMALL_INT (offset))
+ ? "lw\t%0,%2%#\n\tadd\t%0,%0,%3"
+ : "lw\t%0,%2%#\n\t%[li\t%@,%3\n\tadd\t%0,%0,%@%]";
}
}
}
}
}
- else if (code1 == CONST_DOUBLE && CONST_DOUBLE_HIGH (op1) == 0 && CONST_DOUBLE_LOW (op1) == 0)
+ else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))
{
switch (mode)
{
else
{
delay = DELAY_LOAD;
- ret = (TARGET_FLOAT64)
- ? "dmtc1\t%1,%0"
- : "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0";
+ if (TARGET_64BIT)
+ {
+#ifdef TARGET_FP_CALL_32
+ if (FP_CALL_GP_REG_P (regno1))
+ ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tdmtc1\t%1,%0";
+ else
+#endif
+ ret = "dmtc1\t%1,%0";
+ }
+ else
+ ret = "mtc1\t%L1,%0\n\tmtc1\t%M1,%D0";
}
}
else if (FP_REG_P (regno1))
{
delay = DELAY_LOAD;
- ret = (TARGET_FLOAT64)
- ? "dmfc1\t%0,%1"
- : "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1";
+ if (TARGET_64BIT)
+ {
+#ifdef TARGET_FP_CALL_32
+ if (FP_CALL_GP_REG_P (regno0))
+ ret = "dmfc1\t%0,%1\n\tmfc1\t%D0,%1\n\tdsrl\t%0,32";
+ else
+#endif
+ ret = "dmfc1\t%0,%1";
+ }
+ else
+ ret = "mfc1\t%L0,%1\n\tmfc1\t%M0,%D1";
}
else if (MD_REG_P (regno0) && GP_REG_P (regno1))
{
delay = DELAY_HILO;
- ret = "mthi\t%M1\n\tmtlo\t%L1";
+ if (TARGET_64BIT)
+ ret = "mt%0\t%1";
+ else
+ ret = "mthi\t%M1\n\tmtlo\t%L1";
}
else if (GP_REG_P (regno0) && MD_REG_P (regno1))
{
delay = DELAY_HILO;
- ret = "mfhi\t%M0\n\tmflo\t%L0";
+ if (TARGET_64BIT)
+ ret = "mf%1\t%0";
+ else
+ ret = "mfhi\t%M0\n\tmflo\t%L0";
}
+ else if (TARGET_64BIT)
+ ret = "move\t%0,%1";
+
else if (regno0 != (regno1+1))
ret = "move\t%0,%1\n\tmove\t%D0,%D1";
else if (code1 == CONST_DOUBLE)
{
- if (CONST_DOUBLE_HIGH (op1) != 0 || CONST_DOUBLE_LOW (op1) != 0)
+ if (op1 != CONST0_RTX (GET_MODE (op1)))
{
if (GET_MODE (op1) == DFmode)
{
delay = DELAY_LOAD;
- ret = "li.d\t%0,%1";
+#ifdef TARGET_FP_CALL_32
+ if (FP_CALL_GP_REG_P (regno0))
+ ret = "li.d\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32";
+ else
+#endif
+ ret = "li.d\t%0,%1";
}
+ else if (TARGET_64BIT)
+ ret = "li\t%0,%1";
+
else
{
operands[2] = GEN_INT (CONST_DOUBLE_LOW (op1));
else
{
if (GP_REG_P (regno0))
- ret = "move\t%0,%.\n\tmove\t%D0,%.";
+ ret = (TARGET_64BIT
+#ifdef TARGET_FP_CALL_32
+ && ! FP_CALL_GP_REG_P (regno0)
+#endif
+ )
+ ? "move\t%0,%."
+ : "move\t%0,%.\n\tmove\t%D0,%.";
else if (FP_REG_P (regno0))
{
delay = DELAY_LOAD;
- ret = (TARGET_FLOAT64)
+ ret = (TARGET_64BIT)
? "dmtc1\t%.,%0"
: "mtc1\t%.,%0\n\tmtc1\t%.,%D0";
}
else if (code1 == CONST_INT && INTVAL (op1) == 0)
{
if (GP_REG_P (regno0))
- ret = "move\t%0,%.\n\tmove\t%D0,%.";
+ ret = (TARGET_64BIT)
+ ? "move\t%0,%."
+ : "move\t%0,%.\n\tmove\t%D0,%.";
else if (FP_REG_P (regno0))
{
delay = DELAY_LOAD;
- ret = (TARGET_FLOAT64)
+ ret = (TARGET_64BIT)
? "dmtc1\t%.,%0"
: "mtc1\t%.,%0\n\tmtc1\t%.,%D0";
}
else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))
{
- operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);
- ret = "li\t%M0,%2\n\tli\t%L0,%1";
+ if (TARGET_64BIT)
+ ret = "li\t%0,%1";
+ else
+ {
+ operands[2] = GEN_INT (INTVAL (operands[1]) >= 0 ? 0 : -1);
+ ret = "li\t%M0,%2\n\tli\t%L0,%1";
+ }
}
else if (code1 == MEM)
if (FP_REG_P (regno0))
ret = "l.d\t%0,%1";
+ else if (TARGET_64BIT)
+ {
+#ifdef TARGET_FP_CALL_32
+ if (FP_CALL_GP_REG_P (regno0))
+ {
+ if (offsettable_address_p (FALSE, SImode, op1))
+ ret = "lwu\t%0,%1\n\tlwu\t%D0,4+%1";
+ else
+ ret = "ld\t%0,%1\n\tdsll\t%D0,%0,32\n\tdsrl\t%D0,32\n\tdsrl\t%0,32";
+ }
+ else
+#endif
+ ret = "ld\t%0,%1";
+ }
+
else if (offsettable_address_p (1, DFmode, XEXP (op1, 0)))
{
operands[2] = adj_offsettable_operand (op1, 4);
ret = volatile_buffer;
}
}
+
+ else if (code1 == LABEL_REF
+ || code1 == SYMBOL_REF
+ || code1 == CONST)
+ {
+ if (! TARGET_64BIT)
+ abort ();
+ return mips_move_1word (operands, insn, 0);
+ }
}
else if (code0 == MEM)
if (FP_REG_P (regno1))
ret = "s.d\t%1,%0";
+ else if (TARGET_64BIT)
+ {
+#ifdef TARGET_FP_CALL_32
+ if (FP_CALL_GP_REG_P (regno1))
+ ret = "dsll\t%1,32\n\tor\t%1,%D1\n\tsd\t%1,%0";
+ else
+#endif
+ ret = "sd\t%1,%0";
+ }
+
else if (offsettable_address_p (1, DFmode, XEXP (op0, 0)))
{
operands[2] = adj_offsettable_operand (op0, 4);
}
}
- else if (code1 == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op1) == 0
- && CONST_DOUBLE_LOW (op1) == 0
- && offsettable_address_p (1, DFmode, XEXP (op0, 0)))
+ else if (((code1 == CONST_INT && INTVAL (op1) == 0)
+ || (code1 == CONST_DOUBLE
+ && op1 == CONST0_RTX (GET_MODE (op1))))
+ && (TARGET_64BIT
+ || offsettable_address_p (1, DFmode, XEXP (op0, 0))))
{
- if (TARGET_FLOAT64)
+ if (TARGET_64BIT)
ret = "sd\t%.,%0";
else
{
case CONST:
{
rtx offset = const0_rtx;
- addr = eliminate_constant_term (addr, &offset);
+ addr = eliminate_constant_term (XEXP (addr, 0), &offset);
if (GET_CODE (addr) == LABEL_REF)
return 2;
if (GET_CODE (addr) != SYMBOL_REF)
return 4;
- if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
+ if (! SMALL_INT (offset))
return 2;
}
/* fall through */
break;
case CONST_INT:
- {
- int value = INTVAL (plus1);
- return (value < -32768 || value > 32767) ? 2 : 1;
- }
+ return (SMALL_INT (plus1) ? 1 : 2);
case CONST:
case SYMBOL_REF:
\f
/* Generate the code to compare two integer values. The return value is:
(reg:SI xx) The pseudo register the comparison is in
- (rtx)0 No register, generate a simple branch. */
+ (rtx)0 No register, generate a simple branch.
+
+ ??? This is called with result nonzero by the Scond patterns in
+ mips.md. These patterns are called with a target in the mode of
+ the Scond instruction pattern. Since this must be a constant, we
+ must use SImode. This means that if RESULT is non-zero, it will
+ always be an SImode register, even if TARGET_64BIT is true. We
+ cope with this by calling convert_move rather than emit_move_insn.
+ This will sometimes lead to an unnecessary extension of the result;
+ for example:
+
+ long long
+ foo (long long i)
+ {
+ return i < 5;
+ }
+
+ */
rtx
gen_int_relational (test_code, result, cmp0, cmp1, p_invert)
};
enum internal_test test;
+ enum machine_mode mode;
struct cmp_info *p_info;
int branch_p;
int eqne_p;
p_info = &info[ (int)test ];
eqne_p = (p_info->test_code == XOR);
+ mode = GET_MODE (cmp0);
+ if (mode == VOIDmode)
+ mode = GET_MODE (cmp1);
+
/* Eliminate simple branches */
branch_p = (result == (rtx)0);
if (branch_p)
}
/* allocate a pseudo to calculate the value in. */
- result = gen_reg_rtx (SImode);
+ result = gen_reg_rtx (mode);
}
/* Make sure we can handle any constants given to us. */
if (GET_CODE (cmp0) == CONST_INT)
- cmp0 = force_reg (SImode, cmp0);
+ cmp0 = force_reg (mode, cmp0);
if (GET_CODE (cmp1) == CONST_INT)
{
HOST_WIDE_INT value = INTVAL (cmp1);
- if (value < p_info->const_low || value > p_info->const_high)
- cmp1 = force_reg (SImode, cmp1);
+ if (value < p_info->const_low
+ || value > p_info->const_high
+ /* ??? Why? And why wasn't the similar code below modified too? */
+ || (TARGET_64BIT
+ && HOST_BITS_PER_WIDE_INT < 64
+ && p_info->const_add != 0
+ && ((p_info->unsignedp
+ ? ((unsigned HOST_WIDE_INT) (value + p_info->const_add)
+ > INTVAL (cmp1))
+ : (value + p_info->const_add) > INTVAL (cmp1))
+ != (p_info->const_add > 0))))
+ cmp1 = force_reg (mode, cmp1);
}
/* See if we need to invert the result. */
reg = cmp0;
else
{
- reg = (invert || eqne_p) ? gen_reg_rtx (SImode) : result;
- emit_move_insn (reg, gen_rtx (p_info->test_code, SImode, cmp0, cmp1));
+ reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
+ convert_move (reg, gen_rtx (p_info->test_code, mode, cmp0, cmp1), 0);
}
if (test == ITEST_NE)
{
- emit_move_insn (result, gen_rtx (GTU, SImode, reg, const0_rtx));
+ convert_move (result, gen_rtx (GTU, mode, reg, const0_rtx), 0);
invert = FALSE;
}
else if (test == ITEST_EQ)
{
- reg2 = (invert) ? gen_reg_rtx (SImode) : result;
- emit_move_insn (reg2, gen_rtx (LTU, SImode, reg, const1_rtx));
+ reg2 = (invert) ? gen_reg_rtx (mode) : result;
+ convert_move (reg2, gen_rtx (LTU, mode, reg, const1_rtx), 0);
reg = reg2;
}
if (invert)
- emit_move_insn (result, gen_rtx (XOR, SImode, reg, const1_rtx));
+ convert_move (result, gen_rtx (XOR, mode, reg, const1_rtx), 0);
return result;
}
\f
/* Emit the common code for doing conditional branches.
operand[0] is the label to jump to.
- The comparison operands are saved away by cmp{si,sf,df}. */
+ The comparison operands are saved away by cmp{si,di,sf,df}. */
void
gen_conditional_branch (operands, test_code)
SImode, /* ltu */
SImode, /* leu */
},
+ { /* CMP_DI */
+ DImode, /* eq */
+ DImode, /* ne */
+ DImode, /* gt */
+ DImode, /* ge */
+ DImode, /* lt */
+ DImode, /* le */
+ DImode, /* gtu */
+ DImode, /* geu */
+ DImode, /* ltu */
+ DImode, /* leu */
+ },
{ /* CMP_SF */
CC_FPmode, /* eq */
CC_REV_FPmode, /* ne */
if (test == ITEST_MAX)
{
- mode = SImode;
+ mode = word_mode;
goto fail;
}
if (mode == VOIDmode)
goto fail;
- switch (branch_type)
+ switch (type)
{
default:
goto fail;
case CMP_SI:
+ case CMP_DI:
reg = gen_int_relational (test_code, (rtx)0, cmp0, cmp1, &invert);
if (reg != (rtx)0)
{
/* Make sure not non-zero constant if ==/!= */
else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
- cmp1 = force_reg (SImode, cmp1);
+ cmp1 = force_reg (mode, cmp1);
break;
}
\f
-#define UNITS_PER_SHORT (SHORT_TYPE_SIZE / BITS_PER_UNIT)
-
+#if 0
/* Internal code to generate the load and store of one word/short/byte.
The load is emitted directly, and the store insn is returned. */
-#if 0
+#define UNITS_PER_MIPS_DWORD 8
+#define UNITS_PER_MIPS_WORD 4
+#define UNITS_PER_MIPS_HWORD 2
+
static rtx
block_move_load_store (dest_reg, src_reg, p_bytes, p_offset, align, orig_src)
rtx src_reg; /* register holding source memory address */
if (bytes <= 0 || align <= 0)
abort ();
- if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD)
+ if (bytes >= UNITS_PER_MIPS_DWORD && align >= UNIS_PER_MIPS_DWORD)
+ {
+ mode = DImode;
+ size = UNITS_PER_MIPS_DWORD;
+ load_func = gen_movdi;
+ store_func = gen_movdi;
+ }
+ else if (bytes >= UNITS_PER_MIPS_WORD && align >= UNITS_PER_MIPS_WORD)
{
mode = SImode;
- size = UNITS_PER_WORD;
+ size = UNITS_PER_MIPS_WORD;
load_func = gen_movsi;
store_func = gen_movsi;
}
#if 0
/* Don't generate unaligned moves here, rather defer those to the
- general movestrsi_internal pattern. */
- else if (bytes >= UNITS_PER_WORD)
+ general movestrsi_internal pattern.
+ If this gets commented back in, then should add the dword equivalent. */
+ else if (bytes >= UNITS_PER_MIPS_WORD)
{
mode = SImode;
- size = UNITS_PER_WORD;
+ size = UNITS_PER_MIPS_WORD;
load_func = gen_movsi_ulw;
store_func = gen_movsi_usw;
}
#endif
- else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT)
+ else if (bytes >= UNITS_PER_MIPS_SHORT && align >= UNITS_PER_MIPS_SHORT)
{
mode = HImode;
- size = UNITS_PER_SHORT;
+ size = UNITS_PER_MIPS_SHORT;
load_func = gen_movhi;
store_func = gen_movhi;
}
#define MAX_MOVE_REGS 4
#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
+/* ??? Should add code to use DWORD load/stores. */
+
static void
block_move_loop (dest_reg, src_reg, bytes, align, orig_src)
rtx dest_reg; /* register holding destination address */
if (bytes > 0x7fff)
{
- emit_insn (gen_movsi (final_src, bytes_rtx));
- emit_insn (gen_addsi3 (final_src, final_src, src_reg));
+ if (TARGET_LONG64)
+ {
+ emit_insn (gen_movdi (final_src, bytes_rtx));
+ emit_insn (gen_adddi3 (final_src, final_src, src_reg));
+ }
+ else
+ {
+ emit_insn (gen_movsi (final_src, bytes_rtx));
+ emit_insn (gen_addsi3 (final_src, final_src, src_reg));
+ }
}
else
- emit_insn (gen_addsi3 (final_src, src_reg, bytes_rtx));
+ {
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (final_src, src_reg, bytes_rtx));
+ else
+ emit_insn (gen_addsi3 (final_src, src_reg, bytes_rtx));
+ }
emit_label (label);
bytes_rtx = GEN_INT (MAX_MOVE_BYTES);
emit_insn (gen_movstrsi_internal (dest_mem, src_mem, bytes_rtx, align_rtx));
- emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx));
- emit_insn (gen_addsi3 (dest_reg, dest_reg, bytes_rtx));
- emit_insn (gen_cmpsi (src_reg, final_src));
+ if (TARGET_LONG64)
+ {
+ emit_insn (gen_adddi3 (src_reg, src_reg, bytes_rtx));
+ emit_insn (gen_adddi3 (dest_reg, dest_reg, bytes_rtx));
+ emit_insn (gen_cmpdi (src_reg, final_src));
+ }
+ else
+ {
+ emit_insn (gen_addsi3 (src_reg, src_reg, bytes_rtx));
+ emit_insn (gen_addsi3 (dest_reg, dest_reg, bytes_rtx));
+ emit_insn (gen_cmpsi (src_reg, final_src));
+ }
emit_jump_insn (gen_bne (label));
if (leftover)
rtx src_reg;
rtx bytes_rtx;
{
+ /* We want to pass the size as Pmode, which will normally be SImode
+ but will be DImode if we are using 64 bit longs and pointers. */
+ if (GET_MODE (bytes_rtx) != VOIDmode
+ && GET_MODE (bytes_rtx) != Pmode)
+ bytes_rtx = convert_to_mode (Pmode, bytes_rtx, TRUE);
+
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"), 0,
VOIDmode, 3,
dest_reg, Pmode,
src_reg, Pmode,
- bytes_rtx, SImode);
+ bytes_rtx, Pmode);
#else
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
VOIDmode, 3,
src_reg, Pmode,
dest_reg, Pmode,
- bytes_rtx, SImode);
+ bytes_rtx, Pmode);
#endif
}
bytes -= leftover;
- emit_insn (gen_iorsi3 (temp, src_reg, dest_reg));
- emit_insn (gen_andsi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1)));
- emit_insn (gen_cmpsi (temp, const0_rtx));
+ if (TARGET_LONG64)
+ {
+ emit_insn (gen_iordi3 (temp, src_reg, dest_reg));
+ emit_insn (gen_anddi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1)));
+ emit_insn (gen_cmpdi (temp, const0_rtx));
+ }
+ else
+ {
+ emit_insn (gen_iorsi3 (temp, src_reg, dest_reg));
+ emit_insn (gen_andsi3 (temp, temp, GEN_INT (UNITS_PER_WORD-1)));
+ emit_insn (gen_cmpsi (temp, const0_rtx));
+ }
emit_jump_insn (gen_beq (aligned_label));
/* Unaligned loop. */
{
load_store[num].offset = offset;
- if (bytes >= UNITS_PER_WORD && align >= UNITS_PER_WORD)
+ if (TARGET_64BIT && bytes >= 8 && align >= 8)
+ {
+ load_store[num].load = "ld\t%0,%1";
+ load_store[num].load_nop = "ld\t%0,%1%#";
+ load_store[num].store = "sd\t%0,%1";
+ load_store[num].last_store = "sd\t%0,%1";
+ load_store[num].final = (char *)0;
+ load_store[num].mode = DImode;
+ offset += 8;
+ bytes -= 8;
+ }
+
+ /* ??? Fails because of a MIPS assembler bug? */
+ else if (TARGET_64BIT && bytes >= 8)
+ {
+#if BYTES_BIG_ENDIAN
+ load_store[num].load = "ldl\t%0,%1\n\tldr\t%0,%2";
+ load_store[num].load_nop = "ldl\t%0,%1\n\tldr\t%0,%2%#";
+ load_store[num].store = "sdl\t%0,%1\n\tsdr\t%0,%2";
+ load_store[num].last_store = "sdr\t%0,%2";
+ load_store[num].final = "sdl\t%0,%1";
+#else
+ load_store[num].load = "ldl\t%0,%2\n\tldr\t%0,%1";
+ load_store[num].load_nop = "ldl\t%0,%2\n\tldr\t%0,%1%#";
+ load_store[num].store = "sdl\t%0,%2\n\tsdr\t%0,%1";
+ load_store[num].last_store = "sdr\t%0,%1";
+ load_store[num].final = "sdl\t%0,%2";
+#endif
+ load_store[num].mode = DImode;
+ offset += 8;
+ bytes -= 8;
+ use_lwl_lwr = TRUE;
+ }
+
+ else if (bytes >= 4 && align >= 4)
{
load_store[num].load = "lw\t%0,%1";
load_store[num].load_nop = "lw\t%0,%1%#";
load_store[num].last_store = "sw\t%0,%1";
load_store[num].final = (char *)0;
load_store[num].mode = SImode;
- offset += UNITS_PER_WORD;
- bytes -= UNITS_PER_WORD;
+ offset += 4;
+ bytes -= 4;
}
- else if (bytes >= UNITS_PER_WORD)
+ else if (bytes >= 4)
{
#if BYTES_BIG_ENDIAN
load_store[num].load = "lwl\t%0,%1\n\tlwr\t%0,%2";
load_store[num].final = "swl\t%0,%2";
#endif
load_store[num].mode = SImode;
- offset += UNITS_PER_WORD;
- bytes -= UNITS_PER_WORD;
+ offset += 4;
+ bytes -= 4;
use_lwl_lwr = TRUE;
}
- else if (bytes >= UNITS_PER_SHORT && align >= UNITS_PER_SHORT)
+ else if (bytes >= 2 && align >= 2)
{
load_store[num].load = "lh\t%0,%1";
load_store[num].load_nop = "lh\t%0,%1%#";
load_store[num].store = "sh\t%0,%1";
load_store[num].last_store = "sh\t%0,%1";
load_store[num].final = (char *)0;
- load_store[num].offset = offset;
load_store[num].mode = HImode;
- offset += UNITS_PER_SHORT;
- bytes -= UNITS_PER_SHORT;
+ offset += 2;
+ bytes -= 2;
}
else
plus_constant (src_reg, offset));
if (use_lwl_lwr)
- xoperands[2] = gen_rtx (MEM, load_store[i].mode,
- plus_constant (src_reg, UNITS_PER_WORD-1+offset));
+ {
+ int extra_offset;
+ extra_offset = GET_MODE_SIZE (load_store[i].mode) - 1;
+ xoperands[2] = gen_rtx (MEM, load_store[i].mode,
+ plus_constant (src_reg,
+ extra_offset
+ + offset));
+ }
output_asm_insn (load_store[i].load, xoperands);
}
if (use_lwl_lwr)
- xoperands[2] = gen_rtx (MEM, load_store[i].mode,
- plus_constant (dest_reg, UNITS_PER_WORD-1+offset));
+ {
+ int extra_offset;
+ extra_offset = GET_MODE_SIZE (load_store[i].mode) - 1;
+ xoperands[2] = gen_rtx (MEM, load_store[i].mode,
+ plus_constant (dest_reg,
+ extra_offset
+ + offset));
+ }
if (move_type == BLOCK_MOVE_NORMAL)
output_asm_insn (load_store[i].store, xoperands);
}
num = 0; /* reset load_store */
- use_lwl_lwr = FALSE; /* reset whether or not we used lwl/lwr */
+ use_lwl_lwr = FALSE;
}
}
&& GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
abort ();
cum->gp_reg_found = 1;
- cum->arg_words += (GET_MODE_SIZE (mode) + 3) / 4;
+ cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
+ / UNITS_PER_WORD);
break;
case BLKmode:
cum->gp_reg_found = 1;
- cum->arg_words += (int_size_in_bytes (type) + 3) / 4;
+ cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
+ / UNITS_PER_WORD);
break;
case SFmode:
break;
case DFmode:
- cum->arg_words += 2;
+ cum->arg_words += (TARGET_64BIT ? 1 : 2);
break;
case DImode:
cum->gp_reg_found = 1;
- cum->arg_words += 2;
+ cum->arg_words += (TARGET_64BIT ? 1 : 2);
break;
case QImode:
}
}
-/* Return a RTL expression containing the register for the given mode,
- or 0 if the argument is too be passed on the stack. */
+/* Return an RTL expression containing the register for the given mode,
+ or 0 if the argument is to be passed on the stack. */
struct rtx_def *
function_arg (cum, mode, type, named)
break;
case DFmode:
- cum->arg_words += (cum->arg_words & 1);
+ if (! TARGET_64BIT)
+ cum->arg_words += (cum->arg_words & 1);
regbase = (cum->gp_reg_found || TARGET_SOFT_FLOAT || cum->arg_number >= 2
? GP_ARG_FIRST
: FP_ARG_FIRST);
/* Drops through. */
case BLKmode:
- if (type != (tree)0 && TYPE_ALIGN (type) > BITS_PER_WORD)
+ if (type != (tree)0 && TYPE_ALIGN (type) > BITS_PER_WORD
+ && ! TARGET_64BIT)
cum->arg_words += (cum->arg_words & 1);
regbase = GP_ARG_FIRST;
break;
case DImode:
- cum->arg_words += (cum->arg_words & 1);
+ if (! TARGET_64BIT)
+ cum->arg_words += (cum->arg_words & 1);
regbase = GP_ARG_FIRST;
}
This also makes varargs work. If we have such a structure,
we save the adjustment RTL, and the call define expands will
emit them. For the VOIDmode argument (argument after the
- last real argument, pass back a parallel vector holding each
+ last real argument), pass back a parallel vector holding each
of the adjustments. */
/* ??? function_arg can be called more than once for each argument.
As a result, we compute more adjustments than we need here.
See the CUMULATIVE_ARGS definition in mips.h. */
- if (struct_p && int_size_in_bytes (type) < 4)
+ /* ??? This scheme requires everything smaller than the word size to
+ shifted to the left, but when TARGET_64BIT and ! TARGET_INT64,
+ that would mean every int needs to be shifted left, which is very
+ inefficient. Let's not carry this compatibility to the 64 bit
+ calling convention for now. */
+
+ if (struct_p && int_size_in_bytes (type) < UNITS_PER_WORD
+ && ! TARGET_64BIT)
{
rtx amount = GEN_INT (BITS_PER_WORD
- int_size_in_bytes (type) * BITS_PER_UNIT);
- rtx reg = gen_rtx (REG, SImode, regbase + cum->arg_words + bias);
- cum->adjust[ cum->num_adjusts++ ] = gen_ashlsi3 (reg, reg, amount);
+ rtx reg = gen_rtx (REG, word_mode, regbase + cum->arg_words + bias);
+ if (TARGET_64BIT)
+ cum->adjust[ cum->num_adjusts++ ] = gen_ashldi3 (reg, reg, amount);
+ else
+ cum->adjust[ cum->num_adjusts++ ] = gen_ashlsi3 (reg, reg, amount);
}
}
{
int words;
if (mode == BLKmode)
- words = (int_size_in_bytes (type) + 3) / 4;
+ words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
+ / UNITS_PER_WORD);
else
- words = (GET_MODE_SIZE (mode) + 3) / 4;
+ words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
return 0; /* structure fits in registers */
return MAX_ARGS_IN_REGISTERS - cum->arg_words;
}
- else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS-1)
+ else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS-1
+ && ! TARGET_64BIT)
{
if (TARGET_DEBUG_E_MODE)
fprintf (stderr, "function_arg_partial_nregs = 1\n");
mips_section_threshold = (g_switch_set) ? g_switch_value : MIPS_DEFAULT_GVALUE;
+ if (mips_section_threshold <= 0)
+ target_flags &= ~MASK_GPOPT;
+ else if (optimize)
+ target_flags |= MASK_GPOPT;
+
+ /* Get the architectural level. */
+ if (mips_isa_string == (char *)0)
+ {
+#ifdef MIPS_ISA_DEFAULT
+ mips_isa = MIPS_ISA_DEFAULT;
+#else
+ mips_isa = 1;
+#endif
+ }
+
+ else if (isdigit (*mips_isa_string))
+ {
+ mips_isa = atoi (mips_isa_string);
+ if (mips_isa < 1 || mips_isa > 3)
+ {
+ error ("-mips%d not supported", mips_isa);
+ mips_isa = 1;
+ }
+ }
+
+ else
+ {
+ error ("bad value (%s) for -mips switch", mips_isa_string);
+ mips_isa = 1;
+ }
+
/* Identify the processor type */
if (mips_cpu_string == (char *)0
|| !strcmp (mips_cpu_string, "default")
|| !strcmp (mips_cpu_string, "DEFAULT"))
{
- mips_cpu_string = "default";
- mips_cpu = PROCESSOR_DEFAULT;
+ switch (mips_isa)
+ {
+ default:
+ mips_cpu_string = "3000";
+ mips_cpu = PROCESSOR_R3000;
+ break;
+ case 2:
+ mips_cpu_string = "6000";
+ mips_cpu = PROCESSOR_R6000;
+ break;
+ case 3:
+ mips_cpu_string = "4000";
+ mips_cpu = PROCESSOR_R4000;
+ break;
+ }
}
else
case '4':
if (!strcmp (p, "4000") || !strcmp (p, "4k") || !strcmp (p, "4K"))
mips_cpu = PROCESSOR_R4000;
+ /* The r4400 is exactly the same as the r4000 from the compiler's
+ viewpoint. */
+ else if (!strcmp (p, "4400"))
+ mips_cpu = PROCESSOR_R4000;
+ else if (!strcmp (p, "4600"))
+ mips_cpu = PROCESSOR_R4600;
break;
case '6':
if (!strcmp (p, "6000") || !strcmp (p, "6k") || !strcmp (p, "6K"))
mips_cpu = PROCESSOR_R6000;
break;
+
+ case 'o':
+ if (!strcmp (p, "orion"))
+ mips_cpu = PROCESSOR_R4600;
+ break;
}
if (mips_cpu == PROCESSOR_DEFAULT)
}
}
- /* Now get the architectural level. */
- if (mips_isa_string == (char *)0)
- mips_isa = 1;
-
- else if (isdigit (*mips_isa_string))
- mips_isa = atoi (mips_isa_string);
-
- else
- {
- error ("bad value (%s) for -mips switch", mips_isa_string);
- mips_isa = 1;
- }
-
- if (mips_isa < 0 || mips_isa > 3)
- error ("-mips%d not supported", mips_isa);
-
- else if (mips_isa > 1
- && (mips_cpu == PROCESSOR_DEFAULT || mips_cpu == PROCESSOR_R3000))
- error ("-mcpu=%s does not support -mips%d", mips_cpu_string, mips_isa);
-
- else if (mips_cpu == PROCESSOR_R6000 && mips_isa > 2)
+ if ((mips_cpu == PROCESSOR_R3000 && mips_isa > 1)
+ || (mips_cpu == PROCESSOR_R6000 && mips_isa > 2))
error ("-mcpu=%s does not support -mips%d", mips_cpu_string, mips_isa);
/* make sure sizes of ints/longs/etc. are ok */
if (mips_isa < 3)
{
if (TARGET_INT64)
- fatal ("Only the r4000 can support 64 bit ints");
+ fatal ("Only MIPS-III CPUs can support 64 bit ints");
else if (TARGET_LONG64)
- fatal ("Only the r4000 can support 64 bit longs");
+ fatal ("Only MIPS-III CPUs can support 64 bit longs");
else if (TARGET_LLONG128)
- fatal ("Only the r4000 can support 128 bit long longs");
+ fatal ("Only MIPS-III CPUs can support 128 bit long longs");
else if (TARGET_FLOAT64)
- fatal ("Only the r4000 can support 64 bit fp registers");
+ fatal ("Only MIPS-III CPUs can support 64 bit fp registers");
+ }
+ else
+ {
+ target_flags |= MASK_64BIT;
+
+ if (TARGET_LLONG128)
+ fatal ("128 bit long longs are not supported");
}
- else if (TARGET_INT64 || TARGET_LONG64 || TARGET_LLONG128 || TARGET_FLOAT64)
- warning ("r4000 64/128 bit types not yet supported");
/* Tell halfpic.c that we have half-pic code if we do. */
if (TARGET_HALF_PIC)
mips_abicalls = MIPS_ABICALLS_NO;
/* -mrnames says to use the MIPS software convention for register
- names instead of the hardware names (ie, a0 instead of $4).
+ names instead of the hardware names (ie, $a0 instead of $4).
We do this by switching the names in mips_reg_names, which the
reg_names points into via the REGISTER_NAMES macro. */
if (TARGET_NAME_REGS)
- {
- if (TARGET_GAS)
- {
- target_flags &= ~ MASK_NAME_REGS;
- error ("Gas does not support the MIPS software register name convention.");
- }
- else
- bcopy ((char *) mips_sw_reg_names, (char *) mips_reg_names, sizeof (mips_reg_names));
- }
+ bcopy ((char *) mips_sw_reg_names, (char *) mips_reg_names, sizeof (mips_reg_names));
/* If this is OSF/1, set up a SIGINFO handler so we can see what function
is currently being compiled. */
#endif
#endif
+ /* Initialize the high and low values for legitimate floating point
+ constants. Rather than trying to get the accuracy down to the
+ last bit, just use approximate ranges. */
+ dfhigh = REAL_VALUE_ATOF ("1.0e300", DFmode);
+ dflow = REAL_VALUE_ATOF ("1.0e-300", DFmode);
+ sfhigh = REAL_VALUE_ATOF ("1.0e38", SFmode);
+ sflow = REAL_VALUE_ATOF ("1.0e-38", SFmode);
+
/* Set up the classification arrays now. */
mips_rtx_classify[(int)PLUS] = CLASS_ADD_OP;
mips_rtx_classify[(int)MINUS] = CLASS_ADD_OP;
|| (TARGET_DEBUG_H_MODE && class == MODE_INT)));
else if (MD_REG_P (regno))
- temp = (mode == SImode || (regno == MD_REG_FIRST && mode == DImode));
+ {
+ if (TARGET_64BIT)
+ temp = (mode == DImode
+ || (regno == MD_REG_FIRST && mode == TImode));
+ else
+ temp = (mode == SImode
+ || (regno == MD_REG_FIRST && mode == DImode));
+ }
else
temp = FALSE;
else if (code == CONST_DOUBLE)
{
-#if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
- union { double d; int i[2]; } u;
- u.i[0] = CONST_DOUBLE_LOW (op);
- u.i[1] = CONST_DOUBLE_HIGH (op);
- if (GET_MODE (op) == SFmode)
- {
- float f;
- f = u.d;
- u.d = f;
- }
- fprintf (file, "%.20e", u.d);
-#else
- fatal ("CONST_DOUBLE found in cross compilation");
-#endif
+ REAL_VALUE_TYPE d;
+ char s[30];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (d, op);
+ REAL_VALUE_TO_DECIMAL (d, "%.20e", s);
+ fprintf (file, s);
}
else if ((letter == 'x') && (GET_CODE(op) == CONST_INT))
int len;
if (TARGET_GP_OPT
- && mips_section_threshold != 0
&& ((TREE_CODE (decl)) != FUNCTION_DECL)
&& ((len = int_size_in_bytes (TREE_TYPE (decl))) > 0))
{
\f
/* Compute a string to use as a temporary file name. */
+/* On MSDOS, write temp files in current dir
+ because there's no place else we can expect to use. */
+#if __MSDOS__
+#ifndef P_tmpdir
+#define P_tmpdir "./"
+#endif
+#endif
+
static FILE *
make_temp_file ()
{
}
len = strlen (base);
- temp_filename = (char *) alloca (len + sizeof("/ccXXXXXX"));
+ /* temp_filename is global, so we must use malloc, not alloca. */
+ temp_filename = (char *) xmalloc (len + sizeof("/ctXXXXXX"));
strcpy (temp_filename, base);
if (len > 0 && temp_filename[len-1] != '/')
temp_filename[len++] = '/';
- strcpy (temp_filename + len, "ccXXXXXX");
+ strcpy (temp_filename + len, "ctXXXXXX");
mktemp (temp_filename);
stream = fopen (temp_filename, "w+");
if (!stream)
pfatal_with_name (temp_filename);
+#ifndef __MSDOS__
+ /* In MSDOS, we cannot unlink the temporary file until we are finished using
+ it. Otherwise, we delete it now, so that it will be gone even if the
+ compiler happens to crash. */
unlink (temp_filename);
+#endif
return stream;
}
else
asm_out_data_file = asm_out_text_file = stream;
- if (TARGET_NAME_REGS)
- fprintf (asm_out_file, "#include <regdef.h>\n");
-
print_options (stream);
}
if (fclose (asm_out_text_file) != 0)
pfatal_with_name (temp_filename);
+
+#ifdef __MSDOS__
+ unlink (temp_filename);
+#endif
}
}
assemble_name (stream, name);
fprintf (stream, final_string, size); /* ":\n", ",%u\n", ",%u\n" */
- if (TARGET_GP_OPT && mips_section_threshold != 0)
+ if (TARGET_GP_OPT)
{
tree name_tree = get_identifier (name);
TREE_ASM_WRITTEN (name_tree) = 1;
{
if (regs_ever_live[regno] && !call_used_regs[regno])
{
- fp_reg_size += 2*UNITS_PER_WORD;
+ fp_reg_size += fp_inc * UNITS_PER_FPREG;
fmask |= fp_bits << (regno - FP_REG_FIRST);
}
}
current_frame_info.fmask = fmask;
current_frame_info.initialized = reload_completed;
current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
- current_frame_info.num_fp = fp_reg_size / (2*UNITS_PER_WORD);
+ current_frame_info.num_fp = fp_reg_size / (fp_inc * UNITS_PER_FPREG);
if (mask)
{
if (fmask)
{
- unsigned long offset = args_size + extra_size + var_size
- + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD;
+ unsigned long offset = (args_size + extra_size + var_size
+ + gp_reg_rounded + fp_reg_size
+ - fp_inc * UNITS_PER_FPREG);
current_frame_info.fp_sp_offset = offset;
current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD;
}
base_reg_rtx = gen_rtx (REG, Pmode, MIPS_TEMP2_REGNUM);
base_offset = large_offset;
if (file == (FILE *)0)
- emit_insn (gen_addsi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ {
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ else
+ emit_insn (gen_addsi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ }
else
- fprintf (file, "\taddu\t%s,%s,%s\n",
+ fprintf (file, "\t%s\t%s,%s,%s\n",
+ TARGET_LONG64 ? "daddu" : "addu",
reg_names[MIPS_TEMP2_REGNUM],
reg_names[REGNO (large_reg)],
reg_names[STACK_POINTER_REGNUM]);
if (file == (FILE *)0)
{
emit_move_insn (base_reg_rtx, GEN_INT (gp_offset));
- emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
+ else
+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
}
else
- fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\taddu\t%s,%s,%s\n",
+ fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\t%s\t%s,%s,%s\n",
reg_names[MIPS_TEMP2_REGNUM],
(long)base_offset,
(long)base_offset,
+ TARGET_LONG64 ? "daddu" : "addu",
reg_names[MIPS_TEMP2_REGNUM],
reg_names[MIPS_TEMP2_REGNUM],
reg_names[STACK_POINTER_REGNUM]);
{
if (file == (FILE *)0)
{
- rtx reg_rtx = gen_rtx (REG, Pmode, regno);
- rtx mem_rtx = gen_rtx (MEM, Pmode,
+ rtx reg_rtx = gen_rtx (REG, word_mode, regno);
+ rtx mem_rtx = gen_rtx (MEM, word_mode,
gen_rtx (PLUS, Pmode, base_reg_rtx,
GEN_INT (gp_offset - base_offset)));
if (store_p || !TARGET_ABICALLS
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
fprintf (file, "\t%s\t%s,%ld(%s)\n",
- (store_p) ? "sw" : "lw",
+ (TARGET_64BIT
+ ? (store_p) ? "sd" : "ld"
+ : (store_p) ? "sw" : "lw"),
reg_names[regno],
gp_offset - base_offset,
reg_names[REGNO(base_reg_rtx)]);
if (fmask)
{
int fp_inc = (TARGET_FLOAT64) ? 1 : 2;
+ int fp_size = fp_inc * UNITS_PER_FPREG;
/* Pick which pointer to use as a base register. */
fp_offset = current_frame_info.fp_sp_offset;
- end_offset = fp_offset - (current_frame_info.fp_reg_size - 2*UNITS_PER_WORD);
+ end_offset = fp_offset - (current_frame_info.fp_reg_size - fp_size);
if (fp_offset < 0 || end_offset < 0)
fatal ("fp_offset (%ld) or end_offset (%ld) is less than zero.",
base_reg_rtx = gen_rtx (REG, Pmode, MIPS_TEMP2_REGNUM);
base_offset = large_offset;
if (file == (FILE *)0)
- emit_insn (gen_addsi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ {
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ else
+ emit_insn (gen_addsi3 (base_reg_rtx, large_reg, stack_pointer_rtx));
+ }
else
- fprintf (file, "\taddu\t%s,%s,%s\n",
+ fprintf (file, "\t%s\t%s,%s,%s\n",
+ TARGET_LONG64 ? "daddu" : "addu",
reg_names[MIPS_TEMP2_REGNUM],
reg_names[REGNO (large_reg)],
reg_names[STACK_POINTER_REGNUM]);
if (file == (FILE *)0)
{
emit_move_insn (base_reg_rtx, GEN_INT (fp_offset));
- emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
+ else
+ emit_insn (gen_addsi3 (base_reg_rtx, base_reg_rtx, stack_pointer_rtx));
}
else
- fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\taddu\t%s,%s,%s\n",
+ fprintf (file, "\tli\t%s,0x%.08lx\t# %ld\n\t%s\t%s,%s,%s\n",
reg_names[MIPS_TEMP2_REGNUM],
(long)base_offset,
(long)base_offset,
+ TARGET_LONG64 ? "daddu" : "addu",
reg_names[MIPS_TEMP2_REGNUM],
reg_names[MIPS_TEMP2_REGNUM],
reg_names[STACK_POINTER_REGNUM]);
reg_names[REGNO(base_reg_rtx)]);
- fp_offset -= 2*UNITS_PER_WORD;
+ fp_offset -= fp_size;
}
}
}
reg_names[PIC_FUNCTION_ADDR_REGNUM]);
if (tsize > 0)
{
- fprintf (file, "\tsubu\t%s,%s,%d\n", sp_str, sp_str, tsize);
+ fprintf (file, "\t%s\t%s,%s,%d\n",
+ (TARGET_LONG64 ? "dsubu" : "subu"),
+ sp_str, sp_str, tsize);
fprintf (file, "\t.cprestore %d\n", current_frame_info.args_size);
}
}
{
if (offset != 0)
ptr = gen_rtx (PLUS, Pmode, stack_pointer_rtx, GEN_INT (offset));
- emit_move_insn (gen_rtx (MEM, Pmode, ptr),
- gen_rtx (REG, Pmode, regno));
+ emit_move_insn (gen_rtx (MEM, word_mode, ptr),
+ gen_rtx (REG, word_mode, regno));
offset += UNITS_PER_WORD;
}
}
{
if (tsize > 32767)
{
- tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
+ tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
emit_move_insn (tmp_rtx, tsize_rtx);
tsize_rtx = tmp_rtx;
}
- emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
- tsize_rtx));
+ if (TARGET_LONG64)
+ emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
+ else
+ emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
}
save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
if (frame_pointer_needed)
- emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_movdi (frame_pointer_rtx, stack_pointer_rtx));
+ else
+ emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
+ }
}
/* If we are profiling, make sure no instructions are scheduled before
if (set_volatile != 0)
{
set_volatile = 0;
- fprintf (file, "\t#.set\tnovolatile\n", (TARGET_MIPS_AS) ? "" : "#");
+ fprintf (file, "\t%s.set\tnovolatile\n", (TARGET_MIPS_AS) ? "" : "#");
error ("internal gcc error: .set volatile left on in epilogue");
}
fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
if (tsize > 32767)
- fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
+ fprintf (file, "\t%s\t%s,%s,%s\n",
+ TARGET_LONG64 ? "daddu" : "addu",
+ sp_str, sp_str, t1_str);
else if (tsize > 0)
- fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
+ fprintf (file, "\t%s\t%s,%s,%d\n",
+ TARGET_LONG64 ? "daddu" : "addu",
+ sp_str, sp_str, tsize);
else if (!load_only_r31 && epilogue_delay != 0)
final_scan_insn (XEXP (epilogue_delay, 0),
else
{
if (tsize > 32767)
- fprintf (file, "\taddu\t%s,%s,%s\n", sp_str, sp_str, t1_str);
+ fprintf (file, "\t%s\t%s,%s,%s\n",
+ TARGET_LONG64 ? "daddu" : "addu",
+ sp_str, sp_str, t1_str);
else if (tsize > 0)
- fprintf (file, "\taddu\t%s,%s,%d\n", sp_str, sp_str, tsize);
+ fprintf (file, "\t%s\t%s,%s,%d\n",
+ TARGET_LONG64 ? "daddu" : "addu",
+ sp_str, sp_str, tsize);
fprintf (file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 31]);
}
if (tsize > 32767)
{
- tmp_rtx = gen_rtx (REG, SImode, MIPS_TEMP1_REGNUM);
+ tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
emit_move_insn (tmp_rtx, tsize_rtx);
tsize_rtx = tmp_rtx;
}
if (tsize > 0)
{
if (frame_pointer_needed)
- emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
+ {
+ if (TARGET_LONG64)
+ emit_insn (gen_movdi (stack_pointer_rtx, frame_pointer_rtx));
+ else
+ emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
+ }
save_restore_insns (FALSE, tmp_rtx, tsize, (FILE *)0);
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tsize_rtx));
+ if (TARGET_LONG64)
+ emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
+ else
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ tsize_rtx));
}
emit_jump_insn (gen_return_internal (gen_rtx (REG, Pmode, GP_REG_FIRST+31)));