return (off % 4) == 0;
}
-/* Return true if operand is a (MEM (PLUS (REG) (offset))) where offset
- is not divisible by four. */
-
-int
-invalid_gpr_mem (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- rtx addr;
- long off;
-
- if (GET_CODE (op) != MEM)
- return 0;
-
- addr = XEXP (op, 0);
- if (GET_CODE (addr) != PLUS
- || GET_CODE (XEXP (addr, 0)) != REG
- || GET_CODE (XEXP (addr, 1)) != CONST_INT)
- return 0;
-
- off = INTVAL (XEXP (addr, 1));
- return (off & 3) != 0;
-}
-
-/* Return true if operand is a hard register that can be used as a base
- register. */
-
-int
-base_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- unsigned int regno;
-
- if (!REG_P (op))
- return 0;
-
- regno = REGNO (op);
- return regno != 0 && regno <= 31;
-}
-
/* Return true if either operand is a general purpose register. */
bool
case DFmode:
case DImode:
- /* Both DFmode and DImode may end up in gprs. If gprs are 32-bit,
- then we need to load/store at both offset and offset+4. */
- if (!TARGET_POWERPC64)
+ if (mode == DFmode || !TARGET_POWERPC64)
extra = 4;
+ else if (offset & 3)
+ return false;
break;
case TFmode:
case TImode:
- if (!TARGET_POWERPC64)
+ if (mode == TFmode || !TARGET_POWERPC64)
extra = 12;
+ else if (offset & 3)
+ return false;
else
extra = 8;
break;
return x;
}
#endif
+
+ /* Force ld/std non-word aligned offset into base register by wrapping
+ in offset 0. */
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && REGNO (XEXP (x, 0)) < 32
+ && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && (INTVAL (XEXP (x, 1)) & 3) != 0
+ && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
+ && TARGET_POWERPC64)
+ {
+ x = gen_rtx_PLUS (GET_MODE (x), x, GEN_INT (0));
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ *win = 1;
+ return x;
+ }
+
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
*win = 1;
return x;
}
+
#if TARGET_MACHO
if (GET_CODE (x) == SYMBOL_REF
&& DEFAULT_ABI == ABI_DARWIN
return x;
}
#endif
+
if (TARGET_TOC
&& constant_pool_expr_p (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
\f
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
- NO_REGS is returned. INP is nonzero if we are loading the reg, zero
- for storing. */
+ NO_REGS is returned. */
enum reg_class
secondary_reload_class (enum reg_class class,
enum machine_mode mode,
- rtx in,
- int inp)
+ rtx in)
{
int regno;
return BASE_REGS;
}
- /* A 64-bit gpr load or store using an offset that isn't a multiple of
- four needs a secondary reload. */
- if (TARGET_POWERPC64
- && GET_MODE_UNIT_SIZE (mode) >= 8
- && (!inp || class != BASE_REGS)
- && invalid_gpr_mem (in, mode))
- return BASE_REGS;
-
if (GET_CODE (in) == REG)
{
regno = REGNO (in);
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdf_hardfloat64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,b,!r,f,f,m,!cl,!r,!h,!r,!r,!r")
- (match_operand:DF 1 "input_operand" "r,Y,m,r,f,m,f,r,h,0,G,H,F"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,!cl,!r,!h,!r,!r,!r")
+ (match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"@
std%U0%X0 %1,%0
ld%U1%X1 %0,%1
- #
mr %0,%1
fmr %0,%1
lfd%U1%X1 %0,%1
#
#
#"
- [(set_attr "type" "store,load,load,*,fp,fpload,fpstore,mtjmpr,*,*,*,*,*")
- (set_attr "length" "4,4,8,4,4,4,4,4,4,4,8,12,16")])
-
-(define_split
- [(set (match_operand:DF 0 "base_reg_operand" "")
- (match_operand:DF 1 "invalid_gpr_mem" ""))]
- "TARGET_POWERPC64 && no_new_pseudos"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (match_dup 4))]
- "
-{
- operands[2] = gen_rtx_REG (Pmode, REGNO (operands[0]));
- operands[3] = XEXP (operands[1], 0);
- operands[4] = replace_equiv_address (operands[1], operands[2]);
-}")
-
-(define_expand "reload_outdf"
- [(parallel [(match_operand:DF 0 "invalid_gpr_mem" "")
- (match_operand:DF 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "=&b")])]
- "TARGET_POWERPC64"
-{
- if (!TARGET_64BIT)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[2]));
- emit_move_insn (operands[2], XEXP (operands[0], 0));
- operands[0] = replace_equiv_address (operands[0], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "reload_indf"
- [(parallel [(match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "invalid_gpr_mem" "")
- (match_operand:DI 2 "register_operand" "=&b")])]
- "TARGET_POWERPC64"
-{
- if (!TARGET_64BIT)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[2]));
- emit_move_insn (operands[2], XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
+ [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,*,*,*,*,*")
+ (set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat64"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
}")
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,b,r,r,r,r,r,??f,f,m,r,*h,*h")
- (match_operand:DI 1 "input_operand" "r,Y,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,r,??f,f,m,r,*h,*h")
+ (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,R,f,m,f,*h,r,0"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
"@
std%U0%X0 %1,%0
ld%U1%X1 %0,%1
- #
mr %0,%1
li %0,%1
lis %0,%v1
mf%1 %0
mt%0 %1
{cror 0,0,0|nop}"
- [(set_attr "type" "store,load,load,*,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*")
- (set_attr "length" "4,4,8,4,4,4,20,4,4,4,4,4,4,4")])
-
-(define_split
- [(set (match_operand:DI 0 "base_reg_operand" "")
- (match_operand:DI 1 "invalid_gpr_mem" ""))]
- "TARGET_POWERPC64 && no_new_pseudos"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (match_dup 4))]
- "
-{
- operands[2] = operands[0];
- if (!TARGET_64BIT)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]));
- operands[3] = XEXP (operands[1], 0);
- operands[4] = replace_equiv_address (operands[1], operands[2]);
-}")
-
-(define_expand "reload_outdi"
- [(parallel [(match_operand:DI 0 "invalid_gpr_mem" "")
- (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "=&b")])]
- "TARGET_POWERPC64"
-{
- if (!TARGET_64BIT)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[2]));
- emit_move_insn (operands[2], XEXP (operands[0], 0));
- operands[0] = replace_equiv_address (operands[0], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "reload_indi"
- [(parallel [(match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "invalid_gpr_mem" "")
- (match_operand:DI 2 "register_operand" "=&b")])]
- "TARGET_POWERPC64"
-{
- if (!TARGET_64BIT)
- operands[2] = gen_rtx_REG (SImode, REGNO (operands[2]));
- emit_move_insn (operands[2], XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
+ [(set_attr "type" "store,load,*,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*")
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
;; immediate value valid for a single instruction hiding in a const_double
(define_insn ""