Commit 225b8835 by Ian Lance Taylor

Add support for mult instruction in 64 bit mode

From-SVN: r9234
parent b6da8566
...@@ -246,7 +246,7 @@ char mips_reg_names[][8] = ...@@ -246,7 +246,7 @@ char mips_reg_names[][8] =
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
"hi", "lo", "$fcr31" "hi", "lo", "accum","$fcr31"
}; };
/* Mips software names for the registers, used to overwrite the /* Mips software names for the registers, used to overwrite the
...@@ -262,7 +262,7 @@ char mips_sw_reg_names[][8] = ...@@ -262,7 +262,7 @@ char mips_sw_reg_names[][8] =
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
"hi", "lo", "$fcr31" "hi", "lo", "accum","$fcr31"
}; };
/* Map hard register number to register class */ /* Map hard register number to register class */
...@@ -284,7 +284,7 @@ enum reg_class mips_regno_to_class[] = ...@@ -284,7 +284,7 @@ enum reg_class mips_regno_to_class[] =
FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS,
HI_REG, LO_REG, ST_REGS HI_REG, LO_REG, HILO_REG, ST_REGS
}; };
/* Map register constraint character to register class. */ /* Map register constraint character to register class. */
...@@ -927,7 +927,10 @@ mips_move_1word (operands, insn, unsignedp) ...@@ -927,7 +927,10 @@ mips_move_1word (operands, insn, unsignedp)
else if (MD_REG_P (regno1)) else if (MD_REG_P (regno1))
{ {
delay = DELAY_HILO; delay = DELAY_HILO;
ret = "mf%1\t%0"; if (regno1 != HILO_REGNUM)
ret = "mf%1\t%0";
else
ret = "mflo\t%0";
} }
else else
...@@ -958,7 +961,8 @@ mips_move_1word (operands, insn, unsignedp) ...@@ -958,7 +961,8 @@ mips_move_1word (operands, insn, unsignedp)
if (GP_REG_P (regno1)) if (GP_REG_P (regno1))
{ {
delay = DELAY_HILO; delay = DELAY_HILO;
ret = "mt%0\t%1"; if (regno0 != HILO_REGNUM)
ret = "mt%0\t%1";
} }
} }
...@@ -1040,6 +1044,12 @@ mips_move_1word (operands, insn, unsignedp) ...@@ -1040,6 +1044,12 @@ mips_move_1word (operands, insn, unsignedp)
delay = DELAY_LOAD; delay = DELAY_LOAD;
ret = "mtc1\t%z1,%0"; ret = "mtc1\t%z1,%0";
} }
else if (MD_REG_P (regno0))
{
delay = DELAY_HILO;
ret = "mt%0\t%.";
}
} }
else if (GP_REG_P (regno0)) else if (GP_REG_P (regno0))
...@@ -1301,7 +1311,12 @@ mips_move_2words (operands, insn) ...@@ -1301,7 +1311,12 @@ mips_move_2words (operands, insn)
{ {
delay = DELAY_HILO; delay = DELAY_HILO;
if (TARGET_64BIT) if (TARGET_64BIT)
ret = "mt%0\t%1"; {
if (regno0 != HILO_REGNUM)
ret = "mt%0\t%1";
else if (regno1 == 0)
ret = "mtlo\t%.\n\tmthi\t%.";
}
else else
ret = "mthi\t%M1\n\tmtlo\t%L1"; ret = "mthi\t%M1\n\tmtlo\t%L1";
} }
...@@ -1310,7 +1325,10 @@ mips_move_2words (operands, insn) ...@@ -1310,7 +1325,10 @@ mips_move_2words (operands, insn)
{ {
delay = DELAY_HILO; delay = DELAY_HILO;
if (TARGET_64BIT) if (TARGET_64BIT)
ret = "mf%1\t%0"; {
if (regno1 != HILO_REGNUM)
ret = "mf%1\t%0";
}
else else
ret = "mfhi\t%M0\n\tmflo\t%L0"; ret = "mfhi\t%M0\n\tmflo\t%L0";
} }
...@@ -1398,6 +1416,14 @@ mips_move_2words (operands, insn) ...@@ -1398,6 +1416,14 @@ mips_move_2words (operands, insn)
? "li.d\t%0,%1" ? "li.d\t%0,%1"
: "mtc1\t%.,%0\n\tmtc1\t%.,%D0"); : "mtc1\t%.,%0\n\tmtc1\t%.,%D0");
} }
else if (MD_REG_P (regno0))
{
delay = DELAY_HILO;
if (regno0 != HILO_REGNUM)
ret = "mt%0\t%.\n";
else
ret = "mtlo\t%.\n\tmthi\t%.";
}
} }
else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0)) else if (code1 == CONST_INT && GET_MODE (op0) == DImode && GP_REG_P (regno0))
...@@ -3352,7 +3378,9 @@ override_options () ...@@ -3352,7 +3378,9 @@ override_options ()
mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS); mips_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
mips_char_to_class['h'] = HI_REG; mips_char_to_class['h'] = HI_REG;
mips_char_to_class['l'] = LO_REG; mips_char_to_class['l'] = LO_REG;
mips_char_to_class['a'] = HILO_REG;
mips_char_to_class['x'] = MD_REGS; mips_char_to_class['x'] = MD_REGS;
mips_char_to_class['b'] = ALL_REGS;
mips_char_to_class['y'] = GR_REGS; mips_char_to_class['y'] = GR_REGS;
mips_char_to_class['z'] = ST_REGS; mips_char_to_class['z'] = ST_REGS;
...@@ -5533,24 +5561,58 @@ mips_function_value (valtype, func) ...@@ -5533,24 +5561,58 @@ mips_function_value (valtype, func)
} }
#endif #endif
/* Moving the HI or LO register somewhere requires a general register. */ /* This function returns the register class required for a secondary
register when copying between one of the registers in CLASS, and X,
using MODE. If IN_P is nonzero, the copy is going from X to the
register, otherwise the register is the source. A return value of
NO_REGS means that no secondary register is required. */
enum reg_class enum reg_class
mips_secondary_reload_class (class, mode, x) mips_secondary_reload_class (class, mode, x, in_p)
enum reg_class class; enum reg_class class;
enum machine_mode mode; enum machine_mode mode;
rtx x; rtx x;
int in_p;
{ {
if (class != HI_REG && class != LO_REG && class != MD_REGS) int regno = -1;
return NO_REGS;
if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG) if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
regno = true_regnum (x);
/* We always require a general register when copying anything to
HILO_REGNUM, except when copying an SImode value from HILO_REGNUM
to a general register, or when copying from register 0. */
if (class == HILO_REG && regno != GP_REG_FIRST + 0)
{
if (! in_p
&& GP_REG_P (regno)
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
return NO_REGS;
return GR_REGS;
}
if (regno == HILO_REGNUM)
{ {
int regno = true_regnum (x); if (in_p
&& class == GR_REGS
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode))
return NO_REGS;
return GR_REGS;
}
if (regno >= GP_REG_FIRST && regno <= GP_REG_LAST) /* Copying from HI or LO to anywhere other than a general register
requires a general register. */
if (class == HI_REG || class == LO_REG || class == MD_REGS)
{
if (GP_REG_P (regno))
return NO_REGS;
return GR_REGS;
}
if (MD_REG_P (regno))
{
if (class == GR_REGS)
return NO_REGS; return NO_REGS;
return GR_REGS;
} }
return GR_REGS; return NO_REGS;
} }
...@@ -1138,10 +1138,13 @@ do { \ ...@@ -1138,10 +1138,13 @@ do { \
All registers that the compiler knows about must be given numbers, All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers. even those that are not normally considered general registers.
On the Mips, we have 32 integer registers, 32 floating point registers On the Mips, we have 32 integer registers, 32 floating point
and the special registers hi, lo, and fp status. */ registers and the special registers hi, lo, hilo, and fp status.
The hilo register is only used in 64 bit mode. It represents a 64
bit value stored as two 32 bit values in the hi and lo registers;
this is the result of the mult instruction. */
#define FIRST_PSEUDO_REGISTER 67 #define FIRST_PSEUDO_REGISTER 68
/* 1 for registers that have pervasive standard uses /* 1 for registers that have pervasive standard uses
and are not available for the register allocator. and are not available for the register allocator.
...@@ -1154,7 +1157,7 @@ do { \ ...@@ -1154,7 +1157,7 @@ do { \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 1 \ 0, 0, 0, 1 \
} }
...@@ -1171,7 +1174,7 @@ do { \ ...@@ -1171,7 +1174,7 @@ do { \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, \ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1 \ 1, 1, 1, 1 \
} }
...@@ -1190,16 +1193,17 @@ do { \ ...@@ -1190,16 +1193,17 @@ do { \
#define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32) #define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32)
#define MD_REG_FIRST 64 #define MD_REG_FIRST 64
#define MD_REG_LAST 65 #define MD_REG_LAST 66
#define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1) #define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1)
#define ST_REG_FIRST 66 #define ST_REG_FIRST 67
#define ST_REG_LAST 66 #define ST_REG_LAST 67
#define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1) #define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1)
#define AT_REGNUM (GP_REG_FIRST + 1) #define AT_REGNUM (GP_REG_FIRST + 1)
#define HI_REGNUM (MD_REG_FIRST + 0) #define HI_REGNUM (MD_REG_FIRST + 0)
#define LO_REGNUM (MD_REG_FIRST + 1) #define LO_REGNUM (MD_REG_FIRST + 1)
#define HILO_REGNUM (MD_REG_FIRST + 2)
#define FPSW_REGNUM ST_REG_FIRST #define FPSW_REGNUM ST_REG_FIRST
#define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM) #define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
...@@ -1342,6 +1346,7 @@ enum reg_class ...@@ -1342,6 +1346,7 @@ enum reg_class
FP_REGS, /* floating point registers */ FP_REGS, /* floating point registers */
HI_REG, /* hi register */ HI_REG, /* hi register */
LO_REG, /* lo register */ LO_REG, /* lo register */
HILO_REG, /* hilo register pair for 64 bit mode mult */
MD_REGS, /* multiply/divide registers (hi/lo) */ MD_REGS, /* multiply/divide registers (hi/lo) */
ST_REGS, /* status registers (fp status) */ ST_REGS, /* status registers (fp status) */
ALL_REGS, /* all registers */ ALL_REGS, /* all registers */
...@@ -1363,6 +1368,7 @@ enum reg_class ...@@ -1363,6 +1368,7 @@ enum reg_class
"FP_REGS", \ "FP_REGS", \
"HI_REG", \ "HI_REG", \
"LO_REG", \ "LO_REG", \
"HILO_REG", \
"MD_REGS", \ "MD_REGS", \
"ST_REGS", \ "ST_REGS", \
"ALL_REGS" \ "ALL_REGS" \
...@@ -1386,9 +1392,10 @@ enum reg_class ...@@ -1386,9 +1392,10 @@ enum reg_class
{ 0x00000000, 0xffffffff, 0x00000000 }, /* floating registers*/ \ { 0x00000000, 0xffffffff, 0x00000000 }, /* floating registers*/ \
{ 0x00000000, 0x00000000, 0x00000001 }, /* hi register */ \ { 0x00000000, 0x00000000, 0x00000001 }, /* hi register */ \
{ 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \ { 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \
{ 0x00000000, 0x00000000, 0x00000004 }, /* hilo register */ \
{ 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \ { 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \
{ 0x00000000, 0x00000000, 0x00000004 }, /* status registers */ \ { 0x00000000, 0x00000000, 0x00000008 }, /* status registers */ \
{ 0xffffffff, 0xffffffff, 0x00000007 } /* all registers */ \ { 0xffffffff, 0xffffffff, 0x0000000f } /* all registers */ \
} }
...@@ -1428,7 +1435,9 @@ extern enum reg_class mips_regno_to_class[]; ...@@ -1428,7 +1435,9 @@ extern enum reg_class mips_regno_to_class[];
'h' Hi register 'h' Hi register
'l' Lo register 'l' Lo register
'x' Multiply/divide registers 'x' Multiply/divide registers
'z' FP Status register */ 'a' HILO_REG
'z' FP Status register
'b' All registers */
extern enum reg_class mips_char_to_class[]; extern enum reg_class mips_char_to_class[];
...@@ -1548,8 +1557,10 @@ extern enum reg_class mips_char_to_class[]; ...@@ -1548,8 +1557,10 @@ extern enum reg_class mips_char_to_class[];
/* The HI and LO registers can only be reloaded via the general /* The HI and LO registers can only be reloaded via the general
registers. */ registers. */
#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
mips_secondary_reload_class (CLASS, MODE, X) mips_secondary_reload_class (CLASS, MODE, X, 1)
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
mips_secondary_reload_class (CLASS, MODE, X, 0)
/* Not declared above, with the other functions, because enum /* Not declared above, with the other functions, because enum
reg_class is not declared yet. */ reg_class is not declared yet. */
...@@ -2870,9 +2881,11 @@ while (0) ...@@ -2870,9 +2881,11 @@ while (0)
: (FROM) == FP_REGS && (TO) == FP_REGS ? 2 \ : (FROM) == FP_REGS && (TO) == FP_REGS ? 2 \
: (FROM) == GR_REGS && (TO) == FP_REGS ? 4 \ : (FROM) == GR_REGS && (TO) == FP_REGS ? 4 \
: (FROM) == FP_REGS && (TO) == GR_REGS ? 4 \ : (FROM) == FP_REGS && (TO) == GR_REGS ? 4 \
: (((FROM) == HI_REG || (FROM) == LO_REG || (FROM) == MD_REGS) \ : (((FROM) == HI_REG || (FROM) == LO_REG \
|| (FROM) == MD_REGS || (FROM) == HILO_REG) \
&& (TO) == GR_REGS) ? 6 \ && (TO) == GR_REGS) ? 6 \
: (((TO) == HI_REG || (TO) == LO_REG || (TO) == MD_REGS) \ : (((TO) == HI_REG || (TO) == LO_REG \
|| (TO) == MD_REGS || (FROM) == HILO_REG) \
&& (FROM) == GR_REGS) ? 6 \ && (FROM) == GR_REGS) ? 6 \
: 12) : 12)
...@@ -3085,6 +3098,7 @@ while (0) ...@@ -3085,6 +3098,7 @@ while (0)
&mips_reg_names[64][0], \ &mips_reg_names[64][0], \
&mips_reg_names[65][0], \ &mips_reg_names[65][0], \
&mips_reg_names[66][0], \ &mips_reg_names[66][0], \
&mips_reg_names[67][0], \
} }
/* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c. /* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c.
...@@ -3099,7 +3113,7 @@ while (0) ...@@ -3099,7 +3113,7 @@ while (0)
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
"hi", "lo", "$fcr31" \ "hi", "lo", "accum","$fcr31" \
} }
/* If defined, a C initializer for an array of structures /* If defined, a C initializer for an array of structures
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment