Add EXTRA_OFFSET to the address we return. */
rtx
-get_unaligned_address (rtx ref, int extra_offset)
+get_unaligned_address (rtx ref)
{
rtx base;
HOST_WIDE_INT offset = 0;
if (GET_CODE (base) == PLUS)
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
- return plus_constant (base, offset + extra_offset);
+ return plus_constant (base, offset);
+}
+
+/* Compute a value X, such that X & 7 == (ADDR + OFS) & 7.
+ X is always returned in a register. */
+
+rtx
+get_unaligned_offset (rtx addr, HOST_WIDE_INT ofs)
+{
+ if (GET_CODE (addr) == PLUS)
+ {
+ ofs += INTVAL (XEXP (addr, 1));
+ addr = XEXP (addr, 0);
+ }
+
+ return expand_simple_binop (Pmode, PLUS, addr, GEN_INT (ofs & 7),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
}
/* On the Alpha, all (non-symbolic) constants except zero go into
seq = ((mode == QImode
? gen_unaligned_loadqi
: gen_unaligned_loadhi)
- (subtarget, get_unaligned_address (operands[1], 0),
+ (subtarget, get_unaligned_address (operands[1]),
temp1, temp2));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
rtx seq = ((mode == QImode
? gen_unaligned_storeqi
: gen_unaligned_storehi)
- (get_unaligned_address (operands[0], 0),
+ (get_unaligned_address (operands[0]),
operands[1], temp1, temp2, temp3));
alpha_set_memflags (seq, operands[0]);
if (unaligned_memory_operand (operands[1], QImode))
{
- rtx seq
- = gen_unaligned_extendqidi (operands[0],
- get_unaligned_address (operands[1], 1));
-
+ rtx seq = gen_unaligned_extendqidi (operands[0], XEXP (operands[1], 0));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
DONE;
if (unaligned_memory_operand (operands[1], HImode))
{
- rtx seq
- = gen_unaligned_extendhidi (operands[0],
- get_unaligned_address (operands[1], 2));
+ rtx seq = gen_unaligned_extendhidi (operands[0], XEXP (operands[1], 0));
alpha_set_memflags (seq, operands[1]);
emit_insn (seq);
;; as a pattern saves one instruction. The code is similar to that for
;; the unaligned loads (see below).
;;
-;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result.
+;; Operand 1 is the address, operand 0 is the result.
(define_expand "unaligned_extendqidi"
[(use (match_operand:QI 0 "register_operand" ""))
(use (match_operand:DI 1 "address_operand" ""))]
""
{
+ operands[0] = gen_lowpart (DImode, operands[0]);
if (WORDS_BIG_ENDIAN)
emit_insn (gen_unaligned_extendqidi_be (operands[0], operands[1]));
else
})
(define_expand "unaligned_extendqidi_le"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3)
- (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1))
- (const_int -8))))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
(ashift:DI (match_dup 3)
(minus:DI (const_int 64)
(ashift:DI
(and:DI (match_dup 2) (const_int 7))
(const_int 3)))))
- (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (set (match_operand:DI 0 "register_operand" "")
(ashiftrt:DI (match_dup 4) (const_int 56)))]
"! WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], 1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendqidi_be"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3) (plus:DI (match_dup 2) (const_int -1)))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
- (mem:DI (and:DI (match_dup 3)
- (const_int -8))))
- (set (match_dup 5) (plus:DI (match_dup 2) (const_int -2)))
- (set (match_dup 6)
- (ashift:DI (match_dup 4)
+ (ashift:DI (match_dup 3)
(ashift:DI
(and:DI
- (plus:DI (match_dup 5) (const_int 1))
+ (plus:DI (match_dup 2) (const_int 1))
(const_int 7))
(const_int 3))))
- (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
- (ashiftrt:DI (match_dup 6) (const_int 56)))]
+ (set (match_operand:DI 0 "register_operand" "")
+ (ashiftrt:DI (match_dup 4) (const_int 56)))]
"WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], -1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
- operands[6] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendhidi"
""
{
operands[0] = gen_lowpart (DImode, operands[0]);
- emit_insn ((WORDS_BIG_ENDIAN
- ? gen_unaligned_extendhidi_be
- : gen_unaligned_extendhidi_le) (operands[0], operands[1]));
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_extendhidi_be (operands[0], operands[1]));
+ else
+ emit_insn (gen_unaligned_extendhidi_le (operands[0], operands[1]));
DONE;
})
(define_expand "unaligned_extendhidi_le"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3)
- (mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2))
- (const_int -8))))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
(ashift:DI (match_dup 3)
(minus:DI (const_int 64)
(ashiftrt:DI (match_dup 4) (const_int 48)))]
"! WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], 2);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendhidi_be"
- [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
- (set (match_dup 3) (plus:DI (match_dup 2) (const_int -2)))
+ [(set (match_dup 3)
+ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8))))
(set (match_dup 4)
- (mem:DI (and:DI (match_dup 3)
- (const_int -8))))
- (set (match_dup 5) (plus:DI (match_dup 2) (const_int -3)))
- (set (match_dup 6)
- (ashift:DI (match_dup 4)
+ (ashift:DI (match_dup 3)
(ashift:DI
(and:DI
- (plus:DI (match_dup 5) (const_int 1))
+ (plus:DI (match_dup 2) (const_int 1))
(const_int 7))
(const_int 3))))
(set (match_operand:DI 0 "register_operand" "")
- (ashiftrt:DI (match_dup 6) (const_int 48)))]
+ (ashiftrt:DI (match_dup 4) (const_int 48)))]
"WORDS_BIG_ENDIAN"
{
- operands[2] = gen_reg_rtx (DImode);
+ operands[2] = get_unaligned_offset (operands[1], -1);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
- operands[6] = gen_reg_rtx (DImode);
})
(define_insn "*extxl_const"
else
scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- addr = get_unaligned_address (operands[1], 0);
+ 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]);
else
scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- addr = get_unaligned_address (operands[1], 0);
+ 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]);
}
else
{
- rtx addr = get_unaligned_address (operands[0], 0);
+ 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;
}
else
{
- rtx addr = get_unaligned_address (operands[0], 0);
+ 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;