Fix up MIPS16 hard float and add support for complex.
2007-05-23 Sandra Loosemore <sandra@codesourcery.com> Nigel Stephens <nigel@mips.com> Richard Sandiford <richard@codesourcery.com> gcc/ Fix up MIPS16 hard float and add support for complex. * config/mips/mips.h (TARGET_HARD_FLOAT_ABI): New. (TARGET_SOFT_FLOAT_ABI): New. (TARGET_CPU_CPP_BUILTINS): Define __mips_hard_float and __mips_soft_float to reflect the ABI in use, not whether the FPU is directly accessible (e.g., in MIPS16 mode). (UNITS_PER_HWFPVALUE): Use TARGET_SOFT_FLOAT_ABI. (UNITS_PER_FPVALUE): Likewise. * config/mips/mips.c (mips_expand_call): Remove redundant TARGET_MIPS16 check. (mips_arg_regno): New. (function_arg_advance): When setting bits in cum->fp_code for MIPS16, don't subtract 1 from cum->arg_number, since it is now zero-based. (function_arg): Use mips_arg_regno. (mips_return_mode_in_fpr_p): New. (mips16_call_stub_mode_suffix): New. (mips16_cfun_returns_in_fpr_p): New. (mips_save_reg_p): Use mips16_cfun_returns_in_fpr_p. (mips_output_function_prologue): Test mips16_hard_float, not !TARGET_SOFT_FLOAT, to decide when a function stub is required. (mips_expand_epilogue): Call MIPS16 helper routines to copy return value into a floating-point register. (mips_can_use_return_insn): Use mips16_cfun_returns_in_fpr_p. (mips_function_value): Rewrite to use mips_return_mode_in_fpr_p. (mips16_fp_args): Handle MIPS32r2 ISA which supports TARGET_FLOAT64, and use mfhc1/mthc1 to copy the most significant word of double arguments from or to the high bits of 64-bit floating point registers. (build_mips16_function_stub): Fill in DECL_RESULT for stubdecl. (mips16_fpret_double): New helper function. (build_mips16_call_stub): Use mips16_return_mode_in_fpr_p. Add support for complex modes. Fill in DECL_RESULT for stubdecl. (mips_init_libfuncs): Remove redundant TARGET_MIPS16 check. * config/mips/mips16.S (RET, ARG1, ARG2): New. (MERGE_GPRf, MERGE_GPRt): New. (DELAYt, DELAYf): New. (MOVE_SF_BYTE0, MOVE_SI_BYTE0): New. (MOVE_SF_BYTE4, MOVE_SF_BYTE8): New. (MOVE_DF_BYTE0, MOVE_DF_BYTE8): New. (MOVE_SF_RET, MOVE_SC_RET, MOVE_DF_RET, MOVE_DC_RET, MOVE_SI_RET): New. (SFOP): Renamed to... (OPSF3): This, and macro-ified. Updated all uses. (SFOP2): Renamed to... (OPSF2): This, and macro-ified. Updated all uses. (SFCMP): Renamed to... (CMPSF): This, and macro-ified. Updated all uses. (SFREVCMP): Renamed to... (REVCMPSF): This, and macro-ified. Updated all uses. (__mips16_floatsisf, __mips16_fix_truncsfsi): Macro-ified. (LDDBL1, LDDBL2, RETDBL): Deleted. (DFOP): Renamed to... (OPDF3): This, and macro-ified. Updated all uses. (DFOP2): Renamed to... (OPDF2): This, and macro-ified. Updated all uses. (__mips16_extendsfdf2, __mips16_truncdfsf2): Macro-ified. (DFCMP): Renamed to... (CMPDF): This, and macro-ified. Updated all uses. (DFREVCMP): Renamed to... (REVCMPDF): This, and macro-ified. Updated all uses. (__mips16_floatsidf, __mips16_fix_truncdfsi): Macro-ified. (RET_FUNCTION): New. (__mips16_ret_sf, __mips16_ret_df): Macro-ified. (__mips16_ret_sc, __mips16_ret_dc): New. (STUB_ARGS_0, STUB_ARGS_1, STUB_ARGS_5, STUB_ARGS_9, STUB_ARGS_2, STUB_ARGS_6, STUB_ARGS_10): New. (CALL_STUB_NO_RET): New. (__mips16_call_stub_1): Macro-ified. (__mips16_call_stub_5): Macro-ified. (__mips16_call_stub_2): Macro-ified. (__mips16_call_stub_6): Macro-ified. (__mips16_call_stub_9): Macro-ified. (__mips16_call_stub_10): Macro-ified. (CALL_STUB_RET): New. (__mips16_call_stub_sf_0): Macro-ified. (__mips16_call_stub_sf_1): Macro-ified. (__mips16_call_stub_sf_5): Macro-ified. (__mips16_call_stub_sf_2): Macro-ified. (__mips16_call_stub_sf_6): Macro-ified. (__mips16_call_stub_sf_9): Macro-ified. (__mips16_call_stub_sf_10): Macro-ified. (__mips16_call_stub_df_0): Macro-ified. (__mips16_call_stub_df_1): Macro-ified. (__mips16_call_stub_df_5): Macro-ified. (__mips16_call_stub_df_2): Macro-ified. (__mips16_call_stub_df_6): Macro-ified. (__mips16_call_stub_df_9): Macro-ified. (__mips16_call_stub_df_10): Macro-ified. (__mips16_call_stub_sc_0): New. (__mips16_call_stub_sc_1): New. (__mips16_call_stub_sc_5): New. (__mips16_call_stub_sc_2): New. (__mips16_call_stub_sc_6): New. (__mips16_call_stub_sc_9): New. (__mips16_call_stub_sc_10): New. (__mips16_call_stub_dc_0): New. (__mips16_call_stub_dc_1): New. (__mips16_call_stub_dc_5): New. (__mips16_call_stub_dc_2): New. (__mips16_call_stub_dc_6): New. (__mips16_call_stub_dc_9): New. (__mips16_call_stub_dc_10): New. * config/mips/t-elf (LIB1ASMFUNCS): Add MIPS16 floating-point stubs. * config/mips/t-isa3264 (LIB1ASMFUNCS): Likewise. * config/mips/t-r2900 (LIB1ASMFUNCS): Likewise. gcc/testsuite/ * gcc.target/mips/inter/mips16_stubs_1_main.c: New. * gcc.target/mips/inter/mips16_stubs_1_x.c: New. * gcc.target/mips/inter/mips16_stubs_1_y.c: New. * gcc.target/mips/inter/mips16-inter.exp: New. Co-Authored-By: Nigel Stephens <nigel@mips.com> Co-Authored-By: Richard Sandiford <richard@codesourcery.com> From-SVN: r124999
This commit is contained in:
parent
70c1e0331b
commit
a38e0142a8
12 changed files with 1141 additions and 556 deletions
115
gcc/ChangeLog
115
gcc/ChangeLog
|
@ -1,3 +1,118 @@
|
|||
2007-05-23 Sandra Loosemore <sandra@codesourcery.com>
|
||||
Nigel Stephens <nigel@mips.com>
|
||||
Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
Fix up MIPS16 hard float and add support for complex.
|
||||
|
||||
* config/mips/mips.h (TARGET_HARD_FLOAT_ABI): New.
|
||||
(TARGET_SOFT_FLOAT_ABI): New.
|
||||
(TARGET_CPU_CPP_BUILTINS): Define __mips_hard_float and
|
||||
__mips_soft_float to reflect the ABI in use, not whether the
|
||||
FPU is directly accessible (e.g., in MIPS16 mode).
|
||||
(UNITS_PER_HWFPVALUE): Use TARGET_SOFT_FLOAT_ABI.
|
||||
(UNITS_PER_FPVALUE): Likewise.
|
||||
|
||||
* config/mips/mips.c (mips_expand_call): Remove redundant
|
||||
TARGET_MIPS16 check.
|
||||
(mips_arg_regno): New.
|
||||
(function_arg_advance): When setting bits in cum->fp_code for
|
||||
MIPS16, don't subtract 1 from cum->arg_number, since it is now
|
||||
zero-based.
|
||||
(function_arg): Use mips_arg_regno.
|
||||
(mips_return_mode_in_fpr_p): New.
|
||||
(mips16_call_stub_mode_suffix): New.
|
||||
(mips16_cfun_returns_in_fpr_p): New.
|
||||
(mips_save_reg_p): Use mips16_cfun_returns_in_fpr_p.
|
||||
(mips_output_function_prologue): Test mips16_hard_float, not
|
||||
!TARGET_SOFT_FLOAT, to decide when a function stub is required.
|
||||
(mips_expand_epilogue): Call MIPS16 helper routines to copy
|
||||
return value into a floating-point register.
|
||||
(mips_can_use_return_insn): Use mips16_cfun_returns_in_fpr_p.
|
||||
(mips_function_value): Rewrite to use mips_return_mode_in_fpr_p.
|
||||
(mips16_fp_args): Handle MIPS32r2 ISA which supports
|
||||
TARGET_FLOAT64, and use mfhc1/mthc1 to copy the most significant
|
||||
word of double arguments from or to the high bits of 64-bit
|
||||
floating point registers.
|
||||
(build_mips16_function_stub): Fill in DECL_RESULT for stubdecl.
|
||||
(mips16_fpret_double): New helper function.
|
||||
(build_mips16_call_stub): Use mips16_return_mode_in_fpr_p. Add
|
||||
support for complex modes. Fill in DECL_RESULT for stubdecl.
|
||||
(mips_init_libfuncs): Remove redundant TARGET_MIPS16 check.
|
||||
|
||||
* config/mips/mips16.S
|
||||
(RET, ARG1, ARG2): New.
|
||||
(MERGE_GPRf, MERGE_GPRt): New.
|
||||
(DELAYt, DELAYf): New.
|
||||
(MOVE_SF_BYTE0, MOVE_SI_BYTE0): New.
|
||||
(MOVE_SF_BYTE4, MOVE_SF_BYTE8): New.
|
||||
(MOVE_DF_BYTE0, MOVE_DF_BYTE8): New.
|
||||
(MOVE_SF_RET, MOVE_SC_RET, MOVE_DF_RET, MOVE_DC_RET, MOVE_SI_RET): New.
|
||||
(SFOP): Renamed to...
|
||||
(OPSF3): This, and macro-ified. Updated all uses.
|
||||
(SFOP2): Renamed to...
|
||||
(OPSF2): This, and macro-ified. Updated all uses.
|
||||
(SFCMP): Renamed to...
|
||||
(CMPSF): This, and macro-ified. Updated all uses.
|
||||
(SFREVCMP): Renamed to...
|
||||
(REVCMPSF): This, and macro-ified. Updated all uses.
|
||||
(__mips16_floatsisf, __mips16_fix_truncsfsi): Macro-ified.
|
||||
(LDDBL1, LDDBL2, RETDBL): Deleted.
|
||||
(DFOP): Renamed to...
|
||||
(OPDF3): This, and macro-ified. Updated all uses.
|
||||
(DFOP2): Renamed to...
|
||||
(OPDF2): This, and macro-ified. Updated all uses.
|
||||
(__mips16_extendsfdf2, __mips16_truncdfsf2): Macro-ified.
|
||||
(DFCMP): Renamed to...
|
||||
(CMPDF): This, and macro-ified. Updated all uses.
|
||||
(DFREVCMP): Renamed to...
|
||||
(REVCMPDF): This, and macro-ified. Updated all uses.
|
||||
(__mips16_floatsidf, __mips16_fix_truncdfsi): Macro-ified.
|
||||
(RET_FUNCTION): New.
|
||||
(__mips16_ret_sf, __mips16_ret_df): Macro-ified.
|
||||
(__mips16_ret_sc, __mips16_ret_dc): New.
|
||||
(STUB_ARGS_0, STUB_ARGS_1, STUB_ARGS_5, STUB_ARGS_9, STUB_ARGS_2,
|
||||
STUB_ARGS_6, STUB_ARGS_10): New.
|
||||
(CALL_STUB_NO_RET): New.
|
||||
(__mips16_call_stub_1): Macro-ified.
|
||||
(__mips16_call_stub_5): Macro-ified.
|
||||
(__mips16_call_stub_2): Macro-ified.
|
||||
(__mips16_call_stub_6): Macro-ified.
|
||||
(__mips16_call_stub_9): Macro-ified.
|
||||
(__mips16_call_stub_10): Macro-ified.
|
||||
(CALL_STUB_RET): New.
|
||||
(__mips16_call_stub_sf_0): Macro-ified.
|
||||
(__mips16_call_stub_sf_1): Macro-ified.
|
||||
(__mips16_call_stub_sf_5): Macro-ified.
|
||||
(__mips16_call_stub_sf_2): Macro-ified.
|
||||
(__mips16_call_stub_sf_6): Macro-ified.
|
||||
(__mips16_call_stub_sf_9): Macro-ified.
|
||||
(__mips16_call_stub_sf_10): Macro-ified.
|
||||
(__mips16_call_stub_df_0): Macro-ified.
|
||||
(__mips16_call_stub_df_1): Macro-ified.
|
||||
(__mips16_call_stub_df_5): Macro-ified.
|
||||
(__mips16_call_stub_df_2): Macro-ified.
|
||||
(__mips16_call_stub_df_6): Macro-ified.
|
||||
(__mips16_call_stub_df_9): Macro-ified.
|
||||
(__mips16_call_stub_df_10): Macro-ified.
|
||||
(__mips16_call_stub_sc_0): New.
|
||||
(__mips16_call_stub_sc_1): New.
|
||||
(__mips16_call_stub_sc_5): New.
|
||||
(__mips16_call_stub_sc_2): New.
|
||||
(__mips16_call_stub_sc_6): New.
|
||||
(__mips16_call_stub_sc_9): New.
|
||||
(__mips16_call_stub_sc_10): New.
|
||||
(__mips16_call_stub_dc_0): New.
|
||||
(__mips16_call_stub_dc_1): New.
|
||||
(__mips16_call_stub_dc_5): New.
|
||||
(__mips16_call_stub_dc_2): New.
|
||||
(__mips16_call_stub_dc_6): New.
|
||||
(__mips16_call_stub_dc_9): New.
|
||||
(__mips16_call_stub_dc_10): New.
|
||||
|
||||
* config/mips/t-elf (LIB1ASMFUNCS): Add MIPS16 floating-point stubs.
|
||||
* config/mips/t-isa3264 (LIB1ASMFUNCS): Likewise.
|
||||
* config/mips/t-r2900 (LIB1ASMFUNCS): Likewise.
|
||||
|
||||
2007-05-23 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* doc/invoke.texi (Invoking GCC): Document that the order of the
|
||||
|
|
|
@ -3490,8 +3490,7 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
|
|||
mips_load_call_address (addr, orig_addr, sibcall_p);
|
||||
}
|
||||
|
||||
if (TARGET_MIPS16
|
||||
&& mips16_hard_float
|
||||
if (mips16_hard_float
|
||||
&& build_mips16_call_stub (result, addr, args_size,
|
||||
aux == 0 ? 0 : (int) GET_MODE (aux)))
|
||||
return;
|
||||
|
@ -3878,6 +3877,24 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||
}
|
||||
|
||||
|
||||
/* INFO describes an argument that is passed in a single-register value.
|
||||
Return the register it uses, assuming that FPRs are available if
|
||||
HARD_FLOAT_P. */
|
||||
|
||||
static unsigned int
|
||||
mips_arg_regno (const struct mips_arg_info *info, bool hard_float_p)
|
||||
{
|
||||
if (!info->fpr_p || !hard_float_p)
|
||||
return GP_ARG_FIRST + info->reg_offset;
|
||||
else if (mips_abi == ABI_32 && TARGET_DOUBLE_FLOAT && info->reg_offset > 0)
|
||||
/* In o32, the second argument is always passed in $f14
|
||||
for TARGET_DOUBLE_FLOAT, regardless of whether the
|
||||
first argument was a word or doubleword. */
|
||||
return FP_ARG_FIRST + 2;
|
||||
else
|
||||
return FP_ARG_FIRST + info->reg_offset;
|
||||
}
|
||||
|
||||
/* Implement FUNCTION_ARG_ADVANCE. */
|
||||
|
||||
void
|
||||
|
@ -3895,7 +3912,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||
for an explanation of what this code does. It assumes the O32
|
||||
ABI, which passes at most 2 arguments in float registers. */
|
||||
if (cum->arg_number < 2 && info.fpr_p)
|
||||
cum->fp_code += (mode == SFmode ? 1 : 2) << ((cum->arg_number - 1) * 2);
|
||||
cum->fp_code += (mode == SFmode ? 1 : 2) << (cum->arg_number * 2);
|
||||
|
||||
if (mips_abi != ABI_EABI || !info.fpr_p)
|
||||
cum->num_gprs = info.reg_offset + info.reg_words;
|
||||
|
@ -4032,15 +4049,7 @@ function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
|||
}
|
||||
}
|
||||
|
||||
if (!info.fpr_p)
|
||||
return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
|
||||
else if (mips_abi == ABI_32 && TARGET_DOUBLE_FLOAT && info.reg_offset > 0)
|
||||
/* In o32, the second argument is always passed in $f14
|
||||
for TARGET_DOUBLE_FLOAT, regardless of whether the
|
||||
first argument was a word or doubleword. */
|
||||
return gen_rtx_REG (mode, FP_ARG_FIRST + 2);
|
||||
else
|
||||
return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
|
||||
return gen_rtx_REG (mode, mips_arg_regno (&info, TARGET_HARD_FLOAT));
|
||||
}
|
||||
|
||||
|
||||
|
@ -6303,6 +6312,51 @@ mips_global_pointer (void)
|
|||
}
|
||||
|
||||
|
||||
/* Return true if the function return value MODE will get returned in a
|
||||
floating-point register. */
|
||||
|
||||
static bool
|
||||
mips_return_mode_in_fpr_p (enum machine_mode mode)
|
||||
{
|
||||
return ((GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
|
||||
|| GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
|
||||
&& GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_HWFPVALUE);
|
||||
}
|
||||
|
||||
/* Return a two-character string representing a function floating-point
|
||||
return mode, used to name MIPS16 function stubs. */
|
||||
|
||||
static const char *
|
||||
mips16_call_stub_mode_suffix (enum machine_mode mode)
|
||||
{
|
||||
if (mode == SFmode)
|
||||
return "sf";
|
||||
else if (mode == DFmode)
|
||||
return "df";
|
||||
else if (mode == SCmode)
|
||||
return "sc";
|
||||
else if (mode == DCmode)
|
||||
return "dc";
|
||||
else if (mode == V2SFmode)
|
||||
return "df";
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Return true if the current function returns its value in a floating-point
|
||||
register in MIPS16 mode. */
|
||||
|
||||
static bool
|
||||
mips16_cfun_returns_in_fpr_p (void)
|
||||
{
|
||||
tree return_type = DECL_RESULT (current_function_decl);
|
||||
return (mips16_hard_float
|
||||
&& !aggregate_value_p (return_type, current_function_decl)
|
||||
&& mips_return_mode_in_fpr_p (DECL_MODE (return_type)));
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the current function must save REGNO. */
|
||||
|
||||
static bool
|
||||
|
@ -6337,10 +6391,6 @@ mips_save_reg_p (unsigned int regno)
|
|||
|
||||
if (TARGET_MIPS16)
|
||||
{
|
||||
tree return_type;
|
||||
|
||||
return_type = DECL_RESULT (current_function_decl);
|
||||
|
||||
/* $18 is a special case in mips16 code. It may be used to call
|
||||
a function which returns a floating point value, but it is
|
||||
marked in call_used_regs. */
|
||||
|
@ -6351,10 +6401,7 @@ mips_save_reg_p (unsigned int regno)
|
|||
value into the floating point registers if the return value is
|
||||
floating point. */
|
||||
if (regno == GP_REG_FIRST + 31
|
||||
&& mips16_hard_float
|
||||
&& !aggregate_value_p (return_type, current_function_decl)
|
||||
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
|
||||
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
|
||||
&& mips16_cfun_returns_in_fpr_p ())
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6739,7 +6786,7 @@ mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
|
|||
floating point arguments. The linker will arrange for any 32-bit
|
||||
functions to call this stub, which will then jump to the 16-bit
|
||||
function proper. */
|
||||
if (TARGET_MIPS16 && !TARGET_SOFT_FLOAT
|
||||
if (mips16_hard_float
|
||||
&& current_function_args_info.fp_code != 0)
|
||||
build_mips16_function_stub (file);
|
||||
|
||||
|
@ -7069,6 +7116,33 @@ mips_expand_epilogue (int sibcall_p)
|
|||
emit_jump_insn (gen_return ());
|
||||
return;
|
||||
}
|
||||
|
||||
/* In mips16 mode, if the return value should go into a floating-point
|
||||
register, we need to call a helper routine to copy it over. */
|
||||
if (mips16_cfun_returns_in_fpr_p ())
|
||||
{
|
||||
char *name;
|
||||
rtx func;
|
||||
rtx insn;
|
||||
rtx retval;
|
||||
rtx call;
|
||||
tree id;
|
||||
tree return_type;
|
||||
enum machine_mode return_mode;
|
||||
|
||||
return_type = DECL_RESULT (current_function_decl);
|
||||
return_mode = DECL_MODE (return_type);
|
||||
|
||||
name = ACONCAT (("__mips16_ret_",
|
||||
mips16_call_stub_mode_suffix (return_mode),
|
||||
NULL));
|
||||
id = get_identifier (name);
|
||||
func = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id));
|
||||
retval = gen_rtx_REG (return_mode, GP_RETURN);
|
||||
call = gen_call_value_internal (retval, func, const0_rtx);
|
||||
insn = emit_call_insn (call);
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), retval);
|
||||
}
|
||||
|
||||
/* Split the frame into two. STEP1 is the amount of stack we should
|
||||
deallocate before restoring the registers. STEP2 is the amount we
|
||||
|
@ -7175,24 +7249,16 @@ mips_expand_epilogue (int sibcall_p)
|
|||
int
|
||||
mips_can_use_return_insn (void)
|
||||
{
|
||||
tree return_type;
|
||||
|
||||
if (! reload_completed)
|
||||
return 0;
|
||||
|
||||
if (regs_ever_live[31] || current_function_profile)
|
||||
return 0;
|
||||
|
||||
return_type = DECL_RESULT (current_function_decl);
|
||||
|
||||
/* In mips16 mode, a function which returns a floating point value
|
||||
/* In mips16 mode, a function that returns a floating point value
|
||||
needs to arrange to copy the return value into the floating point
|
||||
registers. */
|
||||
if (TARGET_MIPS16
|
||||
&& mips16_hard_float
|
||||
&& ! aggregate_value_p (return_type, current_function_decl)
|
||||
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
|
||||
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
|
||||
if (mips16_cfun_returns_in_fpr_p ())
|
||||
return 0;
|
||||
|
||||
if (cfun->machine->frame.initialized)
|
||||
|
@ -7617,23 +7683,25 @@ mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
|
|||
return gen_rtx_REG (mode, GP_RETURN);
|
||||
}
|
||||
|
||||
if ((GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
|
||||
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
|
||||
return gen_rtx_REG (mode, FP_RETURN);
|
||||
if (!TARGET_MIPS16)
|
||||
{
|
||||
/* Handle long doubles for n32 & n64. */
|
||||
if (mode == TFmode)
|
||||
return mips_return_fpr_pair (mode,
|
||||
DImode, 0,
|
||||
DImode, GET_MODE_SIZE (mode) / 2);
|
||||
|
||||
/* Handle long doubles for n32 & n64. */
|
||||
if (mode == TFmode)
|
||||
return mips_return_fpr_pair (mode,
|
||||
DImode, 0,
|
||||
DImode, GET_MODE_SIZE (mode) / 2);
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
|
||||
&& GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
|
||||
return mips_return_fpr_pair (mode,
|
||||
GET_MODE_INNER (mode), 0,
|
||||
GET_MODE_INNER (mode),
|
||||
GET_MODE_SIZE (mode) / 2);
|
||||
if (mips_return_mode_in_fpr_p (mode))
|
||||
{
|
||||
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
|
||||
return mips_return_fpr_pair (mode,
|
||||
GET_MODE_INNER (mode), 0,
|
||||
GET_MODE_INNER (mode),
|
||||
GET_MODE_SIZE (mode) / 2);
|
||||
else
|
||||
return gen_rtx_REG (mode, FP_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
return gen_rtx_REG (mode, GP_RETURN);
|
||||
}
|
||||
|
@ -7978,6 +8046,7 @@ mips16_fp_args (FILE *file, int fp_code, int from_fp_p)
|
|||
const char *s;
|
||||
int gparg, fparg;
|
||||
unsigned int f;
|
||||
CUMULATIVE_ARGS cum;
|
||||
|
||||
/* This code only works for the original 32-bit ABI and the O64 ABI. */
|
||||
gcc_assert (TARGET_OLDABI);
|
||||
|
@ -7986,43 +8055,50 @@ mips16_fp_args (FILE *file, int fp_code, int from_fp_p)
|
|||
s = "mfc1";
|
||||
else
|
||||
s = "mtc1";
|
||||
gparg = GP_ARG_FIRST;
|
||||
fparg = FP_ARG_FIRST;
|
||||
|
||||
init_cumulative_args (&cum, NULL, NULL);
|
||||
|
||||
for (f = (unsigned int) fp_code; f != 0; f >>= 2)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
struct mips_arg_info info;
|
||||
|
||||
if ((f & 3) == 1)
|
||||
{
|
||||
if ((fparg & 1) != 0)
|
||||
++fparg;
|
||||
fprintf (file, "\t%s\t%s,%s\n", s,
|
||||
reg_names[gparg], reg_names[fparg]);
|
||||
}
|
||||
mode = SFmode;
|
||||
else if ((f & 3) == 2)
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
fprintf (file, "\td%s\t%s,%s\n", s,
|
||||
reg_names[gparg], reg_names[fparg]);
|
||||
else
|
||||
{
|
||||
if ((fparg & 1) != 0)
|
||||
++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;
|
||||
}
|
||||
}
|
||||
mode = DFmode;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
++gparg;
|
||||
++fparg;
|
||||
mips_arg_info (&cum, mode, NULL, true, &info);
|
||||
gparg = mips_arg_regno (&info, false);
|
||||
fparg = mips_arg_regno (&info, true);
|
||||
|
||||
if (mode == SFmode)
|
||||
fprintf (file, "\t%s\t%s,%s\n", s,
|
||||
reg_names[gparg], reg_names[fparg]);
|
||||
else if (TARGET_64BIT)
|
||||
fprintf (file, "\td%s\t%s,%s\n", s,
|
||||
reg_names[gparg], reg_names[fparg]);
|
||||
else if (ISA_HAS_MXHC1)
|
||||
/* -mips32r2 -mfp64 */
|
||||
fprintf (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 (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]);
|
||||
|
||||
function_arg_advance (&cum, mode, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8049,6 +8125,7 @@ build_mips16_function_stub (FILE *file)
|
|||
stubdecl = build_decl (FUNCTION_DECL, stubid,
|
||||
build_function_type (void_type_node, NULL_TREE));
|
||||
DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
|
||||
DECL_RESULT (stubdecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
|
||||
|
||||
fprintf (file, "\t# Stub function for %s (", current_function_name ());
|
||||
need_comma = 0;
|
||||
|
@ -8122,6 +8199,47 @@ struct mips16_stub
|
|||
|
||||
static struct mips16_stub *mips16_stubs;
|
||||
|
||||
/* 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
|
||||
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
|
||||
|
@ -8143,7 +8261,7 @@ static struct mips16_stub *mips16_stubs;
|
|||
int
|
||||
build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
||||
{
|
||||
int fpret;
|
||||
int fpret = 0;
|
||||
const char *fnname;
|
||||
char *secname, *stubname;
|
||||
struct mips16_stub *l;
|
||||
|
@ -8153,14 +8271,13 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
|||
|
||||
/* We don't need to do anything if we aren't in mips16 mode, or if
|
||||
we were invoked with the -msoft-float option. */
|
||||
if (! TARGET_MIPS16 || ! mips16_hard_float)
|
||||
if (!mips16_hard_float)
|
||||
return 0;
|
||||
|
||||
/* Figure out whether the value might come back in a floating point
|
||||
register. */
|
||||
fpret = (retval != 0
|
||||
&& GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
|
||||
&& GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE);
|
||||
if (retval)
|
||||
fpret = mips_return_mode_in_fpr_p (GET_MODE (retval));
|
||||
|
||||
/* We don't need to do anything if there were no floating point
|
||||
arguments and the value will not be returned in a floating point
|
||||
|
@ -8178,11 +8295,6 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
|||
require more sophisticated support. */
|
||||
gcc_assert (TARGET_OLDABI);
|
||||
|
||||
/* We can only handle SFmode and DFmode floating point return
|
||||
values. */
|
||||
if (fpret)
|
||||
gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode);
|
||||
|
||||
/* If we're calling via a function pointer, then we must always call
|
||||
via a stub. There are magic stubs provided in libgcc.a for each
|
||||
of the required cases. Each of them expects the function address
|
||||
|
@ -8197,11 +8309,14 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
|||
/* ??? If this code is modified to support other ABI's, we need
|
||||
to handle PARALLEL return values here. */
|
||||
|
||||
sprintf (buf, "__mips16_call_stub_%s%d",
|
||||
(fpret
|
||||
? (GET_MODE (retval) == SFmode ? "sf_" : "df_")
|
||||
: ""),
|
||||
fp_code);
|
||||
if (fpret)
|
||||
sprintf (buf, "__mips16_call_stub_%s_%d",
|
||||
mips16_call_stub_mode_suffix (GET_MODE (retval)),
|
||||
fp_code);
|
||||
else
|
||||
sprintf (buf, "__mips16_call_stub_%d",
|
||||
fp_code);
|
||||
|
||||
id = get_identifier (buf);
|
||||
stub_fn = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id));
|
||||
|
||||
|
@ -8277,6 +8392,7 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
|||
stubdecl = build_decl (FUNCTION_DECL, stubid,
|
||||
build_function_type (void_type_node, NULL_TREE));
|
||||
DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
|
||||
DECL_RESULT (stubdecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
|
||||
|
||||
fprintf (asm_out_file, "\t# Stub function to call %s%s (",
|
||||
(fpret
|
||||
|
@ -8339,6 +8455,27 @@ build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
|
|||
if (GET_MODE (retval) == SFmode)
|
||||
fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
|
||||
reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]);
|
||||
else if (GET_MODE (retval) == SCmode)
|
||||
{
|
||||
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 + MAX_FPRS_PER_FMT]);
|
||||
}
|
||||
else if (GET_MODE (retval) == DFmode
|
||||
|| GET_MODE (retval) == V2SFmode)
|
||||
{
|
||||
mips16_fpret_double (GP_REG_FIRST + 2, FP_REG_FIRST + 0);
|
||||
}
|
||||
else if (GET_MODE (retval) == DCmode)
|
||||
{
|
||||
mips16_fpret_double (GP_REG_FIRST + 2,
|
||||
FP_REG_FIRST + 0);
|
||||
mips16_fpret_double (GP_REG_FIRST + 4,
|
||||
FP_REG_FIRST + MAX_FPRS_PER_FMT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_BIG_ENDIAN)
|
||||
|
@ -9190,7 +9327,7 @@ mips_init_libfuncs (void)
|
|||
set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
|
||||
}
|
||||
|
||||
if (TARGET_MIPS16 && mips16_hard_float)
|
||||
if (mips16_hard_float)
|
||||
{
|
||||
set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
|
||||
set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
|
||||
|
|
|
@ -288,6 +288,11 @@ extern const struct mips_rtx_cost_data *mips_cost;
|
|||
#define TARGET_OLDABI (mips_abi == ABI_32 || mips_abi == ABI_O64)
|
||||
#define TARGET_NEWABI (mips_abi == ABI_N32 || mips_abi == ABI_64)
|
||||
|
||||
/* Similar to TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT, but reflect the ABI
|
||||
in use rather than whether the FPU is directly accessible. */
|
||||
#define TARGET_HARD_FLOAT_ABI (TARGET_HARD_FLOAT || mips16_hard_float)
|
||||
#define TARGET_SOFT_FLOAT_ABI (!TARGET_HARD_FLOAT_ABI)
|
||||
|
||||
/* IRIX specific stuff. */
|
||||
#define TARGET_IRIX 0
|
||||
#define TARGET_IRIX6 0
|
||||
|
@ -406,9 +411,11 @@ extern const struct mips_rtx_cost_data *mips_cost;
|
|||
builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \
|
||||
} \
|
||||
\
|
||||
if (TARGET_HARD_FLOAT) \
|
||||
/* These defines reflect the ABI in use, not whether the \
|
||||
FPU is directly accessible. */ \
|
||||
if (TARGET_HARD_FLOAT_ABI) \
|
||||
builtin_define ("__mips_hard_float"); \
|
||||
else if (TARGET_SOFT_FLOAT) \
|
||||
else \
|
||||
builtin_define ("__mips_soft_float"); \
|
||||
\
|
||||
if (TARGET_SINGLE_FLOAT) \
|
||||
|
@ -1033,12 +1040,12 @@ extern const struct mips_rtx_cost_data *mips_cost;
|
|||
/* The largest size of value that can be held in floating-point
|
||||
registers and moved with a single instruction. */
|
||||
#define UNITS_PER_HWFPVALUE \
|
||||
(TARGET_SOFT_FLOAT ? 0 : MAX_FPRS_PER_FMT * UNITS_PER_FPREG)
|
||||
(TARGET_SOFT_FLOAT_ABI ? 0 : MAX_FPRS_PER_FMT * UNITS_PER_FPREG)
|
||||
|
||||
/* The largest size of value that can be held in floating-point
|
||||
registers. */
|
||||
#define UNITS_PER_FPVALUE \
|
||||
(TARGET_SOFT_FLOAT ? 0 \
|
||||
(TARGET_SOFT_FLOAT_ABI ? 0 \
|
||||
: TARGET_SINGLE_FLOAT ? UNITS_PER_FPREG \
|
||||
: LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,11 +19,16 @@ LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
|
|||
_m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
|
||||
_m16fltsidf _m16fix_truncdfsi \
|
||||
_m16retsf _m16retdf \
|
||||
_m16retsc _m16retdc \
|
||||
_m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
|
||||
_m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
|
||||
_m16stubsf9 _m16stubsf10 \
|
||||
_m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
|
||||
_m16stubdf9 _m16stubdf10
|
||||
_m16stubdf9 _m16stubdf10 \
|
||||
_m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \
|
||||
_m16stubsc9 _m16stubsc10 \
|
||||
_m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \
|
||||
_m16stubdc9 _m16stubdc10
|
||||
|
||||
# We must build libgcc2.a with -G 0, in case the user wants to link
|
||||
# without the $gp register.
|
||||
|
|
|
@ -19,11 +19,16 @@ LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
|
|||
_m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
|
||||
_m16fltsidf _m16fix_truncdfsi \
|
||||
_m16retsf _m16retdf \
|
||||
_m16retsc _m16retdc \
|
||||
_m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
|
||||
_m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
|
||||
_m16stubsf9 _m16stubsf10 \
|
||||
_m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
|
||||
_m16stubdf9 _m16stubdf10
|
||||
_m16stubdf9 _m16stubdf10 \
|
||||
_m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \
|
||||
_m16stubsc9 _m16stubsc10 \
|
||||
_m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \
|
||||
_m16stubdc9 _m16stubdc10
|
||||
|
||||
# We must build libgcc2.a with -G 0, in case the user wants to link
|
||||
# without the $gp register.
|
||||
|
|
|
@ -7,11 +7,16 @@ LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
|
|||
_m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
|
||||
_m16fltsidf _m16fix_truncdfsi \
|
||||
_m16retsf _m16retdf \
|
||||
_m16retsc _m16retdc \
|
||||
_m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
|
||||
_m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
|
||||
_m16stubsf9 _m16stubsf10 \
|
||||
_m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
|
||||
_m16stubdf9 _m16stubdf10
|
||||
_m16stubdf9 _m16stubdf10 \
|
||||
_m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \
|
||||
_m16stubsc9 _m16stubsc10 \
|
||||
_m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \
|
||||
_m16stubdc9 _m16stubdc10
|
||||
|
||||
# We must build libgcc2.a with -G 0, in case the user wants to link
|
||||
# without the $gp register.
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2007-05-23 Sandra Loosemore <sandra@codesourcery.com>
|
||||
Nigel Stephens <nigel@mips.com>
|
||||
Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* gcc.target/mips/inter/mips16_stubs_1_main.c: New.
|
||||
* gcc.target/mips/inter/mips16_stubs_1_x.c: New.
|
||||
* gcc.target/mips/inter/mips16_stubs_1_y.c: New.
|
||||
* gcc.target/mips/inter/mips16-inter.exp: New.
|
||||
|
||||
2007-05-23 Kazu Hirata <kazu@codesourcery.com>
|
||||
|
||||
* gcc.dg/bf-spl1.c, gcc.dg/m68k-pic-1.c: Enable on fido-*-*.
|
||||
|
|
48
gcc/testsuite/gcc.target/mips/inter/mips16-inter.exp
Normal file
48
gcc/testsuite/gcc.target/mips/inter/mips16-inter.exp
Normal file
|
@ -0,0 +1,48 @@
|
|||
# Run compatibility tests in which the "alt" compiler tries to force
|
||||
# MIPS16 mode.
|
||||
|
||||
# We can only guarantee MIPS16 runtime support for certain targets.
|
||||
if { ![istarget mipsisa*-*-elf*] && ![istarget mips64vr*-*-elf*] } {
|
||||
return
|
||||
}
|
||||
|
||||
# Save the old value of CFLAGS_FOR_TARGET, if any.
|
||||
global saved_CFLAGS_FOR_TARGET
|
||||
if { [info exists CFLAGS_FOR_TARGET] } {
|
||||
set saved_CFLAGS_FOR_TARGET $CFLAGS_FOR_TARGET
|
||||
} else {
|
||||
unset -nocomplain saved_CFLAGS_FOR_TARGET
|
||||
}
|
||||
|
||||
# The "alt" compiler is the normal compiler with an extra "-mips16" argument.
|
||||
proc compat-use-alt-compiler { } {
|
||||
global saved_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET
|
||||
|
||||
if { [info exists saved_CFLAGS_FOR_TARGET] } {
|
||||
set CFLAGS_FOR_TARGET [concat $saved_CFLAGS_FOR_TARGET "-mips16"]
|
||||
} else {
|
||||
set CFLAGS_FOR_TARGET "-mips16"
|
||||
}
|
||||
}
|
||||
|
||||
# Make the compiler under test the default.
|
||||
proc compat-use-tst-compiler { } {
|
||||
global saved_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET
|
||||
|
||||
if { [info exists saved_CFLAGS_FOR_TARGET] } {
|
||||
set CFLAGS_FOR_TARGET $saved_CFLAGS_FOR_TARGET
|
||||
} else {
|
||||
unset -nocomplain CFLAGS_FOR_TARGET
|
||||
}
|
||||
}
|
||||
|
||||
load_lib gcc.exp
|
||||
load_lib compat.exp
|
||||
|
||||
gcc_init
|
||||
foreach src [lsort [find $srcdir/$subdir mips16_*_main.c]] {
|
||||
if { [runtest_file_p $runtests $src] } {
|
||||
compat-execute $src "mips16_inter" 1
|
||||
}
|
||||
}
|
||||
compat-use-tst-compiler
|
10
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_main.c
Normal file
10
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_main.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
extern void init (void);
|
||||
extern void test (void);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
init ();
|
||||
test ();
|
||||
return 0;
|
||||
}
|
176
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_x.c
Normal file
176
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_x.c
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/* All the function pointers are declared and initialized in
|
||||
mips16-stubs-2.c. */
|
||||
|
||||
extern double the_result;
|
||||
|
||||
extern void v0 (void);
|
||||
extern void v1 (float);
|
||||
extern void v5 (float, float);
|
||||
extern void v9 (float, double);
|
||||
extern void v2 (double);
|
||||
extern void v6 (double, float);
|
||||
extern void v10 (double, double);
|
||||
|
||||
extern float f0 (void);
|
||||
extern float f1 (float);
|
||||
extern float f5 (float, float);
|
||||
extern float f9 (float, double);
|
||||
extern float f2 (double);
|
||||
extern float f6 (double, float);
|
||||
extern float f10 (double, double);
|
||||
|
||||
extern double d0 (void);
|
||||
extern double d1 (float);
|
||||
extern double d5 (float, float);
|
||||
extern double d9 (float, double);
|
||||
extern double d2 (double);
|
||||
extern double d6 (double, float);
|
||||
extern double d10 (double, double);
|
||||
|
||||
extern _Complex float cf0 (void);
|
||||
extern _Complex float cf1 (float);
|
||||
extern _Complex float cf5 (float, float);
|
||||
extern _Complex float cf9 (float, double);
|
||||
extern _Complex float cf2 (double);
|
||||
extern _Complex float cf6 (double, float);
|
||||
extern _Complex float cf10 (double, double);
|
||||
|
||||
extern _Complex double cd0 (void);
|
||||
extern _Complex double cd1 (float);
|
||||
extern _Complex double cd5 (float, float);
|
||||
extern _Complex double cd9 (float, double);
|
||||
extern _Complex double cd2 (double);
|
||||
extern _Complex double cd6 (double, float);
|
||||
extern _Complex double cd10 (double, double);
|
||||
|
||||
extern void (*pv0) (void);
|
||||
extern void (*pv1) (float);
|
||||
extern void (*pv5) (float, float);
|
||||
extern void (*pv9) (float, double);
|
||||
extern void (*pv2) (double);
|
||||
extern void (*pv6) (double, float);
|
||||
extern void (*pv10) (double, double);
|
||||
|
||||
extern float (*pf0) (void);
|
||||
extern float (*pf1) (float);
|
||||
extern float (*pf5) (float, float);
|
||||
extern float (*pf9) (float, double);
|
||||
extern float (*pf2) (double);
|
||||
extern float (*pf6) (double, float);
|
||||
extern float (*pf10) (double, double);
|
||||
|
||||
extern double (*pd0) (void);
|
||||
extern double (*pd1) (float);
|
||||
extern double (*pd5) (float, float);
|
||||
extern double (*pd9) (float, double);
|
||||
extern double (*pd2) (double);
|
||||
extern double (*pd6) (double, float);
|
||||
extern double (*pd10) (double, double);
|
||||
|
||||
extern _Complex float (*pcf0) (void);
|
||||
extern _Complex float (*pcf1) (float);
|
||||
extern _Complex float (*pcf5) (float, float);
|
||||
extern _Complex float (*pcf9) (float, double);
|
||||
extern _Complex float (*pcf2) (double);
|
||||
extern _Complex float (*pcf6) (double, float);
|
||||
extern _Complex float (*pcf10) (double, double);
|
||||
|
||||
extern _Complex double (*pcd0) (void);
|
||||
extern _Complex double (*pcd1) (float);
|
||||
extern _Complex double (*pcd5) (float, float);
|
||||
extern _Complex double (*pcd9) (float, double);
|
||||
extern _Complex double (*pcd2) (double);
|
||||
extern _Complex double (*pcd6) (double, float);
|
||||
extern _Complex double (*pcd10) (double, double);
|
||||
|
||||
/* Macros for results checking. */
|
||||
#define CHECK_RESULT(x, y) if ((x) != (y)) abort ()
|
||||
#define CHECK_VOID_RESULT(x, y) CHECK_RESULT (((x), the_result), y)
|
||||
|
||||
/* Call functions through pointers and and check against expected results. */
|
||||
void
|
||||
test (void)
|
||||
{
|
||||
|
||||
CHECK_VOID_RESULT (v0 (), 1.0);
|
||||
CHECK_VOID_RESULT (v1 (1.0), 2.0);
|
||||
CHECK_VOID_RESULT (v5 (5.0, 6.0), 12.0);
|
||||
CHECK_VOID_RESULT (v9 (9.0, 10.0), 20.0);
|
||||
CHECK_VOID_RESULT (v2 (2.0), 3.0);
|
||||
CHECK_VOID_RESULT (v6 (6.0, 7.0), 14.0);
|
||||
CHECK_VOID_RESULT (v10 (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT (f0 (), 1.0);
|
||||
CHECK_RESULT (f1 (1.0), 2.0);
|
||||
CHECK_RESULT (f5 (5.0, 6.0), 12.0);
|
||||
CHECK_RESULT (f9 (9.0, 10.0), 20.0);
|
||||
CHECK_RESULT (f2 (2.0), 3.0);
|
||||
CHECK_RESULT (f6 (6.0, 7.0), 14.0);
|
||||
CHECK_RESULT (f10 (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT (d0 (), 1.0);
|
||||
CHECK_RESULT (d1 (1.0), 2.0);
|
||||
CHECK_RESULT (d5 (5.0, 6.0), 12.0);
|
||||
CHECK_RESULT (d9 (9.0, 10.0), 20.0);
|
||||
CHECK_RESULT (d2 (2.0), 3.0);
|
||||
CHECK_RESULT (d6 (6.0, 7.0), 14.0);
|
||||
CHECK_RESULT (d10 (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT (cf0 (), 1.0 + 0.0i);
|
||||
CHECK_RESULT (cf1 (1.0), 2.0 + 1.0i);
|
||||
CHECK_RESULT (cf5 (5.0, 6.0), 12.0 + 5.0i);
|
||||
CHECK_RESULT (cf9 (9.0, 10.0), 20.0 + 9.0i);
|
||||
CHECK_RESULT (cf2 (2.0), 3.0 + 2.0i);
|
||||
CHECK_RESULT (cf6 (6.0, 7.0), 14.0 + 6.0i);
|
||||
CHECK_RESULT (cf10 (10.0, 11.0), 22.0 + 10.0i);
|
||||
|
||||
CHECK_RESULT (cd0 (), 1.0 + 0.0i);
|
||||
CHECK_RESULT (cd1 (1.0), 2.0 + 1.0i);
|
||||
CHECK_RESULT (cd5 (5.0, 6.0), 12.0 + 5.0i);
|
||||
CHECK_RESULT (cd9 (9.0, 10.0), 20.0 + 9.0i);
|
||||
CHECK_RESULT (cd2 (2.0), 3.0 + 2.0i);
|
||||
CHECK_RESULT (cd6 (6.0, 7.0), 14.0 + 6.0i);
|
||||
CHECK_RESULT (cd10 (10.0, 11.0), 22.0 + 10.0i);
|
||||
|
||||
CHECK_VOID_RESULT ((*pv0) (), 1.0);
|
||||
CHECK_VOID_RESULT ((*pv1) (1.0), 2.0);
|
||||
CHECK_VOID_RESULT ((*pv5) (5.0, 6.0), 12.0);
|
||||
CHECK_VOID_RESULT ((*pv9) (9.0, 10.0), 20.0);
|
||||
CHECK_VOID_RESULT ((*pv2) (2.0), 3.0);
|
||||
CHECK_VOID_RESULT ((*pv6) (6.0, 7.0), 14.0);
|
||||
CHECK_VOID_RESULT ((*pv10) (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT ((*pf0) (), 1.0);
|
||||
CHECK_RESULT ((*pf1) (1.0), 2.0);
|
||||
CHECK_RESULT ((*pf5) (5.0, 6.0), 12.0);
|
||||
CHECK_RESULT ((*pf9) (9.0, 10.0), 20.0);
|
||||
CHECK_RESULT ((*pf2) (2.0), 3.0);
|
||||
CHECK_RESULT ((*pf6) (6.0, 7.0), 14.0);
|
||||
CHECK_RESULT ((*pf10) (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT ((*pd0) (), 1.0);
|
||||
CHECK_RESULT ((*pd1) (1.0), 2.0);
|
||||
CHECK_RESULT ((*pd5) (5.0, 6.0), 12.0);
|
||||
CHECK_RESULT ((*pd9) (9.0, 10.0), 20.0);
|
||||
CHECK_RESULT ((*pd2) (2.0), 3.0);
|
||||
CHECK_RESULT ((*pd6) (6.0, 7.0), 14.0);
|
||||
CHECK_RESULT ((*pd10) (10.0, 11.0), 22.0);
|
||||
|
||||
CHECK_RESULT ((*pcf0) (), 1.0 + 0.0i);
|
||||
CHECK_RESULT ((*pcf1) (1.0), 2.0 + 1.0i);
|
||||
CHECK_RESULT ((*pcf5) (5.0, 6.0), 12.0 + 5.0i);
|
||||
CHECK_RESULT ((*pcf9) (9.0, 10.0), 20.0 + 9.0i);
|
||||
CHECK_RESULT ((*pcf2) (2.0), 3.0 + 2.0i);
|
||||
CHECK_RESULT ((*pcf6) (6.0, 7.0), 14.0 + 6.0i);
|
||||
CHECK_RESULT ((*pcf10) (10.0, 11.0), 22.0 + 10.0i);
|
||||
|
||||
CHECK_RESULT ((*pcd0) (), 1.0 + 0.0i);
|
||||
CHECK_RESULT ((*pcd1) (1.0), 2.0 + 1.0i);
|
||||
CHECK_RESULT ((*pcd5) (5.0, 6.0), 12.0 + 5.0i);
|
||||
CHECK_RESULT ((*pcd9) (9.0, 10.0), 20.0 + 9.0i);
|
||||
CHECK_RESULT ((*pcd2) (2.0), 3.0 + 2.0i);
|
||||
CHECK_RESULT ((*pcd6) (6.0, 7.0), 14.0 + 6.0i);
|
||||
CHECK_RESULT ((*pcd10) (10.0, 11.0), 22.0 + 10.0i);
|
||||
}
|
133
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_y.c
Normal file
133
gcc/testsuite/gcc.target/mips/inter/mips16_stubs_1_y.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* All test functions return the sum of arguments, plus 1.
|
||||
Void-returning functions put the result in the_result.
|
||||
Complex-returning functions return their signature number as the
|
||||
(constant) imaginary part of the result. */
|
||||
|
||||
double the_result;
|
||||
|
||||
void v0 (void) { the_result = 1.0; }
|
||||
void v1 (float x) { the_result = 1.0 + x; }
|
||||
void v5 (float x, float y) { the_result = 1.0 + x + y; }
|
||||
void v9 (float x, double y) { the_result = 1.0 + x + y; }
|
||||
void v2 (double x) { the_result = 1.0 + x; }
|
||||
void v6 (double x, float y) { the_result = 1.0 + x + y; }
|
||||
void v10 (double x, double y) { the_result = 1.0 + x + y; }
|
||||
|
||||
float f0 (void) { return 1.0; }
|
||||
float f1 (float x) { return 1.0 + x; }
|
||||
float f5 (float x, float y) { return 1.0 + x + y; }
|
||||
float f9 (float x, double y) { return 1.0 + x + y; }
|
||||
float f2 (double x) { return 1.0 + x; }
|
||||
float f6 (double x, float y) { return 1.0 + x + y; }
|
||||
float f10 (double x, double y) { return 1.0 + x + y; }
|
||||
|
||||
double d0 (void) { return 1.0; }
|
||||
double d1 (float x) { return 1.0 + x; }
|
||||
double d5 (float x, float y) { return 1.0 + x + y; }
|
||||
double d9 (float x, double y) { return 1.0 + x + y; }
|
||||
double d2 (double x) { return 1.0 + x; }
|
||||
double d6 (double x, float y) { return 1.0 + x + y; }
|
||||
double d10 (double x, double y) { return 1.0 + x + y; }
|
||||
|
||||
_Complex float cf0 (void) { return 1.0 + 0.0i; }
|
||||
_Complex float cf1 (float x) { return 1.0 + x + 1.0i; }
|
||||
_Complex float cf5 (float x, float y) { return 1.0 + x + y + 5.0i; }
|
||||
_Complex float cf9 (float x, double y) { return 1.0 + x + y + 9.0i; }
|
||||
_Complex float cf2 (double x) { return 1.0 + x + 2.0i; }
|
||||
_Complex float cf6 (double x, float y) { return 1.0 + x + y + 6.0i; }
|
||||
_Complex float cf10 (double x, double y) { return 1.0 + x + y + 10.0i; }
|
||||
|
||||
_Complex double cd0 (void) { return 1.0 + 0.0i; }
|
||||
_Complex double cd1 (float x) { return 1.0 + x + 1.0i; }
|
||||
_Complex double cd5 (float x, float y) { return 1.0 + x + y + 5.0i; }
|
||||
_Complex double cd9 (float x, double y) { return 1.0 + x + y + 9.0i; }
|
||||
_Complex double cd2 (double x) { return 1.0 + x + 2.0i; }
|
||||
_Complex double cd6 (double x, float y) { return 1.0 + x + y + 6.0i; }
|
||||
_Complex double cd10 (double x, double y) { return 1.0 + x + y + 10.0i; }
|
||||
|
||||
|
||||
/* Declare and initialize all the pointer-to-function variables. */
|
||||
|
||||
void (*pv0) (void);
|
||||
void (*pv1) (float);
|
||||
void (*pv5) (float, float);
|
||||
void (*pv9) (float, double);
|
||||
void (*pv2) (double);
|
||||
void (*pv6) (double, float);
|
||||
void (*pv10) (double, double);
|
||||
|
||||
float (*pf0) (void);
|
||||
float (*pf1) (float);
|
||||
float (*pf5) (float, float);
|
||||
float (*pf9) (float, double);
|
||||
float (*pf2) (double);
|
||||
float (*pf6) (double, float);
|
||||
float (*pf10) (double, double);
|
||||
|
||||
double (*pd0) (void);
|
||||
double (*pd1) (float);
|
||||
double (*pd5) (float, float);
|
||||
double (*pd9) (float, double);
|
||||
double (*pd2) (double);
|
||||
double (*pd6) (double, float);
|
||||
double (*pd10) (double, double);
|
||||
|
||||
_Complex float (*pcf0) (void);
|
||||
_Complex float (*pcf1) (float);
|
||||
_Complex float (*pcf5) (float, float);
|
||||
_Complex float (*pcf9) (float, double);
|
||||
_Complex float (*pcf2) (double);
|
||||
_Complex float (*pcf6) (double, float);
|
||||
_Complex float (*pcf10) (double, double);
|
||||
|
||||
_Complex double (*pcd0) (void);
|
||||
_Complex double (*pcd1) (float);
|
||||
_Complex double (*pcd5) (float, float);
|
||||
_Complex double (*pcd9) (float, double);
|
||||
_Complex double (*pcd2) (double);
|
||||
_Complex double (*pcd6) (double, float);
|
||||
_Complex double (*pcd10) (double, double);
|
||||
|
||||
void
|
||||
init (void)
|
||||
{
|
||||
pv0 = v0;
|
||||
pv1 = v1;
|
||||
pv5 = v5;
|
||||
pv9 = v9;
|
||||
pv2 = v2;
|
||||
pv6 = v6;
|
||||
pv10 = v10;
|
||||
|
||||
pf0 = f0;
|
||||
pf1 = f1;
|
||||
pf5 = f5;
|
||||
pf9 = f9;
|
||||
pf2 = f2;
|
||||
pf6 = f6;
|
||||
pf10 = f10;
|
||||
|
||||
pd0 = d0;
|
||||
pd1 = d1;
|
||||
pd5 = d5;
|
||||
pd9 = d9;
|
||||
pd2 = d2;
|
||||
pd6 = d6;
|
||||
pd10 = d10;
|
||||
|
||||
pcf0 = cf0;
|
||||
pcf1 = cf1;
|
||||
pcf5 = cf5;
|
||||
pcf9 = cf9;
|
||||
pcf2 = cf2;
|
||||
pcf6 = cf6;
|
||||
pcf10 = cf10;
|
||||
|
||||
pcd0 = cd0;
|
||||
pcd1 = cd1;
|
||||
pcd5 = cd5;
|
||||
pcd9 = cd9;
|
||||
pcd2 = cd2;
|
||||
pcd6 = cd6;
|
||||
pcd10 = cd10;
|
||||
}
|
Loading…
Add table
Reference in a new issue