@@ -95,6 +95,7 @@ extern void avr_output_addr_vec (rtx_insn*, rtx);
extern const char *avr_out_sbxx_branch (rtx_insn *insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx, rtx*, int* =NULL, bool =true);
+extern const char* avr_out_minus (rtx*);
extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL);
extern const char* avr_out_addto_sp (rtx*, int*);
extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
@@ -8843,6 +8843,36 @@ lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
}
+/* Output subtraction of integer registers XOP[0] and XOP[2] and return ""
+
+ XOP[0] = XOP[0] - XOP[2]
+
+ where the mode of XOP[0] is in { HI, PSI, SI }, and the mode of
+ XOP[2] is in { QI, HI, PSI }. When the mode of XOP[0] is larger
+ than the mode of XOP[2], then the latter is zero-extended on the fly.
+ The number of instructions will be the mode size of XOP[0]. */
+
+const char *
+avr_out_minus (rtx *xop)
+{
+ int n_bytes0 = GET_MODE_SIZE (GET_MODE (xop[0]));
+ int n_bytes2 = GET_MODE_SIZE (GET_MODE (xop[2]));
+
+ output_asm_insn ("sub %0,%2", xop);
+
+ for (int i = 1; i < n_bytes0; ++i)
+ {
+ rtx op[2];
+ op[0] = all_regs_rtx[i + REGNO (xop[0])];
+ op[1] = (i < n_bytes2) ? all_regs_rtx[i + REGNO (xop[2])] : zero_reg_rtx;
+
+ output_asm_insn ("sbc %0,%1", op);
+ }
+
+ return "";
+}
+
+
/* Output addition of register XOP[0] and compile time constant XOP[2].
INSN is a single_set insn or an insn pattern.
CODE == PLUS: perform addition by using ADD instructions or
@@ -12717,7 +12747,7 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
*total = COSTS_N_INSNS (2);
return true;
}
- // *sub<mode>3_zero_extend1
+ // *sub<HISI:mode>3.zero_extend.<QIPSI:mode>
if (REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
{
@@ -2030,47 +2030,6 @@ (define_insn "*subpsi3"
"sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2"
[(set_attr "length" "3")])
-(define_insn_and_split "*subpsi3_zero_extend.qi_split"
- [(set (match_operand:PSI 0 "register_operand" "=r")
- (minus:PSI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
- ""
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:PSI (match_dup 1)
- (zero_extend:PSI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subpsi3_zero_extend.qi"
- [(set (match_operand:PSI 0 "register_operand" "=r")
- (minus:PSI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))
- (clobber (reg:CC REG_CC))]
- "reload_completed"
- "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__"
- [(set_attr "length" "3")])
-
-(define_insn_and_split "*subpsi3_zero_extend.hi_split"
- [(set (match_operand:PSI 0 "register_operand" "=r")
- (minus:PSI (match_operand:PSI 1 "register_operand" "0")
- (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))]
- ""
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:PSI (match_dup 1)
- (zero_extend:PSI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subpsi3_zero_extend.hi"
- [(set (match_operand:PSI 0 "register_operand" "=r")
- (minus:PSI (match_operand:PSI 1 "register_operand" "0")
- (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))))
- (clobber (reg:CC REG_CC))]
- "reload_completed"
- "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__"
- [(set_attr "length" "3")])
(define_insn_and_split "*subpsi3_sign_extend.hi_split"
[(set (match_operand:PSI 0 "register_operand" "=r")
@@ -2154,26 +2113,6 @@ (define_insn "*sub<mode>3"
}
[(set_attr "adjust_len" "plus")])
-(define_insn_and_split "*subhi3_zero_extend1_split"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (minus:HI (match_operand:HI 1 "register_operand" "0")
- (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
- ""
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:HI (match_dup 1)
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
-
-(define_insn "*subhi3_zero_extend1"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (minus:HI (match_operand:HI 1 "register_operand" "0")
- (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))
- (clobber (reg:CC REG_CC))]
- "reload_completed"
- "sub %A0,%2\;sbc %B0,__zero_reg__"
- [(set_attr "length" "2")])
(define_insn_and_split "*subhi3.sign_extend2_split"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2231,48 +2170,39 @@ (define_insn "*sub<mode>3"
}
[(set_attr "adjust_len" "plus")])
-(define_insn_and_split "*subsi3_zero_extend_split"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))]
- ""
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:SI (match_dup 1)
- (zero_extend:SI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
-(define_insn "*subsi3_zero_extend"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:QI 2 "register_operand" "r"))))
- (clobber (reg:CC REG_CC))]
- "reload_completed"
- "sub %A0,%2\;sbc %B0,__zero_reg__\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
- [(set_attr "length" "4")
- ])
-
-(define_insn_and_split "*subsi3_zero_extend.hi_split"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
- ""
+;; "*subhi3.zero_extend.qi_split"
+;; "*subpsi3.zero_extend.qi_split" "*subpsi3.zero_extend.hi_split"
+;; "*subsi3.zero_extend.qi_split" "*subsi3.zero_extend.hi_split"
+;; "*subsi3.zero_extend.psi_split"
+(define_insn_and_split "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>_split"
+ [(set (match_operand:HISI 0 "register_operand" "=r")
+ (minus:HISI (match_operand:HISI 1 "register_operand" "0")
+ (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r"))))]
+ "GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0)
- (minus:SI (match_dup 1)
- (zero_extend:SI (match_dup 2))))
+ (minus:HISI (match_dup 1)
+ (zero_extend:HISI (match_dup 2))))
(clobber (reg:CC REG_CC))])])
-(define_insn "*subsi3_zero_extend.hi"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))
+;; "*subhi3.zero_extend.qi"
+;; "*subpsi3.zero_extend.qi" "*subpsi3.zero_extend.hi"
+;; "*subsi3.zero_extend.qi" "*subsi3.zero_extend.hi"
+;; "*subsi3.zero_extend.psi"
+(define_insn "*sub<HISI:mode>3.zero_extend.<QIPSI:mode>"
+ [(set (match_operand:HISI 0 "register_operand" "=r")
+ (minus:HISI (match_operand:HISI 1 "register_operand" "0")
+ (zero_extend:HISI (match_operand:QIPSI 2 "register_operand" "r"))))
(clobber (reg:CC REG_CC))]
- "reload_completed"
- "sub %A0,%2\;sbc %B0,%B2\;sbc %C0,__zero_reg__\;sbc %D0,__zero_reg__"
- [(set_attr "length" "4")])
+ "reload_completed
+ && GET_MODE_SIZE (<HISI:MODE>mode) > GET_MODE_SIZE (<QIPSI:MODE>mode)"
+ {
+ return avr_out_minus (operands);
+ }
+ [(set_attr "length" "<HISI:SIZE>")])
+
;******************************************************************************
; mul
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+typedef __UINT8_TYPE__ u8;
+typedef __UINT16_TYPE__ u16;
+typedef __uint24 u24;
+typedef __UINT32_TYPE__ u32;
+
+u32 sub_32_8 (u32 a, u8 b) { return a - b; }
+u32 sub_32_16 (u32 a, u16 b) { return a - b; }
+u32 sub_32_24 (u32 a, u24 b) { return a - b; }
+
+u24 sub_24_8 (u24 a, u8 b) { return a - b; }
+u24 sub_24_16 (u24 a, u16 b) { return a - b; }
+
+u16 sub_16_8 (u16 a, u8 b) { return a - b; }