Commit 5b372d33 by Richard Sandiford Committed by Richard Sandiford

mips.c (mips_output_32bit_xfer): New function.

gcc/
	* config/mips/mips.c (mips_output_32bit_xfer): New function.
	(mips_output_64bit_xfer): Likewise.
	(mips16_fp_args): Rename to...
	(mips_output_args_xfer): ...this and replace the FROM_FP_P argument
	with a DIRECTION argument.  Use mips_output_32bit_xfer and
	mips_output_64bit_xfer.
	(build_mips16_function_stub): Update accordingly.
	(mips16_fpret_double): Delete.
	(build_mips16_call_stub): Update after above changes.
	Use mips_output_32bit_xfer.  Use mips_output_64bit_xfer instead
	of mips16_fpret_double.  Use GP_REG_RETURN.

From-SVN: r129475
parent 23fdf75c
2007-10-19 Richard Sandiford <rsandifo@nildram.co.uk> 2007-10-19 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.c (mips_output_32bit_xfer): New function.
(mips_output_64bit_xfer): Likewise.
(mips16_fp_args): Rename to...
(mips_output_args_xfer): ...this and replace the FROM_FP_P argument
with a DIRECTION argument. Use mips_output_32bit_xfer and
mips_output_64bit_xfer.
(build_mips16_function_stub): Update accordingly.
(mips16_fpret_double): Delete.
(build_mips16_call_stub): Update after above changes.
Use mips_output_32bit_xfer. Use mips_output_64bit_xfer instead
of mips16_fpret_double. Use GP_REG_RETURN.
2007-10-19 Richard Sandiford <rsandifo@nildram.co.uk>
* config/mips/mips.c (mips16_fp_args): Remove the FILE argument and * config/mips/mips.c (mips16_fp_args): Remove the FILE argument and
use asm_out_file instead. use asm_out_file instead.
(build_mips16_function_stub): Likewise. (build_mips16_function_stub): Likewise.
...@@ -5067,28 +5067,57 @@ mips16_call_stub_mode_suffix (enum machine_mode mode) ...@@ -5067,28 +5067,57 @@ mips16_call_stub_mode_suffix (enum machine_mode mode)
gcc_unreachable (); gcc_unreachable ();
} }
/* Write out code to move floating point arguments in or out of /* Write instructions to move a 32-bit value between general register
GPREG and floating-point register FPREG. DIRECTION is 't' to move
from GPREG to FPREG and 'f' to move in the opposite direction. */
static void
mips_output_32bit_xfer (char direction, unsigned int gpreg, unsigned int fpreg)
{
fprintf (asm_out_file, "\tm%cc1\t%s,%s\n", direction,
reg_names[gpreg], reg_names[fpreg]);
}
/* Likewise for 64-bit values. */
static void
mips_output_64bit_xfer (char direction, unsigned int gpreg, unsigned int fpreg)
{
if (TARGET_64BIT)
fprintf (asm_out_file, "\tdm%cc1\t%s,%s\n", direction,
reg_names[gpreg], reg_names[fpreg]);
else if (TARGET_FLOAT64)
{
fprintf (asm_out_file, "\tm%cc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_BIG_ENDIAN], reg_names[fpreg]);
fprintf (asm_out_file, "\tm%chc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_LITTLE_ENDIAN], reg_names[fpreg]);
}
else
{
/* Move the least-significant word. */
fprintf (asm_out_file, "\tm%cc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_BIG_ENDIAN], reg_names[fpreg]);
/* ...then the most significant word. */
fprintf (asm_out_file, "\tm%cc1\t%s,%s\n", direction,
reg_names[gpreg + TARGET_LITTLE_ENDIAN], reg_names[fpreg + 1]);
}
}
/* Write out code to move floating-point arguments into or out of
general registers. FP_CODE is the code describing which arguments general registers. FP_CODE is the code describing which arguments
are present (see the comment at the definition of CUMULATIVE_ARGS in are present (see the comment above the definition of CUMULATIVE_ARGS
mips.h). FROM_FP_P is nonzero if we are copying from the floating in mips.h). DIRECTION is as for mips_output_32bit_xfer. */
point registers. */
static void static void
mips16_fp_args (int fp_code, int from_fp_p) mips_output_args_xfer (int fp_code, char direction)
{ {
const char *s; unsigned int gparg, fparg, f;
int gparg, fparg;
unsigned int f;
CUMULATIVE_ARGS cum; CUMULATIVE_ARGS cum;
/* This code only works for the original 32-bit ABI and the O64 ABI. */ /* This code only works for the original 32-bit ABI and the O64 ABI. */
gcc_assert (TARGET_OLDABI); gcc_assert (TARGET_OLDABI);
if (from_fp_p)
s = "mfc1";
else
s = "mtc1";
init_cumulative_args (&cum, NULL, NULL); init_cumulative_args (&cum, NULL, NULL);
for (f = (unsigned int) fp_code; f != 0; f >>= 2) for (f = (unsigned int) fp_code; f != 0; f >>= 2)
...@@ -5108,28 +5137,9 @@ mips16_fp_args (int fp_code, int from_fp_p) ...@@ -5108,28 +5137,9 @@ mips16_fp_args (int fp_code, int from_fp_p)
fparg = mips_arg_regno (&info, true); fparg = mips_arg_regno (&info, true);
if (mode == SFmode) if (mode == SFmode)
fprintf (asm_out_file, "\t%s\t%s,%s\n", s, mips_output_32bit_xfer (direction, gparg, fparg);
reg_names[gparg], reg_names[fparg]);
else if (TARGET_64BIT)
fprintf (asm_out_file, "\td%s\t%s,%s\n", s,
reg_names[gparg], reg_names[fparg]);
else if (ISA_HAS_MXHC1)
/* -mips32r2 -mfp64 */
fprintf (asm_out_file, "\t%s\t%s,%s\n\t%s\t%s,%s\n",
s,
reg_names[gparg + (WORDS_BIG_ENDIAN ? 1 : 0)],
reg_names[fparg],
from_fp_p ? "mfhc1" : "mthc1",
reg_names[gparg + (WORDS_BIG_ENDIAN ? 0 : 1)],
reg_names[fparg]);
else if (TARGET_BIG_ENDIAN)
fprintf (asm_out_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 else
fprintf (asm_out_file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s, mips_output_64bit_xfer (direction, gparg, fparg);
reg_names[gparg], reg_names[fparg], s,
reg_names[gparg + 1], reg_names[fparg + 1]);
function_arg_advance (&cum, mode, NULL, true); function_arg_advance (&cum, mode, NULL, true);
} }
...@@ -5193,7 +5203,7 @@ build_mips16_function_stub (void) ...@@ -5193,7 +5203,7 @@ build_mips16_function_stub (void)
/* We don't want the assembler to insert any nops here. */ /* We don't want the assembler to insert any nops here. */
fprintf (asm_out_file, "\t.set\tnoreorder\n"); fprintf (asm_out_file, "\t.set\tnoreorder\n");
mips16_fp_args (current_function_args_info.fp_code, 1); mips_output_args_xfer (current_function_args_info.fp_code, 'f');
fprintf (asm_out_file, "\t.set\tnoat\n"); fprintf (asm_out_file, "\t.set\tnoat\n");
fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]); fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
...@@ -5221,47 +5231,6 @@ build_mips16_function_stub (void) ...@@ -5221,47 +5231,6 @@ build_mips16_function_stub (void)
switch_to_section (function_section (current_function_decl)); switch_to_section (function_section (current_function_decl));
} }
/* Emit code to return a double value from a mips16 stub. GPREG is the
first GP reg to use, FPREG is the first FP reg to use. */
static void
mips16_fpret_double (int gpreg, int fpreg)
{
if (TARGET_64BIT)
fprintf (asm_out_file, "\tdmfc1\t%s,%s\n",
reg_names[gpreg], reg_names[fpreg]);
else if (TARGET_FLOAT64)
{
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
reg_names[gpreg + WORDS_BIG_ENDIAN],
reg_names[fpreg]);
fprintf (asm_out_file, "\tmfhc1\t%s,%s\n",
reg_names[gpreg + !WORDS_BIG_ENDIAN],
reg_names[fpreg]);
}
else
{
if (TARGET_BIG_ENDIAN)
{
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
reg_names[gpreg + 0],
reg_names[fpreg + 1]);
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
reg_names[gpreg + 1],
reg_names[fpreg + 0]);
}
else
{
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
reg_names[gpreg + 0],
reg_names[fpreg + 0]);
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
reg_names[gpreg + 1],
reg_names[fpreg + 1]);
}
}
}
/* Build a call stub for a mips16 call. A stub is needed if we are /* Build a call stub for a mips16 call. A stub is needed if we are
passing any floating point values which should go into the floating passing any floating point values which should go into the floating
point registers. If we are, and the call turns out to be to a point registers. If we are, and the call turns out to be to a
...@@ -5452,7 +5421,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) ...@@ -5452,7 +5421,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
/* We don't want the assembler to insert any nops here. */ /* We don't want the assembler to insert any nops here. */
fprintf (asm_out_file, "\t.set\tnoreorder\n"); fprintf (asm_out_file, "\t.set\tnoreorder\n");
mips16_fp_args (fp_code, 0); mips_output_args_xfer (fp_code, 't');
if (! fpret) if (! fpret)
{ {
...@@ -5478,36 +5447,33 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) ...@@ -5478,36 +5447,33 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
switch (GET_MODE (retval)) switch (GET_MODE (retval))
{ {
case SCmode: case SCmode:
fprintf (asm_out_file, "\tmfc1\t%s,%s\n", mips_output_32bit_xfer ('f', GP_RETURN + 1,
reg_names[GP_REG_FIRST + 3], FP_REG_FIRST + MAX_FPRS_PER_FMT);
reg_names[FP_REG_FIRST + MAX_FPRS_PER_FMT]);
/* Fall though. */ /* Fall though. */
case SFmode: case SFmode:
fprintf (asm_out_file, "\tmfc1\t%s,%s\n", mips_output_32bit_xfer ('f', GP_RETURN, FP_REG_FIRST);
reg_names[GP_REG_FIRST + 2],
reg_names[FP_REG_FIRST + 0]);
if (GET_MODE (retval) == SCmode && TARGET_64BIT) if (GET_MODE (retval) == SCmode && TARGET_64BIT)
{ {
/* On 64-bit targets, complex floats are returned in /* On 64-bit targets, complex floats are returned in
a single GPR, such that "sd" on a suitably-aligned a single GPR, such that "sd" on a suitably-aligned
target would store the value correctly. */ target would store the value correctly. */
fprintf (asm_out_file, "\tdsll\t%s,%s,32\n", fprintf (asm_out_file, "\tdsll\t%s,%s,32\n",
reg_names[GP_REG_FIRST + 2 + TARGET_LITTLE_ENDIAN], reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN],
reg_names[GP_REG_FIRST + 2 + TARGET_LITTLE_ENDIAN]); reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN]);
fprintf (asm_out_file, "\tor\t%s,%s,%s\n", fprintf (asm_out_file, "\tor\t%s,%s,%s\n",
reg_names[GP_REG_FIRST + 2], reg_names[GP_RETURN],
reg_names[GP_REG_FIRST + 2], reg_names[GP_RETURN],
reg_names[GP_REG_FIRST + 3]); reg_names[GP_RETURN + 1]);
} }
break; break;
case DCmode: case DCmode:
mips16_fpret_double (GP_REG_FIRST + 2 + (8 / UNITS_PER_WORD), mips_output_64bit_xfer ('f', GP_RETURN + (8 / UNITS_PER_WORD),
FP_REG_FIRST + MAX_FPRS_PER_FMT); FP_REG_FIRST + MAX_FPRS_PER_FMT);
/* Fall though. */ /* Fall though. */
case DFmode: case DFmode:
case V2SFmode: case V2SFmode:
mips16_fpret_double (GP_REG_FIRST + 2, FP_REG_FIRST + 0); mips_output_64bit_xfer ('f', GP_RETURN, FP_REG_FIRST);
break; break;
default: default:
......
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