(define_insn "adddi3"
[(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
(plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
- (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+ (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
(clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
""
"*
}
else
{
- /* TODO : this should work also for CONST operands[2] */
if (GET_CODE (operands[2]) == REG)
operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[1] = operands[2];
+ operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ }
else
operands[1] = adj_offsettable_operand (operands[2], 4);
+ /* TODO : for consts, optimize move and add */
return \"move%.l %2,%3\;add%.l %1,%R0\;addx%.l %3,%0\";
}
}
(define_insn "subdi3"
[(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
(minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
- (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+ (match_operand:DI 2 "general_operand" "<,d,no>,d,a")))
(clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
""
"*
}
else
{
- /* TODO : this should work also for CONST operands[2] */
if (GET_CODE (operands[2]) == REG)
operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ else if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ operands[2] = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ operands[1] = operands[2];
+ operands[2] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ }
else
operands[1] = adj_offsettable_operand (operands[2], 4);
+ /* TODO : for consts, optimize move and sub */
return \"move%.l %2,%3\;sub%.l %1,%R0\;subx%.l %3,%0\";
}
}
"*
{
#ifdef MOTOROLA
- output_asm_insn(\"ext%.l %0\;divs%.w %2,%0\", operands);
+ output_asm_insn (\"ext%.l %0\;divs%.w %2,%0\", operands);
#else
- output_asm_insn(\"extl %0\;divs %2,%0\", operands);
+ output_asm_insn (\"extl %0\;divs %2,%0\", operands);
#endif
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
{
"*
{
#ifdef MOTOROLA
- output_asm_insn(\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
+ output_asm_insn (\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands);
#else
- output_asm_insn(\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
+ output_asm_insn (\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands);
#endif
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
{
\f
;; logical-and instructions
+;; "anddi3" is mainly here to help combine().
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "general_operand" "=o,d")
+ (and:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "dn,don")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ output_asm_insn (\"clr%.l %0\", operands);
+ break;
+ case -1 :
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_andsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ output_asm_insn (\"clr%.l %0\", operands);
+ break;
+ case -1 :
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_andsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"and%.l %2,%0\;and%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"and%.l %2,%0\;and%.l %1,%R0\";
+ }
+ return \"and%.l %2,%0\;and%.l %R2,%R0\";
+}")
+
;; Prevent AND from being made with sp. This doesn't exist in the machine
;; and reload will cause inefficient code. Since sp is a FIXED_REG, we
;; can't allocate pseudos into it.
"!TARGET_5200"
"*
{
- int logval;
- if (GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
- && (DATA_REG_P (operands[0])
- || offsettable_memref_p (operands[0])))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[0] = adj_offsettable_operand (operands[0], 2);
- operands[2] = gen_rtx (CONST_INT, VOIDmode,
- INTVAL (operands[2]) & 0xffff);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
- if (operands[2] == const0_rtx)
- return \"clr%.w %0\";
- return \"and%.w %2,%0\";
- }
- if (GET_CODE (operands[2]) == CONST_INT
- && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
- && (DATA_REG_P (operands[0])
- || offsettable_memref_p (operands[0])))
- {
- if (DATA_REG_P (operands[0]))
- {
- operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
- }
- else
- {
- operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
- operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
- }
- /* This does not set condition codes in a standard way. */
- CC_STATUS_INIT;
- return \"bclr %1,%0\";
- }
- return \"and%.l %2,%0\";
+ return output_andsi3 (operands);
}")
(define_insn "andsi3_5200"
\f
;; inclusive-or instructions
+;; "iordi3" is mainly here to help combine().
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "general_operand" "=o,d")
+ (ior:DI (match_operand:DI 1 "general_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "dn,don")))]
+ "!TARGET_5200"
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ break;
+ case -1 :
+ /* FIXME : a scratch register would be welcome here if operand[0]
+ is not a register */
+ output_asm_insn (\"move%.l %#-1,%0\", operands);
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_iorsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ break;
+ case -1 :
+ /* FIXME : a scratch register would be welcome here if operand[0]
+ is not a register */
+ output_asm_insn (\"move%.l %#-1,%R0\", operands);
+ break;
+ default :
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_iorsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"or%.l %2,%0\;or%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"or%.l %2,%0\;or%.l %1,%R0\";
+ }
+ return \"or%.l %2,%0\;or%.l %R2,%R0\";
+}")
+
(define_expand "iorsi3"
[(set (match_operand:SI 0 "general_operand" "")
(ior:SI (match_operand:SI 1 "general_operand" "")
[(set (match_operand:SI 0 "general_operand" "=m,d")
(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_operand" "dKs,dmMs")))]
- "!TARGET_5200"
+ ""
"*
{
- register int logval;
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >> 16 == 0
- && (DATA_REG_P (operands[0])
- || offsettable_memref_p (operands[0])))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[0] = adj_offsettable_operand (operands[0], 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
- return \"or%.w %2,%0\";
- }
- if (GET_CODE (operands[2]) == CONST_INT
- && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
- && (DATA_REG_P (operands[0])
- || offsettable_memref_p (operands[0])))
- {
- if (DATA_REG_P (operands[0]))
- {
- operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
- }
- else
- {
- operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
- operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
- }
- CC_STATUS_INIT;
- return \"bset %1,%0\";
- }
- return \"or%.l %2,%0\";
+ return output_iorsi3 (operands);
}")
(define_insn "iorsi3_5200"
\f
;; xor instructions
+;; "xordi3" is mainly here to help combine().
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "general_operand" "=od")
+ (xor:DI (match_operand:DI 1 "general_operand" "%0")
+ (match_operand:DI 2 "general_operand" "dn")))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ /* We can get CONST_DOUBLE, but also const1_rtx etc. */
+ if (GET_CODE (operands[2]) == CONST_DOUBLE
+ || GET_CODE (operands[2]) == CONST_INT)
+ {
+ rtx hi, lo;
+
+ if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ hi = GEN_INT (CONST_DOUBLE_HIGH (operands[2]));
+ lo = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+ }
+ else
+ {
+ lo = operands[2];
+ hi = INTVAL (lo) < 0 ? constm1_rtx : const0_rtx;
+ }
+ switch (INTVAL (hi))
+ {
+ case 0 :
+ break;
+ case -1 :
+ output_asm_insn (\"not%.l %0\", operands);
+ break;
+ default :
+ /* FIXME : a scratch register would be welcome here if
+ -128 <= INTVAL (hi) < -1 */
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = hi;
+ output_asm_insn (output_xorsi3 (xoperands), xoperands);
+ }
+ }
+ if (GET_CODE (operands[0]) == REG)
+ operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else
+ operands[0] = adj_offsettable_operand (operands[0], 4);
+ switch (INTVAL (lo))
+ {
+ case 0 :
+ break;
+ case -1 :
+ output_asm_insn (\"not%.l %0\", operands);
+ break;
+ default :
+ /* FIXME : a scratch register would be welcome here if
+ -128 <= INTVAL (lo) < -1 */
+ operands[2] = lo;
+ /* FIXME : this should be merged with xorsi3 */
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = operands[0];
+ xoperands[2] = lo;
+ output_asm_insn (output_xorsi3 (xoperands), xoperands);
+ }
+ }
+ return \"\";
+ }
+ if (GET_CODE (operands[0]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[0], 4);
+ return \"eor%.l %2,%0\;eor%.l %R2,%1\";
+ }
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[1] = adj_offsettable_operand (operands[2], 4);
+ return \"eor%.l %2,%0\;eor%.l %1,%R0\";
+ }
+ return \"eor%.l %2,%0\;eor%.l %R2,%R0\";
+}")
+
(define_expand "xorsi3"
[(set (match_operand:SI 0 "general_operand" "")
(xor:SI (match_operand:SI 1 "general_operand" "")
"!TARGET_5200"
"*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >> 16 == 0
- && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
- {
- if (! DATA_REG_P (operands[0]))
- operands[0] = adj_offsettable_operand (operands[0], 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
- return \"eor%.w %2,%0\";
- }
- return \"eor%.l %2,%0\";
+ return output_xorsi3 (operands);
}")
(define_insn "xorsi3_5200"
\f
;; one complement instructions
-;; "one_cmpldi2" is only here to help combine().
+;; "one_cmpldi2" is mainly here to help combine().
(define_insn "one_cmpldi2"
[(set (match_operand:DI 0 "general_operand" "=dm")
(not:DI (match_operand:DI 1 "general_operand" "0")))]