(UNSPECV_SC 16) ; store-conditional
])
+;; On non-BWX targets, CQImode must be handled the similarly to HImode
+;; when generating reloads.
+(define_mode_macro RELOAD12 [QI HI CQI])
+(define_mode_attr reloadmode [(QI "qi") (HI "hi") (CQI "hi")])
+
+;; Other mode macros
+(define_mode_macro I12MODE [QI HI])
+(define_mode_macro I48MODE [SI DI])
+(define_mode_attr modesuffix [(SI "l") (DI "q")])
+
;; Where necessary, the suffixes _le and _be are used to distinguish between
;; little-endian and big-endian patterns.
;;
DONE;
})
-;; Here are the versions for reload. Note that in the unaligned cases
-;; we know that the operand must not be a pseudo-register because stack
-;; slots are always aligned references.
-
-(define_expand "reload_inqi"
- [(parallel [(match_operand:QI 0 "register_operand" "=r")
- (match_operand:QI 1 "any_memory_operand" "m")
- (match_operand:TI 2 "register_operand" "=&r")])]
- "! TARGET_BWX"
+;; We need to hook into the extra support that we have for HImode
+;; reloads when BWX insns are not available.
+(define_expand "movcqi"
+ [(set (match_operand:CQI 0 "nonimmediate_operand" "")
+ (match_operand:CQI 1 "general_operand" ""))]
+ "!TARGET_BWX"
{
- rtx scratch, seq;
-
- if (aligned_memory_operand (operands[1], QImode))
+ if (GET_CODE (operands[0]) == CONCAT || GET_CODE (operands[1]) == CONCAT)
+ ;
+ else if (!any_memory_operand (operands[0], CQImode))
{
- seq = gen_reload_inqi_help (operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[2])));
+ if (!any_memory_operand (operands[1], CQImode))
+ {
+ emit_move_insn (gen_lowpart (HImode, operands[0]),
+ gen_lowpart (HImode, operands[1]));
+ DONE;
+ }
+ if (aligned_memory_operand (operands[1], CQImode))
+ {
+ bool done;
+ do_aligned1:
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ do_aligned2:
+ operands[0] = gen_lowpart (HImode, operands[0]);
+ done = alpha_expand_mov_nobwx (HImode, operands);
+ gcc_assert (done);
+ DONE;
+ }
}
- else
+ else if (aligned_memory_operand (operands[0], CQImode))
{
- rtx addr;
-
- /* It is possible that one of the registers we got for operands[2]
- might coincide with that of operands[0] (which is why we made
- it TImode). Pick the other one to use as our scratch. */
- if (REGNO (operands[0]) == REGNO (operands[2]))
- scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
- else
- scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
-
- addr = get_unaligned_address (operands[1]);
- operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
- seq = gen_unaligned_loadqi (operands[0], addr, scratch, operands[0]);
- alpha_set_memflags (seq, operands[1]);
+ if (MEM_P (operands[1]))
+ {
+ rtx x = gen_reg_rtx (HImode);
+ emit_move_insn (gen_lowpart (CQImode, x), operands[1]);
+ operands[1] = x;
+ goto do_aligned2;
+ }
+ goto do_aligned1;
}
- emit_insn (seq);
+
+ gcc_assert (!reload_in_progress);
+ emit_move_complex_parts (operands[0], operands[1]);
DONE;
})
-(define_expand "reload_inhi"
- [(parallel [(match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "any_memory_operand" "m")
+;; Here are the versions for reload.
+;;
+;; The aligned input case is recognized early in alpha_secondary_reload
+;; in order to avoid allocating an unnecessary scratch register.
+;;
+;; Note that in the unaligned cases we know that the operand must not be
+;; a pseudo-register because stack slots are always aligned references.
+
+(define_expand "reload_in<mode>"
+ [(parallel [(match_operand:RELOAD12 0 "register_operand" "=r")
+ (match_operand:RELOAD12 1 "any_memory_operand" "m")
(match_operand:TI 2 "register_operand" "=&r")])]
- "! TARGET_BWX"
+ "!TARGET_BWX"
{
- rtx scratch, seq;
+ rtx scratch, seq, addr;
+ unsigned regno = REGNO (operands[2]);
- if (aligned_memory_operand (operands[1], HImode))
- {
- seq = gen_reload_inhi_help (operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[2])));
- }
- else
- {
- rtx addr;
+ /* It is possible that one of the registers we got for operands[2]
+ might coincide with that of operands[0] (which is why we made
+ it TImode). Pick the other one to use as our scratch. */
+ if (regno == REGNO (operands[0]))
+ regno++;
+ scratch = gen_rtx_REG (DImode, regno);
- /* It is possible that one of the registers we got for operands[2]
- might coincide with that of operands[0] (which is why we made
- it TImode). Pick the other one to use as our scratch. */
- if (REGNO (operands[0]) == REGNO (operands[2]))
- scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
- else
- scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
+ addr = get_unaligned_address (operands[1]);
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ seq = gen_unaligned_load<reloadmode> (operands[0], addr,
+ scratch, operands[0]);
+ alpha_set_memflags (seq, operands[1]);
- addr = get_unaligned_address (operands[1]);
- operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
- seq = gen_unaligned_loadhi (operands[0], addr, scratch, operands[0]);
- alpha_set_memflags (seq, operands[1]);
- }
emit_insn (seq);
DONE;
})
-(define_expand "reload_outqi"
- [(parallel [(match_operand:QI 0 "any_memory_operand" "=m")
- (match_operand:QI 1 "register_operand" "r")
+(define_expand "reload_out<mode>"
+ [(parallel [(match_operand:RELOAD12 0 "any_memory_operand" "=m")
+ (match_operand:RELOAD12 1 "register_operand" "r")
(match_operand:TI 2 "register_operand" "=&r")])]
"! TARGET_BWX"
{
- if (aligned_memory_operand (operands[0], QImode))
- {
- emit_insn (gen_reload_outqi_help
- (operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[2])),
- gen_rtx_REG (SImode, REGNO (operands[2]) + 1)));
- }
- else
- {
- rtx addr = get_unaligned_address (operands[0]);
- rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
- rtx scratch3 = scratch1;
- rtx seq;
-
- if (GET_CODE (addr) == REG)
- scratch1 = addr;
+ unsigned regno = REGNO (operands[2]);
- seq = gen_unaligned_storeqi (addr, operands[1], scratch1,
- scratch2, scratch3);
- alpha_set_memflags (seq, operands[0]);
- emit_insn (seq);
+ if (<MODE>mode == CQImode)
+ {
+ operands[0] = gen_lowpart (HImode, operands[0]);
+ operands[1] = gen_lowpart (HImode, operands[1]);
}
- DONE;
-})
-(define_expand "reload_outhi"
- [(parallel [(match_operand:HI 0 "any_memory_operand" "=m")
- (match_operand:HI 1 "register_operand" "r")
- (match_operand:TI 2 "register_operand" "=&r")])]
- "! TARGET_BWX"
-{
- if (aligned_memory_operand (operands[0], HImode))
+ if (aligned_memory_operand (operands[0], <MODE>mode))
{
- emit_insn (gen_reload_outhi_help
+ emit_insn (gen_reload_out<reloadmode>_aligned
(operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[2])),
- gen_rtx_REG (SImode, REGNO (operands[2]) + 1)));
+ gen_rtx_REG (SImode, regno),
+ gen_rtx_REG (SImode, regno + 1)));
}
else
{
rtx addr = get_unaligned_address (operands[0]);
- rtx scratch1 = gen_rtx_REG (DImode, REGNO (operands[2]));
- rtx scratch2 = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
+ rtx scratch1 = gen_rtx_REG (DImode, regno);
+ rtx scratch2 = gen_rtx_REG (DImode, regno + 1);
rtx scratch3 = scratch1;
rtx seq;
if (GET_CODE (addr) == REG)
scratch1 = addr;
- seq = gen_unaligned_storehi (addr, operands[1], scratch1,
- scratch2, scratch3);
+ seq = gen_unaligned_store<reloadmode> (addr, operands[1], scratch1,
+ scratch2, scratch3);
alpha_set_memflags (seq, operands[0]);
emit_insn (seq);
}
;; always get a proper address for a stack slot during reload_foo
;; expansion, so we must delay our address manipulations until after.
-(define_insn_and_split "reload_inqi_help"
- [(set (match_operand:QI 0 "register_operand" "=r")
- (match_operand:QI 1 "memory_operand" "m"))
- (clobber (match_operand:SI 2 "register_operand" "=r"))]
- "! TARGET_BWX && (reload_in_progress || reload_completed)"
+(define_insn_and_split "reload_in<mode>_aligned"
+ [(set (match_operand:I12MODE 0 "register_operand" "=r")
+ (match_operand:I12MODE 1 "memory_operand" "m"))]
+ "!TARGET_BWX && (reload_in_progress || reload_completed)"
"#"
- "! TARGET_BWX && reload_completed"
+ "!TARGET_BWX && reload_completed"
[(const_int 0)]
{
rtx aligned_mem, bitnum;
get_aligned_mem (operands[1], &aligned_mem, &bitnum);
- operands[0] = gen_lowpart (DImode, operands[0]);
- emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
- operands[2]));
- DONE;
-})
-
-(define_insn_and_split "reload_inhi_help"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "memory_operand" "m"))
- (clobber (match_operand:SI 2 "register_operand" "=r"))]
- "! TARGET_BWX && (reload_in_progress || reload_completed)"
- "#"
- "! TARGET_BWX && reload_completed"
- [(const_int 0)]
-{
- rtx aligned_mem, bitnum;
- get_aligned_mem (operands[1], &aligned_mem, &bitnum);
- operands[0] = gen_lowpart (DImode, operands[0]);
- emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
- operands[2]));
- DONE;
-})
-
-(define_insn_and_split "reload_outqi_help"
- [(set (match_operand:QI 0 "memory_operand" "=m")
- (match_operand:QI 1 "register_operand" "r"))
- (clobber (match_operand:SI 2 "register_operand" "=r"))
- (clobber (match_operand:SI 3 "register_operand" "=r"))]
- "! TARGET_BWX && (reload_in_progress || reload_completed)"
- "#"
- "! TARGET_BWX && reload_completed"
- [(const_int 0)]
-{
- rtx aligned_mem, bitnum;
- get_aligned_mem (operands[0], &aligned_mem, &bitnum);
- emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
- operands[2], operands[3]));
+ emit_insn (gen_aligned_load<reloadmode>
+ (gen_lowpart (DImode, operands[0]), aligned_mem, bitnum,
+ gen_rtx_REG (SImode, REGNO (operands[0]))));
DONE;
})
-(define_insn_and_split "reload_outhi_help"
- [(set (match_operand:HI 0 "memory_operand" "=m")
- (match_operand:HI 1 "register_operand" "r"))
+(define_insn_and_split "reload_out<mode>_aligned"
+ [(set (match_operand:I12MODE 0 "memory_operand" "=m")
+ (match_operand:I12MODE 1 "register_operand" "r"))
(clobber (match_operand:SI 2 "register_operand" "=r"))
(clobber (match_operand:SI 3 "register_operand" "=r"))]
- "! TARGET_BWX && (reload_in_progress || reload_completed)"
+ "!TARGET_BWX && (reload_in_progress || reload_completed)"
"#"
- "! TARGET_BWX && reload_completed"
+ "!TARGET_BWX && reload_completed"
[(const_int 0)]
{
rtx aligned_mem, bitnum;