This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
insv, extv, extzv changes
- To: egcs-patches at cygnus dot com
- Subject: insv, extv, extzv changes
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Tue, 15 Sep 1998 23:47:15 -0600
- Reply-To: law at cygnus dot com
FYI, I recently checked in this patch:
* combine.c (make_extraction): If no mode is specified for
an operand of insv, extv, or extzv, default it to word_mode.
(simplify_comparison): Similarly.
* expmed.c (store_bit_field): Similarly.
(extract_bit_field): Similarly.
* function.c (fixup_var_regs_1): Similarly.
* recog.c (validate_replace_rtx_1): Similarly.
* mips.md (extv, extzv, insv expanders): Default modes for most
operands. Handle TARGET_64BIT.
(movdi_uld, movdi_usd): New patterns.
* combine.c (make_extraction): If no mode is specified for
an operand of insv, extv, or extzv, default it to word_mode.
(simplify_comparison): Similarly.
* expmed.c (store_bit_field): Similarly.
(extract_bit_field): Similarly.
* function.c (fixup_var_regs_1): Similarly.
* recog.c (validate_replace_rtx_1): Similarly.
* mips.md (extv, extzv, insv expanders): Default modes for most
operands. Handle TARGET_64BIT.
(movdi_uld, movdi_usd): New patterns.
Index: combine.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/combine.c,v
retrieving revision 1.184
diff -c -3 -p -r1.184 combine.c
*** combine.c 1998/08/19 22:21:35 1.184
--- combine.c 1998/09/16 05:13:14
*************** make_extraction (mode, inner, pos, pos_r
*** 5723,5749 ****
#ifdef HAVE_insv
if (in_dest)
{
! wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
! pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2];
! extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3];
}
#endif
#ifdef HAVE_extzv
if (! in_dest && unsignedp)
{
! wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
! pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3];
! extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0];
}
#endif
#ifdef HAVE_extv
if (! in_dest && ! unsignedp)
{
! wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
! pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3];
! extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0];
}
#endif
--- 5723,5767 ----
#ifdef HAVE_insv
if (in_dest)
{
! wanted_inner_reg_mode
! = (insn_operand_mode[(int) CODE_FOR_insv][0] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_insv][0]);
! pos_mode = (insn_operand_mode[(int) CODE_FOR_insv][2] == VOIDmode
! ? word_mode : insn_operand_mode[(int) CODE_FOR_insv][2]);
! extraction_mode = (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_insv][3]);
}
#endif
#ifdef HAVE_extzv
if (! in_dest && unsignedp)
{
! wanted_inner_reg_mode
! = (insn_operand_mode[(int) CODE_FOR_extzv][1] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_extzv][1]);
! pos_mode = (insn_operand_mode[(int) CODE_FOR_extzv][3] == VOIDmode
! ? word_mode : insn_operand_mode[(int) CODE_FOR_extzv][3]);
! extraction_mode = (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_extzv][0]);
}
#endif
#ifdef HAVE_extv
if (! in_dest && ! unsignedp)
{
! wanted_inner_reg_mode
! = (insn_operand_mode[(int) CODE_FOR_extv][1] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_extv][1]);
! pos_mode = (insn_operand_mode[(int) CODE_FOR_extv][3] == VOIDmode
! ? word_mode : insn_operand_mode[(int) CODE_FOR_extv][3]);
! extraction_mode = (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode
! ? word_mode
! : insn_operand_mode[(int) CODE_FOR_extv][0]);
}
#endif
*************** simplify_comparison (code, pop0, pop1)
*** 9880,9891 ****
&& (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
{
if (BITS_BIG_ENDIAN)
#ifdef HAVE_extzv
! i = (GET_MODE_BITSIZE
! (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i);
#else
! i = BITS_PER_WORD - 1 - i;
#endif
op0 = XEXP (op0, 2);
op1 = GEN_INT (i);
--- 9898,9913 ----
&& (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
{
if (BITS_BIG_ENDIAN)
+ {
#ifdef HAVE_extzv
! mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
! if (mode == VOIDmode)
! mode = word_mode;
! i = (GET_MODE_BITSIZE (mode) - 1 - i);
#else
! i = BITS_PER_WORD - 1 - i;
#endif
+ }
op0 = XEXP (op0, 2);
op1 = GEN_INT (i);
Index: expmed.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/expmed.c,v
retrieving revision 1.120
diff -c -3 -p -r1.120 expmed.c
*** expmed.c 1998/08/19 22:21:59 1.120
--- expmed.c 1998/09/16 05:13:20
*************** negate_rtx (mode, x)
*** 211,221 ****
/* ??? Note that there are two different ideas here for how
to determine the size to count bits within, for a register.
One is BITS_PER_WORD, and the other is the size of operand 3
! of the insv pattern. (The latter assumes that an n-bit machine
! will be able to insert bit fields up to n bits wide.)
! It isn't certain that either of these is right.
! extract_bit_field has the same quandary. */
rtx
store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
rtx str_rtx;
--- 211,221 ----
/* ??? Note that there are two different ideas here for how
to determine the size to count bits within, for a register.
One is BITS_PER_WORD, and the other is the size of operand 3
! of the insv pattern.
+ If operand 3 of the insv pattern is VOIDmode, then we will use BITS_PER_WORD
+ else, we use the mode of operand 3. */
+
rtx
store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
rtx str_rtx;
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 230,235 ****
--- 230,243 ----
register int offset = bitnum / unit;
register int bitpos = bitnum % unit;
register rtx op0 = str_rtx;
+ #ifdef HAVE_insv
+ int insv_bitsize;
+
+ if (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode)
+ insv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ insv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]);
+ #endif
if (GET_CODE (str_rtx) == MEM && ! MEM_IN_STRUCT_P (str_rtx))
abort ();
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 400,420 ****
&& GET_MODE (value) != BLKmode
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */
! && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3])
! >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos
! > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_insv][3]))))
{
int xbitpos = bitpos;
rtx value1;
rtx xop0 = op0;
rtx last = get_last_insn ();
rtx pat;
! enum machine_mode maxmode
! = insn_operand_mode[(int) CODE_FOR_insv][3];
!
int save_volatile_ok = volatile_ok;
volatile_ok = 1;
/* If this machine's insv can only insert into a register, copy OP0
--- 408,429 ----
&& GET_MODE (value) != BLKmode
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */
! && (insv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos > insv_bitsize)))
{
int xbitpos = bitpos;
rtx value1;
rtx xop0 = op0;
rtx last = get_last_insn ();
rtx pat;
! enum machine_mode maxmode;
int save_volatile_ok = volatile_ok;
+
+ maxmode = insn_operand_mode[(int) CODE_FOR_insv][3];
+ if (maxmode == VOIDmode)
+ maxmode = word_mode;
+
volatile_ok = 1;
/* If this machine's insv can only insert into a register, copy OP0
*************** extract_bit_field (str_rtx, bitsize, bit
*** 896,902 ****
--- 905,932 ----
register rtx op0 = str_rtx;
rtx spec_target = target;
rtx spec_target_subreg = 0;
+ #ifdef HAVE_extv
+ int extv_bitsize;
+ #endif
+ #ifdef HAVE_extzv
+ int extzv_bitsize;
+ #endif
+
+ #ifdef HAVE_extv
+ if (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode)
+ extv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ extv_bitsize = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]);
+ #endif
+ #ifdef HAVE_extzv
+ if (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode)
+ extzv_bitsize = GET_MODE_BITSIZE (word_mode);
+ else
+ extzv_bitsize
+ = GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]);
+ #endif
+
/* Discount the part of the structure before the desired byte.
We need to know how many bytes are safe to reference after it. */
if (total_size >= 0)
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1075,1085 ****
{
#ifdef HAVE_extzv
if (HAVE_extzv
! && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0])
! >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos
! > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extzv][0]))))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
--- 1105,1113 ----
{
#ifdef HAVE_extzv
if (HAVE_extzv
! && (extzv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos > extzv_bitsize)))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1089,1097 ****
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
! enum machine_mode maxmode
! = insn_operand_mode[(int) CODE_FOR_extzv][0];
if (GET_CODE (xop0) == MEM)
{
int save_volatile_ok = volatile_ok;
--- 1117,1128 ----
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
! enum machine_mode maxmode;
+ maxmode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+ if (maxmode == VOIDmode)
+ maxmode = word_mode;
+
if (GET_CODE (xop0) == MEM)
{
int save_volatile_ok = volatile_ok;
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1215,1225 ****
{
#ifdef HAVE_extv
if (HAVE_extv
! && (GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0])
! >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos
! > GET_MODE_BITSIZE (insn_operand_mode[(int) CODE_FOR_extv][0]))))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
--- 1246,1254 ----
{
#ifdef HAVE_extv
if (HAVE_extv
! && (extv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
! && (bitsize + bitpos > extv_bitsize)))
{
int xbitpos = bitpos, xoffset = offset;
rtx bitsize_rtx, bitpos_rtx;
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1228,1235 ****
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
! enum machine_mode maxmode
! = insn_operand_mode[(int) CODE_FOR_extv][0];
if (GET_CODE (xop0) == MEM)
{
--- 1257,1267 ----
rtx xspec_target = spec_target;
rtx xspec_target_subreg = spec_target_subreg;
rtx pat;
! enum machine_mode maxmode;
!
! maxmode = insn_operand_mode[(int) CODE_FOR_extv][0];
! if (maxmode == VOIDmode)
! maxmode = word_mode;
if (GET_CODE (xop0) == MEM)
{
Index: function.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/function.c,v
retrieving revision 1.173
diff -c -3 -p -r1.173 function.c
*** function.c 1998/08/19 22:22:06 1.173
--- function.c 1998/09/16 05:13:29
*************** fixup_var_refs_1 (var, promoted_mode, lo
*** 1990,2000 ****
#ifdef HAVE_extzv
if (GET_CODE (x) == ZERO_EXTRACT)
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
#endif
#ifdef HAVE_extv
if (GET_CODE (x) == SIGN_EXTRACT)
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
#endif
/* If we have a narrower mode, we can do something. */
if (wanted_mode != VOIDmode
--- 1990,2008 ----
#ifdef HAVE_extzv
if (GET_CODE (x) == ZERO_EXTRACT)
! {
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
! if (wanted_mode == VOIDmode)
! wanted_mode = word_mode;
! }
#endif
#ifdef HAVE_extv
if (GET_CODE (x) == SIGN_EXTRACT)
! {
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
! if (wanted_mode == VOIDmode)
! wanted_mode = word_mode;
! }
#endif
/* If we have a narrower mode, we can do something. */
if (wanted_mode != VOIDmode
*************** fixup_var_refs_1 (var, promoted_mode, lo
*** 2183,2192 ****
&& ! mode_dependent_address_p (XEXP (tem, 0))
&& ! MEM_VOLATILE_P (tem))
{
! enum machine_mode wanted_mode
! = insn_operand_mode[(int) CODE_FOR_insv][0];
enum machine_mode is_mode = GET_MODE (tem);
HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
/* If we have a narrower mode, we can do something. */
if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
--- 2191,2203 ----
&& ! mode_dependent_address_p (XEXP (tem, 0))
&& ! MEM_VOLATILE_P (tem))
{
! enum machine_mode wanted_mode;
enum machine_mode is_mode = GET_MODE (tem);
HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
+
+ wanted_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
+ if (wanted_mode == VOIDmode)
+ wanted_mode = word_mode;
/* If we have a narrower mode, we can do something. */
if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
Index: recog.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/recog.c,v
retrieving revision 1.58
diff -c -3 -p -r1.58 recog.c
*** recog.c 1998/08/23 06:19:49 1.58
--- recog.c 1998/09/16 05:13:31
*************** validate_replace_rtx_1 (loc, from, to, o
*** 484,494 ****
#ifdef HAVE_extzv
if (code == ZERO_EXTRACT)
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
#endif
#ifdef HAVE_extv
if (code == SIGN_EXTRACT)
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
#endif
/* If we have a narrower mode, we can do something. */
--- 484,502 ----
#ifdef HAVE_extzv
if (code == ZERO_EXTRACT)
! {
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
! if (wanted_mode == VOIDmode)
! wanted_mode = word_mode;
! }
#endif
#ifdef HAVE_extv
if (code == SIGN_EXTRACT)
! {
! wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
! if (wanted_mode == VOIDmode)
! wanted_mode = word_mode;
! }
#endif
/* If we have a narrower mode, we can do something. */
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/config/mips/mips.md,v
retrieving revision 1.127
diff -c -3 -p -r1.127 mips.md
*** mips.md 1998/09/01 21:25:39 1.127
--- mips.md 1998/09/16 05:13:43
*************** move\\t%0,%z4\\n\\
*** 4581,4604 ****
;; Bit field extract patterns which use lwl/lwr.
- ;; ??? There should be DImode variants for 64 bit code, but the current
- ;; bitfield scheme can't handle that. We would need to add new optabs
- ;; in order to make that work.
-
;; ??? There could be HImode variants for the ulh/ulhu/ush macros.
;; It isn't clear whether this will give better code.
(define_expand "extv"
! [(set (match_operand:SI 0 "register_operand" "")
! (sign_extract:SI (match_operand:QI 1 "memory_operand" "")
! (match_operand:SI 2 "immediate_operand" "")
! (match_operand:SI 3 "immediate_operand" "")))]
"!TARGET_MIPS16"
"
{
! /* If this isn't a 32 bit field, and it doesn't start on a byte boundary
! then fail. */
! if (INTVAL (operands[2]) != 32 || (INTVAL (operands[3]) % 8) != 0)
FAIL;
/* This can happen for a 64 bit target, when extracting a value from
--- 4581,4610 ----
;; Bit field extract patterns which use lwl/lwr.
;; ??? There could be HImode variants for the ulh/ulhu/ush macros.
;; It isn't clear whether this will give better code.
+ ;; Only specify the mode operand 1, the rest are assumed to be word_mode.
(define_expand "extv"
! [(set (match_operand 0 "register_operand" "")
! (sign_extract (match_operand:QI 1 "memory_operand" "")
! (match_operand 2 "immediate_operand" "")
! (match_operand 3 "immediate_operand" "")))]
"!TARGET_MIPS16"
"
{
! /* If the field does not start on a byte boundary, then fail. */
! if (INTVAL (operands[3]) % 8 != 0)
! FAIL;
!
! /* MIPS I and MIPS II can only handle a 32bit field. */
! if (!TARGET_64BIT && INTVAL (operands[2]) != 32)
! FAIL;
!
! /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */
! if (TARGET_64BIT
! && INTVAL (operands[2]) != 64
! && INTVAL (operands[2]) != 32)
FAIL;
/* This can happen for a 64 bit target, when extracting a value from
*************** move\\t%0,%z4\\n\\
*** 4610,4633 ****
/* Change the mode to BLKmode for aliasing purposes. */
operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
! /* Otherwise, emit a lwl/lwr pair to load the value. */
! emit_insn (gen_movsi_ulw (operands[0], operands[1]));
DONE;
}")
(define_expand "extzv"
! [(set (match_operand:SI 0 "register_operand" "")
! (zero_extract:SI (match_operand:QI 1 "memory_operand" "")
! (match_operand:SI 2 "immediate_operand" "")
! (match_operand:SI 3 "immediate_operand" "")))]
"!TARGET_MIPS16"
"
{
! /* If this isn't a 32 bit field, and it doesn't start on a byte boundary
! then fail. */
! if (INTVAL (operands[2]) != 32 || (INTVAL (operands[3]) % 8) != 0)
FAIL;
/* This can happen for a 64 bit target, when extracting a value from
a 64 bit union member. extract_bit_field doesn't verify that our
source matches the predicate, so we force it to be a MEM here. */
--- 4616,4660 ----
/* Change the mode to BLKmode for aliasing purposes. */
operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
! /* Otherwise, emit a l[wd]l/l[wd]r pair to load the value. */
! if (INTVAL (operands[2]) == 64)
! emit_insn (gen_movdi_uld (operands[0], operands[1]));
! else
! {
! if (TARGET_64BIT)
! {
! operands[0] = gen_lowpart (SImode, operands[0]);
! if (operands[0] == NULL_RTX)
! FAIL;
! }
! emit_insn (gen_movsi_ulw (operands[0], operands[1]));
! }
DONE;
}")
+ ;; Only specify the mode operand 1, the rest are assumed to be word_mode.
(define_expand "extzv"
! [(set (match_operand 0 "register_operand" "")
! (zero_extract (match_operand:QI 1 "memory_operand" "")
! (match_operand 2 "immediate_operand" "")
! (match_operand 3 "immediate_operand" "")))]
"!TARGET_MIPS16"
"
{
! /* If the field does not start on a byte boundary, then fail. */
! if (INTVAL (operands[3]) % 8 != 0)
FAIL;
+ /* MIPS I and MIPS II can only handle a 32bit field. */
+ if (!TARGET_64BIT && INTVAL (operands[2]) != 32)
+ FAIL;
+
+ /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */
+ if (TARGET_64BIT
+ && INTVAL (operands[2]) != 64
+ && INTVAL (operands[2]) != 32)
+ FAIL;
+
/* This can happen for a 64 bit target, when extracting a value from
a 64 bit union member. extract_bit_field doesn't verify that our
source matches the predicate, so we force it to be a MEM here. */
*************** move\\t%0,%z4\\n\\
*** 4638,4658 ****
operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
/* Otherwise, emit a lwl/lwr pair to load the value. */
! emit_insn (gen_movsi_ulw (operands[0], operands[1]));
DONE;
}")
(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 "register_operand" ""))]
"!TARGET_MIPS16"
"
{
! /* If this isn't a 32 bit field, and it doesn't start on a byte boundary
! then fail. */
! if (INTVAL (operands[1]) != 32 || (INTVAL (operands[2]) % 8) != 0)
FAIL;
/* This can happen for a 64 bit target, when storing into a 32 bit union
--- 4665,4706 ----
operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
/* Otherwise, emit a lwl/lwr pair to load the value. */
! if (INTVAL (operands[2]) == 64)
! emit_insn (gen_movdi_uld (operands[0], operands[1]));
! else
! {
! if (TARGET_64BIT)
! {
! operands[0] = gen_lowpart (SImode, operands[0]);
! if (operands[0] == NULL_RTX)
! FAIL;
! }
! emit_insn (gen_movsi_ulw (operands[0], operands[1]));
! }
DONE;
}")
+ ;; Only specify the mode operands 0, the rest are assumed to be word_mode.
(define_expand "insv"
! [(set (zero_extract (match_operand:QI 0 "memory_operand" "")
! (match_operand 1 "immediate_operand" "")
! (match_operand 2 "immediate_operand" ""))
! (match_operand 3 "register_operand" ""))]
"!TARGET_MIPS16"
"
{
! /* If the field does not start on a byte boundary, then fail. */
! if (INTVAL (operands[2]) % 8 != 0)
! FAIL;
!
! /* MIPS I and MIPS II can only handle a 32bit field. */
! if (!TARGET_64BIT && INTVAL (operands[1]) != 32)
! FAIL;
!
! /* MIPS III and MIPS IV can handle both 32bit and 64bit fields. */
! if (TARGET_64BIT
! && INTVAL (operands[1]) != 64
! && INTVAL (operands[1]) != 32)
FAIL;
/* This can happen for a 64 bit target, when storing into a 32 bit union
*************** move\\t%0,%z4\\n\\
*** 4664,4671 ****
/* Change the mode to BLKmode for aliasing purposes. */
operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0));
! /* Otherwise, emit a swl/swr pair to load the value. */
! emit_insn (gen_movsi_usw (operands[0], operands[3]));
DONE;
}")
--- 4712,4730 ----
/* Change the mode to BLKmode for aliasing purposes. */
operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0));
! /* Otherwise, emit a s[wd]l/s[wd]r pair to load the value. */
! if (INTVAL (operands[1]) == 64)
! emit_insn (gen_movdi_usd (operands[0], operands[3]));
! else
! {
! if (TARGET_64BIT)
! {
! operands[3] = gen_lowpart (SImode, operands[3]);
! if (operands[3] == NULL_RTX)
! FAIL;
! }
! emit_insn (gen_movsi_usw (operands[0], operands[3]));
! }
DONE;
}")
*************** move\\t%0,%z4\\n\\
*** 4721,4726 ****
--- 4780,4844 ----
return \"sw\\t%1,%0\";
return \"usw\\t%z1,%0\";
+ }"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2,4")])
+
+ ;; Bit field extract patterns which use ldl/ldr.
+
+ ;; unaligned double word moves generated by the bit field patterns
+
+ (define_insn "movdi_uld"
+ [(set (match_operand:DI 0 "register_operand" "=&d,&d")
+ (unspec:DI [(match_operand:BLK 1 "general_operand" "R,o")] 0))]
+ ""
+ "*
+ {
+ rtx offset = const0_rtx;
+ rtx addr = XEXP (operands[1], 0);
+ rtx mem_addr = eliminate_constant_term (addr, &offset);
+ char *ret;
+
+ if (TARGET_STATS)
+ mips_count_memory_refs (operands[1], 2);
+
+ /* The stack/frame pointers are always aligned, so we can convert
+ to the faster lw if we are referencing an aligned stack location. */
+
+ if ((INTVAL (offset) & 7) == 0
+ && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx))
+ ret = \"ld\\t%0,%1\";
+ else
+ ret = \"uld\\t%0,%1\";
+
+ return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn);
+ }"
+ [(set_attr "type" "load,load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2,4")])
+
+ (define_insn "movdi_usd"
+ [(set (match_operand:BLK 0 "memory_operand" "=R,o")
+ (unspec:BLK [(match_operand:DI 1 "reg_or_0_operand" "dJ,dJ")] 1))]
+ ""
+ "*
+ {
+ rtx offset = const0_rtx;
+ rtx addr = XEXP (operands[0], 0);
+ rtx mem_addr = eliminate_constant_term (addr, &offset);
+
+ if (TARGET_STATS)
+ mips_count_memory_refs (operands[0], 2);
+
+ /* The stack/frame pointers are always aligned, so we can convert
+ to the faster sw if we are referencing an aligned stack location. */
+
+ if ((INTVAL (offset) & 7) == 0
+ && (mem_addr == stack_pointer_rtx || mem_addr == frame_pointer_rtx))
+ return \"sd\\t%1,%0\";
+
+ return \"usd\\t%z1,%0\";
}"
[(set_attr "type" "store")
(set_attr "mode" "SI")