(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
"
{
- int low = INTVAL (operands[2]) & 0xffff;
- int high = (unsigned) INTVAL (operands[2]) >> 16;
+ HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
+ HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
if (low & 0x8000)
- high++, low |= 0xffff0000;
+ high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
- operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16);
- operands[4] = gen_rtx (CONST_INT, VOIDmode, low);
+ operands[3] = GEN_INT (high);
+ operands[4] = GEN_INT (low);
}")
(define_insn "one_cmplsi2"
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"
{
- int low = INTVAL (operands[2]) & 0xffff;
- int high = (unsigned) INTVAL (operands[2]) >> 16;
+ HOST_WIDE_INT low = INTVAL (operands[2]) & 0xffff;
+ HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
if (low & 0x8000)
- high++, low |= 0xffff0000;
+ high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
- operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16);
- operands[4] = gen_rtx (CONST_INT, VOIDmode, low);
+ operands[3] = GEN_INT (high);
+ operands[4] = GEN_INT (low);
}")
(define_insn "one_cmpldi2"
"
{
operands[3] = gen_rtx (CONST_INT, VOIDmode,
- INTVAL (operands[2]) & 0xffff0000);
+ INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
}")
;; multiple insns.
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
+ (match_operand:DI 1 "any_operand" ""))]
""
"
{
- if (GET_CODE (operands[0]) == MEM)
+ if (! TARGET_64BIT && ! general_operand (operands[1], DImode))
+ FAIL;
+
+ if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DImode, operands[1]);
if (GET_CODE (operands[1]) == CONST_DOUBLE
low = CONST_DOUBLE_LOW (operands[1]);
high = CONST_DOUBLE_HIGH (operands[1]);
}
- else
+ else if (HOST_BITS_PER_WIDE_INT <= 32)
{
low = INTVAL (operands[1]);
high = (low < 0) ? ~0 : 0;
}
+ else
+ {
+ low = INTVAL (operands[1]) & 0xffffffff;
+ high = (unsigned long long) INTVAL (operands[1]) >> 32;
+ }
- emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], WORDS_BIG_ENDIAN),
- GEN_INT (low));
+ if (! TARGET_POWERPC64)
+ {
+ emit_move_insn (gen_rtx (SUBREG, SImode, operands[0],
+ WORDS_BIG_ENDIAN), GEN_INT (low));
- emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], !WORDS_BIG_ENDIAN),
- GEN_INT (high));
- DONE;
+ emit_move_insn (gen_rtx (SUBREG, SImode, operands[0],
+ ! WORDS_BIG_ENDIAN), GEN_INT (high));
+ DONE;
+ }
+ else
+ {
+ if (high + 0x8000 >= 0x10000)
+ {
+ emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1),
+ GEN_INT (high));
+ emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT(32)));
+ if (low)
+ {
+ HOST_WIDE_INT low_low = low & 0xffff;
+ HOST_WIDE_INT low_high = low & (~ (HOST_WIDE_INT) 0xffff);
+ if (low_high)
+ emit_insn (gen_iordi3 (operands[0], operands[0],
+ GEN_INT (low_high)));
+ if (low_low)
+ emit_insn (gen_iordi3 (operands[0], operands[0],
+ GEN_INT (low_low)));
+ }
+ }
+ else if (low)
+ emit_move_insn (gen_rtx (SUBREG, SImode, operands[0], 1),
+ GEN_INT (low));
+ DONE;
+ }
}
/* Stores between FPR and any non-FPR registers must go through a
(set_attr "length" "8,8,8,*,*,*")])
(define_insn ""
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,f,f,m,r,*h,*h")
- (match_operand:DI 1 "input_operand" "r,m,r,I,J,R,f,m,f,*h,r,0"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,f,f,m,r,*h,*h")
+ (match_operand:DI 1 "input_operand" "r,m,r,I,J,n,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
li %0,%1
lis %0,%u1
+ #
{cal|la} %0,%1(%*)
fmr %0,%1
lfd%U1%X1 %0,%1
mf%1 %0
mt%0 %1
cror 0,0,0"
- [(set_attr "type" "*,load,*,*,*,*,fp,fpload,*,*,mtjmpr,*")])
+ [(set_attr "type" "*,load,*,*,*,*,*,fp,fpload,*,*,mtjmpr,*")
+ (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
+
+;; Split a load of a large constant into the appropriate five-instruction
+;; sequence. The expansion in movdi tries to perform the minimum number of
+;; steps, but here we have to handle anything in a constant number of insns.
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "const_double_operand" ""))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 0)
+ (match_dup 2))
+ (set (match_dup 0)
+ (ior:DI (match_dup 0)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (ashift:DI (match_dup 0)
+ (const_int 32)))
+ (set (match_dup 0)
+ (ior:DI (match_dup 0)
+ (match_dup 4)))
+ (set (match_dup 0)
+ (ior:DI (match_dup 0)
+ (match_dup 5)))]
+ "
+{
+ HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ low = CONST_DOUBLE_LOW (operands[1]);
+ high = CONST_DOUBLE_HIGH (operands[1]);
+ }
+ else if (HOST_BITS_PER_WIDE_INT <= 32)
+ {
+ low = INTVAL (operands[1]);
+ high = (low < 0) ? ~0 : 0;
+ }
+ else
+ {
+ low = INTVAL (operands[1]) & 0xffffffff;
+ high = (unsigned long long) INTVAL (operands[1]) >> 32;
+ }
+
+ if ((high + 0x8000) < 0x10000
+ && ((low & 0xffff) == 0 || (low & (~ (HOST_WIDE_INT) 0xffff)) == 0))
+ FAIL;
+
+ operands[2] = GEN_INT (high & (~ (HOST_WIDE_INT) 0xffff));
+ operands[3] = GEN_INT (high & 0xffff);
+ operands[4] = GEN_INT (low & (~ (HOST_WIDE_INT) 0xffff));
+ operands[5] = GEN_INT (low & 0xffff);
+}")
(define_insn ""
[(set (match_operand:CC 2 "cc_reg_operand" "=x")
|| INTVAL (operands[0]) > 32768)
{
neg_op0 = gen_reg_rtx (Pmode);
- if (TARGET_POWERPC64)
- emit_insn (gen_negdi2 (neg_op0, operands[0]));
- else
+ if (TARGET_32BIT)
emit_insn (gen_negsi2 (neg_op0, operands[0]));
+ else
+ emit_insn (gen_negdi2 (neg_op0, operands[0]));
}
else
neg_op0 = GEN_INT (- INTVAL (operands[0]));
- if (TARGET_POWERPC64)
- emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
- else
+ if (TARGET_32BIT)
emit_insn (gen_movsi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
+ else
+ emit_insn (gen_movdi_update (stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
DONE;
}")
;; Table jump for switch statements:
(define_expand "tablejump"
+ [(use (match_operand 0 "" ""))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "
+{
+ if (TARGET_32BIT)
+ emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_expand "tablejumpsi"
[(set (match_dup 3)
(plus:SI (match_operand:SI 0 "" "")
(match_dup 2)))
operands[3] = gen_reg_rtx (SImode);
}")
+(define_expand "tablejumpdi"
+ [(set (match_dup 3)
+ (plus:DI (match_operand:DI 0 "" "")
+ (match_dup 2)))
+ (parallel [(set (pc) (match_dup 3))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+ "
+{ operands[0] = force_reg (DImode, operands[0]);
+ operands[2] = force_reg (DImode, gen_rtx (LABEL_REF, VOIDmode, operands[1]));
+ operands[3] = gen_reg_rtx (DImode);
+}")
+
(define_insn ""
[(set (pc)
(match_operand:SI 0 "register_operand" "c,l"))