static void rs6000_parse_alignment_option (void);
static void rs6000_parse_tls_size_option (void);
static void rs6000_parse_yes_no_option (const char *, const char *, int *);
+static void rs6000_parse_float_gprs_option (void);
static int first_altivec_reg_to_save (void);
static unsigned int compute_vrsave_mask (void);
static void compute_save_world_info(rs6000_stack_t *info_ptr);
{"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ /* 8548 has a dummy entry for now. */
+ {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
{"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"970", PROCESSOR_POWER4,
POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
/* Handle -malign-XXXXX option. */
rs6000_parse_alignment_option ();
+ rs6000_parse_float_gprs_option ();
+
/* Handle generic -mFOO=YES/NO options. */
rs6000_parse_yes_no_option ("vrsave", rs6000_altivec_vrsave_string,
&rs6000_altivec_vrsave);
rs6000_parse_yes_no_option ("isel", rs6000_isel_string,
&rs6000_isel);
rs6000_parse_yes_no_option ("spe", rs6000_spe_string, &rs6000_spe);
- rs6000_parse_yes_no_option ("float-gprs", rs6000_float_gprs_string,
- &rs6000_float_gprs);
/* Handle -mtls-size option. */
rs6000_parse_tls_size_option ();
#ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
SUBSUBTARGET_OVERRIDE_OPTIONS;
#endif
+#ifdef SUB3TARGET_OVERRIDE_OPTIONS
+ SUB3TARGET_OVERRIDE_OPTIONS;
+#endif
if (TARGET_E500)
{
error ("unknown ABI specified: '%s'", rs6000_abi_string);
}
+/* Handle -mfloat-gprs= options. */
+static void
+rs6000_parse_float_gprs_option (void)
+{
+ if (rs6000_float_gprs_string == 0)
+ return;
+ else if (! strcmp (rs6000_float_gprs_string, "yes")
+ || ! strcmp (rs6000_float_gprs_string, "single"))
+ rs6000_float_gprs = 1;
+ else if (! strcmp (rs6000_float_gprs_string, "double"))
+ rs6000_float_gprs = 2;
+ else if (! strcmp (rs6000_float_gprs_string, "no"))
+ rs6000_float_gprs = 0;
+ else
+ error ("invalid option for -mfloat-gprs");
+}
+
/* Handle -malign-XXXXXX options. */
static void
rs6000_parse_alignment_option (void)
return 0;
/* Consider all constants with -msoft-float to be easy. */
- if ((TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
&& mode != DImode)
return 1;
long k[2];
REAL_VALUE_TYPE rv;
+ if (TARGET_E500_DOUBLE)
+ return 0;
+
REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
return SPE_CONST_OFFSET_OK (offset);
case DFmode:
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
case DImode:
if (mode == DFmode || !TARGET_POWERPC64)
extra = 4;
&& GET_MODE_NUNITS (mode) == 1
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& mode != TImode)
{
reg = force_reg (Pmode, x);
return reg;
}
- else if (SPE_VECTOR_MODE (mode))
+ else if (SPE_VECTOR_MODE (mode)
+ || (TARGET_E500_DOUBLE && mode == DFmode))
{
/* We accept [reg + reg] and [reg + OFFSET]. */
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
- && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
+ && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+ || (mode != DFmode || TARGET_E500_DOUBLE))
&& mode != DImode
&& mode != TImode)
{
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& !SPE_VECTOR_MODE (mode)
+ && !(TARGET_E500_DOUBLE && mode == DFmode)
&& !ALTIVEC_VECTOR_MODE (mode))
{
HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
&& !ALTIVEC_VECTOR_MODE (mode)
&& !SPE_VECTOR_MODE (mode)
+ && !(TARGET_E500_DOUBLE && mode == DFmode)
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
&& mode != TFmode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
if (FP_REGNO_P (regno))
return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+ if (TARGET_E500_DOUBLE && mode == DFmode)
+ return 1;
+
if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
&& rs6000_compare_fp_p)
{
rtx cmp, or1, or2, or_result, compare_result2;
+ enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
+
+ if (op_mode == VOIDmode)
+ op_mode = GET_MODE (rs6000_compare_op1);
/* Note: The E500 comparison instructions set the GT bit (x +
1), on success. This explains the mess. */
switch (code)
{
case EQ: case UNEQ: case NE: case LTGT:
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
- cmp = flag_finite_math_only
- ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
- cmp = flag_finite_math_only
- ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
break;
- default:
- abort ();
+ default:
+ abort ();
}
/* Synthesize LE and GE from LT/GT || EQ. */
compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
+ if (op_mode == SFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else if (op_mode == DFmode)
+ cmp = flag_finite_math_only
+ ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ else abort ();
emit_insn (cmp);
or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
&& !SPE_CONST_OFFSET_OK (offset)))
int_rtx = GEN_INT (offset);
- if (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode))
{
offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
emit_move_insn (offset_rtx, int_rtx);
{
unsigned regno;
- if (!TARGET_SPE || !SPE_VECTOR_MODE (GET_MODE (reg)))
+ if (TARGET_SPE
+ && (SPE_VECTOR_MODE (GET_MODE (reg))
+ || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
+ ;
+ else
return NULL_RTX;
regno = REGNO (reg);
(define_constants
[(SPE_ACC_REGNO 111)
- (SPEFSCR_REGNO 112)])
+ (SPEFSCR_REGNO 112)
+
+ (CMPDFEQ_GPR 1006)
+ (TSTDFEQ_GPR 1007)
+ (CMPDFGT_GPR 1008)
+ (TSTDFGT_GPR 1009)
+ (CMPDFLT_GPR 1010)
+ (TSTDFLT_GPR 1011)
+ ])
(define_insn "*negsf2_gpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststlt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
+
+;; Same thing, but for double-precision.
+
+(define_insn "cmpdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpeq %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtsteq %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpgt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstgt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmplt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstlt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])