diff options
author | Jim Wilson <wilson@gcc.gnu.org> | 1996-09-25 15:51:33 -0700 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 1996-09-25 15:51:33 -0700 |
commit | 725de644d609069bb6c4d90f1b843ba0f6bcecce (patch) | |
tree | 73c32c75eb5b7a57085a454ec9d9a9b88bbdb658 /gcc/config/sh/sh.md | |
parent | 103fa5258f4a49d8bb0d2fa810fb1e004b465e71 (diff) | |
download | gcc-725de644d609069bb6c4d90f1b843ba0f6bcecce.zip gcc-725de644d609069bb6c4d90f1b843ba0f6bcecce.tar.gz gcc-725de644d609069bb6c4d90f1b843ba0f6bcecce.tar.bz2 |
(insv): New pattern.
From-SVN: r12847
Diffstat (limited to 'gcc/config/sh/sh.md')
-rw-r--r-- | gcc/config/sh/sh.md | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 729884c..2c100ff 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -2536,6 +2536,54 @@ "fabs %0" [(set_attr "type" "fp")]) +;; Bit field extract patterns. These give better code for packed bitfields, +;; because they allow auto-increment addresses to be generated. + +(define_expand "insv" + [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") + (match_operand:SI 1 "immediate_operand" "") + (match_operand:SI 2 "immediate_operand" "")) + (match_operand:SI 3 "general_operand" ""))] + "! TARGET_LITTLE_ENDIAN" + " +{ + rtx addr_target, orig_address, shift_reg; + HOST_WIDE_INT size; + + /* ??? expmed doesn't care for non-register predicates. */ + if (! memory_operand (operands[0], VOIDmode) + || ! immediate_operand (operands[1], VOIDmode) + || ! immediate_operand (operands[2], VOIDmode) + || ! general_operand (operands[3], VOIDmode)) + FAIL; + /* If this isn't a 16 / 24 / 32 bit field, or if + it doesn't start on a byte boundary, then fail. */ + size = INTVAL (operands[1]); + if (size < 16 || size > 32 || size % 8 != 0 + || (INTVAL (operands[2]) % 8) != 0) + FAIL; + + size /= 8; + orig_address = XEXP (operands[0], 0); + addr_target = gen_reg_rtx (SImode); + shift_reg = gen_reg_rtx (SImode); + emit_insn (gen_movsi (shift_reg, operands[3])); + emit_insn (gen_addsi3 (addr_target, orig_address, GEN_INT (size - 1))); + + operands[0] = change_address (operands[0], QImode, addr_target); + emit_insn (gen_movqi (operands[0], gen_rtx (SUBREG, QImode, shift_reg, 0))); + + while (size -= 1) + { + emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); + emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1))); + emit_insn (gen_movqi (operands[0], + gen_rtx (SUBREG, QImode, shift_reg, 0))); + } + + DONE; +}") + ;; ------------------------------------------------------------------------- ;; Peepholes ;; ------------------------------------------------------------------------- |