;; conditional-move-type condition is needed.
(define_mode_macro MOVECC [SI (DI "TARGET_64BIT") (CC "TARGET_HARD_FLOAT")])
+;; This mode macro allows the QI and HI extension patterns to be defined from
+;; the same template.
+(define_mode_macro SHORT [QI HI])
+
;; This mode macro allows :ANYF to be used wherever a scalar or vector
;; floating-point mode is allowed.
(define_mode_macro ANYF [(SF "TARGET_HARD_FLOAT")
;; 32-bit version and "dsubu" in the 64-bit version.
(define_mode_attr d [(SI "") (DI "d")])
+;; This attribute gives the length suffix for a sign- or zero-extension
+;; instruction.
+(define_mode_attr size [(QI "b") (HI "h")])
+
;; Mode attributes for GPR loads and stores.
(define_mode_attr load [(SI "lw") (DI "ld")])
(define_mode_attr store [(SI "sw") (DI "sd")])
[(set_attr "type" "arith,load")
(set_attr "mode" "DI")])
-;; These patterns originally accepted general_operands, however, slightly
-;; better code is generated by only accepting register_operands, and then
-;; letting combine generate the lh and lb insns.
-
-;; These expanders originally put values in registers first. We split
-;; all non-mem patterns after reload.
-
-(define_expand "extendhidi2"
- [(set (match_operand:DI 0 "register_operand")
- (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand")))]
- "TARGET_64BIT"
+(define_expand "extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
"")
-(define_insn "*extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))]
- "TARGET_64BIT"
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (sign_extend:DI (match_operand:HI 1 "register_operand")))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (ashift:DI (match_dup 1) (const_int 48)))
- (set (match_dup 0)
- (ashiftrt:DI (match_dup 0) (const_int 48)))]
- "operands[1] = gen_lowpart (DImode, operands[1]);")
-
-(define_insn "*extendhidi2_mem"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_64BIT"
- "lh\t%0,%1"
- [(set_attr "type" "load")
- (set_attr "mode" "DI")])
-
-(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "register_operand")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
- ""
+(define_insn_and_split "*extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
+ "!ISA_HAS_SEB_SEH"
+ "@
+ #
+ l<SHORT:size>\t%0,%1"
+ "&& reload_completed && REG_P (operands[1])"
+ [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))]
{
- if (ISA_HAS_SEB_SEH)
- {
- emit_insn (gen_extendhisi2_hw (operands[0],
- force_reg (HImode, operands[1])));
- DONE;
- }
-})
-
-(define_insn "*extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand")
- (sign_extend:SI (match_operand:HI 1 "register_operand")))]
- "reload_completed"
- [(set (match_dup 0)
- (ashift:SI (match_dup 1) (const_int 16)))
- (set (match_dup 0)
- (ashiftrt:SI (match_dup 0) (const_int 16)))]
- "operands[1] = gen_lowpart (SImode, operands[1]);")
-
-(define_insn "extendhisi2_mem"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "lh\t%0,%1"
- [(set_attr "type" "load")
- (set_attr "mode" "SI")])
+ operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode)
+ - GET_MODE_BITSIZE (<SHORT:MODE>mode));
+}
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")
+ (set_attr "length" "8,*")])
-(define_insn "extendhisi2_hw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+(define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
"ISA_HAS_SEB_SEH"
- "seh\t%0,%1"
- [(set_attr "type" "arith")
- (set_attr "mode" "SI")])
-
-(define_expand "extendqihi2"
- [(set (match_operand:HI 0 "register_operand")
- (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
- ""
- "")
-
-(define_insn "*extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (sign_extend:HI (match_operand:QI 1 "register_operand" "d")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:HI 0 "register_operand")
- (sign_extend:HI (match_operand:QI 1 "register_operand")))]
- "reload_completed"
- [(set (match_dup 0)
- (ashift:SI (match_dup 1) (const_int 24)))
- (set (match_dup 0)
- (ashiftrt:SI (match_dup 0) (const_int 24)))]
- "operands[0] = gen_lowpart (SImode, operands[0]);
- operands[1] = gen_lowpart (SImode, operands[1]);")
-
-(define_insn "*extendqihi2_internal_mem"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "lb\t%0,%1"
- [(set_attr "type" "load")
- (set_attr "mode" "SI")])
-
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "register_operand")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
- ""
-{
- if (ISA_HAS_SEB_SEH)
- {
- emit_insn (gen_extendqisi2_hw (operands[0],
- force_reg (QImode, operands[1])));
- DONE;
- }
-})
+ "@
+ se<SHORT:size>\t%0,%1
+ l<SHORT:size>\t%0,%1"
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")])
-(define_insn "*extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]
+;; This pattern generates the same code as extendqisi2; split it into
+;; that form after reload.
+(define_insn_and_split "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand")
- (sign_extend:SI (match_operand:QI 1 "register_operand")))]
+ "#"
"reload_completed"
- [(set (match_dup 0)
- (ashift:SI (match_dup 1) (const_int 24)))
- (set (match_dup 0)
- (ashiftrt:SI (match_dup 0) (const_int 24)))]
- "operands[1] = gen_lowpart (SImode, operands[1]);")
-
-(define_insn "*extendqisi2_mem"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "lb\t%0,%1"
- [(set_attr "type" "load")
- (set_attr "mode" "SI")])
-
-(define_insn "extendqisi2_hw"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
- "ISA_HAS_SEB_SEH"
- "seb\t%0,%1"
- [(set_attr "type" "arith")
- (set_attr "mode" "SI")])
-
-(define_expand "extendqidi2"
- [(set (match_operand:DI 0 "register_operand")
- (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand")))]
- "TARGET_64BIT"
- "")
-
-(define_insn "*extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))]
- "TARGET_64BIT"
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (sign_extend:DI (match_operand:QI 1 "register_operand")))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (ashift:DI (match_dup 1) (const_int 56)))
- (set (match_dup 0)
- (ashiftrt:DI (match_dup 0) (const_int 56)))]
- "operands[1] = gen_lowpart (DImode, operands[1]);")
-
-(define_insn "*extendqidi2_mem"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_64BIT"
- "lb\t%0,%1"
- [(set_attr "type" "load")
- (set_attr "mode" "DI")])
+ [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
+ { operands[0] = gen_lowpart (SImode, operands[0]); }
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "8,*")])
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")