+2001-08-21 Zack Weinberg <zackw@panix.com>
+
+ * expmed.c (mode_for_extraction): New function.
+ (store_bit_field, extract_bit_field): Use it.
+ * expr.h: Prototype it and provide an enum for its first argument.
+
+ * combine.c, function.c, recog.c: Don't include insn-codes.h.
+ Use mode_for_extraction rather than testing HAVE_insv/extv/extzv
+ and digging through the insn_data tables.
+ * Makefile.in: Update dependencies.
+
2001-08-22 Neil Booth <neil@daikokuya.demon.co.uk>
* cppfiles.c (stack_include_file): line-map.c now handles include
output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
$(HASHTAB_H) $(TARGET_H)
function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
- function.h insn-codes.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
+ function.h $(EXPR_H) libfuncs.h $(REGS_H) hard-reg-set.h \
insn-config.h $(RECOG_H) output.h toplev.h except.h hash.h $(GGC_H) $(TM_P_H)
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h \
$(BASIC_BLOCK_H)
combine.o : combine.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h function.h \
- insn-config.h insn-codes.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
+ insn-config.h $(INSN_ATTR_H) $(REGS_H) $(EXPR_H) \
$(BASIC_BLOCK_H) $(RECOG_H) real.h hard-reg-set.h toplev.h $(TM_P_H)
regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) hard-reg-set.h flags.h \
$(BASIC_BLOCK_H) $(REGS_H) insn-config.h $(RECOG_H) reload.h real.h \
toplev.h reload.h dwarf2out.h $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H)
recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) function.h $(BASIC_BLOCK_H) \
$(REGS_H) $(RECOG_H) $(EXPR_H) hard-reg-set.h flags.h insn-config.h \
- $(INSN_ATTR_H) insn-codes.h real.h toplev.h output.h reload.h $(TM_P_H)
+ $(INSN_ATTR_H) real.h toplev.h output.h reload.h $(TM_P_H)
reg-stack.o : reg-stack.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) $(RECOG_H) \
$(REGS_H) hard-reg-set.h flags.h insn-config.h toplev.h reload.h \
varray.h function.h $(TM_P_H)
#include "hard-reg-set.h"
#include "basic-block.h"
#include "insn-config.h"
-#include "insn-codes.h"
#include "function.h"
/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
#include "expr.h"
/* Get the mode to use should INNER not be a MEM, the mode for the position,
and the mode for the result. */
-#ifdef HAVE_insv
- if (in_dest)
+ if (in_dest && mode_for_extraction(EP_insv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_insv].operand[0].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_insv].operand[2].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_insv, 0);
+ pos_mode = mode_for_extraction (EP_insv, 2);
+ extraction_mode = mode_for_extraction (EP_insv, 3);
}
-#endif
-#ifdef HAVE_extzv
- if (! in_dest && unsignedp)
+ if (! in_dest && unsignedp
+ && mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_extzv].operand[3].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1);
+ pos_mode = mode_for_extraction (EP_extzv, 3);
+ extraction_mode = mode_for_extraction (EP_extzv, 0);
}
-#endif
-#ifdef HAVE_extv
- if (! in_dest && ! unsignedp)
+ if (! in_dest && ! unsignedp
+ && mode_for_extraction (EP_extv, -1) != MAX_MACHINE_MODE)
{
- wanted_inner_reg_mode
- = insn_data[(int) CODE_FOR_extv].operand[1].mode;
- if (wanted_inner_reg_mode == VOIDmode)
- wanted_inner_reg_mode = word_mode;
-
- pos_mode = insn_data[(int) CODE_FOR_extv].operand[3].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- extraction_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
- if (extraction_mode == VOIDmode)
- extraction_mode = word_mode;
+ wanted_inner_reg_mode = mode_for_extraction (EP_extv, 1);
+ pos_mode = mode_for_extraction (EP_extv, 3);
+ extraction_mode = mode_for_extraction (EP_extv, 0);
}
-#endif
/* Never narrow an object, since that might not be safe. */
{
if (BITS_BIG_ENDIAN)
{
-#ifdef HAVE_extzv
- mode = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (mode == VOIDmode)
- mode = word_mode;
- i = (GET_MODE_BITSIZE (mode) - 1 - i);
-#else
- i = BITS_PER_WORD - 1 - i;
-#endif
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extzv, 1);
+ if (new_mode == MAX_MACHINE_MODE)
+ i = BITS_PER_WORD - 1 - i;
+ else
+ {
+ mode = new_mode;
+ i = (GET_MODE_BITSIZE (mode) - 1 - i);
+ }
}
op0 = XEXP (op0, 2);
return result;
}
+
+/* Report on the availability of insv/extv/extzv and the desired mode
+ of each of their operands. Returns MAX_MACHINE_MODE if HAVE_foo
+ is false; else the mode of the specified operand. If OPNO is -1,
+ all the caller cares about is whether the insn is available. */
+enum machine_mode
+mode_for_extraction (pattern, opno)
+ enum extraction_pattern pattern;
+ int opno;
+{
+ const struct insn_data *data;
+
+ switch (pattern)
+ {
+ case EP_insv:
+#ifdef HAVE_insv
+ if (HAVE_insv)
+ {
+ data = &insn_data[CODE_FOR_insv];
+ break;
+ }
+#endif
+ return MAX_MACHINE_MODE;
+
+ case EP_extv:
+#ifdef HAVE_extv
+ if (HAVE_extv)
+ {
+ data = &insn_data[CODE_FOR_extv];
+ break;
+ }
+#endif
+ return MAX_MACHINE_MODE;
+
+ case EP_extzv:
+#ifdef HAVE_extzv
+ if (HAVE_extzv)
+ {
+ data = &insn_data[CODE_FOR_extzv];
+ break;
+ }
+#endif
+ return MAX_MACHINE_MODE;
+ }
+
+ if (opno == -1)
+ return VOIDmode;
+
+ /* Everyone who uses this function used to follow it with
+ if (result == VOIDmode) result = word_mode; */
+ if (data->operand[opno].mode == VOIDmode)
+ return word_mode;
+ return data->operand[opno].mode;
+}
+
\f
/* Generate code to store value from rtx VALUE
into a bit-field within structure STR_RTX
unsigned HOST_WIDE_INT offset = bitnum / unit;
unsigned HOST_WIDE_INT bitpos = bitnum % unit;
register rtx op0 = str_rtx;
-#ifdef HAVE_insv
+
unsigned HOST_WIDE_INT insv_bitsize;
enum machine_mode op_mode;
- op_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
- if (op_mode == VOIDmode)
- op_mode = word_mode;
- insv_bitsize = GET_MODE_BITSIZE (op_mode);
-#endif
+ op_mode = mode_for_extraction (EP_insv, 3);
+ if (op_mode != MAX_MACHINE_MODE)
+ insv_bitsize = GET_MODE_BITSIZE (op_mode);
/* It is wrong to have align==0, since every object is aligned at
least at a bit boundary. This usually means a bug elsewhere. */
/* Now OFFSET is nonzero only if OP0 is memory
and is therefore always measured in bytes. */
-#ifdef HAVE_insv
- if (HAVE_insv
+ if (op_mode != MAX_MACHINE_MODE
&& GET_MODE (value) != BLKmode
&& !(bitsize == 1 && GET_CODE (value) == CONST_INT)
/* Ensure insv's size is wide enough for this field. */
}
else
insv_loses:
-#endif
/* Insv is not available; store using shifts and boolean ops. */
store_fixed_bit_field (op0, offset, bitsize, bitpos, value, align);
return value;
rtx spec_target = target;
rtx spec_target_subreg = 0;
enum machine_mode int_mode;
-#ifdef HAVE_extv
unsigned HOST_WIDE_INT extv_bitsize;
enum machine_mode extv_mode;
-#endif
-#ifdef HAVE_extzv
unsigned HOST_WIDE_INT extzv_bitsize;
enum machine_mode extzv_mode;
-#endif
-#ifdef HAVE_extv
- extv_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
- if (extv_mode == VOIDmode)
- extv_mode = word_mode;
- extv_bitsize = GET_MODE_BITSIZE (extv_mode);
-#endif
+ extv_mode = mode_for_extraction (EP_extv, 0);
+ if (extv_mode != MAX_MACHINE_MODE)
+ extv_bitsize = GET_MODE_BITSIZE (extv_mode);
-#ifdef HAVE_extzv
- extzv_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
- if (extzv_mode == VOIDmode)
- extzv_mode = word_mode;
- extzv_bitsize = GET_MODE_BITSIZE (extzv_mode);
-#endif
+ extzv_mode = mode_for_extraction (EP_extzv, 0);
+ if (extzv_mode != MAX_MACHINE_MODE)
+ extzv_bitsize = GET_MODE_BITSIZE (extzv_mode);
/* Discount the part of the structure before the desired byte.
We need to know how many bytes are safe to reference after it. */
if (unsignedp)
{
-#ifdef HAVE_extzv
- if (HAVE_extzv
+ if (extzv_mode != MAX_MACHINE_MODE
&& (extzv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
&& (bitsize + bitpos > extzv_bitsize)))
}
else
extzv_loses:
-#endif
target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
bitpos, target, 1, align);
}
else
{
-#ifdef HAVE_extv
- if (HAVE_extv
+ if (extv_mode != MAX_MACHINE_MODE
&& (extv_bitsize >= bitsize)
&& ! ((GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
&& (bitsize + bitpos > extv_bitsize)))
}
else
extv_loses:
-#endif
target = extract_fixed_bit_field (int_mode, op0, offset, bitsize,
bitpos, target, 0, align);
}
that is in range, try a rotate in the opposite direction. */
if (temp == 0 && GET_CODE (op1) == CONST_INT
- && INTVAL (op1) > 0 && INTVAL (op1) < GET_MODE_BITSIZE (mode))
+ && INTVAL (op1) > 0
+ && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
temp = expand_binop (mode,
left ? rotr_optab : rotl_optab,
shifted,
of STACK_BOUNDARY / BITS_PER_UNIT. */
extern rtx round_push PARAMS ((rtx));
+/* Return the mode desired by operand N of a particular bitfield
+ insert/extract insn, or MAX_MACHINE_MODE if no such insn is
+ available. */
+
+enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
+extern enum machine_mode
+mode_for_extraction PARAMS ((enum extraction_pattern, int));
+
extern rtx store_bit_field PARAMS ((rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
enum machine_mode, rtx,
#include "regs.h"
#include "hard-reg-set.h"
#include "insn-config.h"
-#include "insn-codes.h"
#include "recog.h"
#include "output.h"
#include "basic-block.h"
enum machine_mode is_mode = GET_MODE (tem);
HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
-#ifdef HAVE_extzv
if (GET_CODE (x) == ZERO_EXTRACT)
{
- wanted_mode
- = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (wanted_mode == VOIDmode)
- wanted_mode = word_mode;
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extzv, 1);
+ if (new_mode != MAX_MACHINE_MODE)
+ wanted_mode = new_mode;
}
-#endif
-#ifdef HAVE_extv
- if (GET_CODE (x) == SIGN_EXTRACT)
+ else if (GET_CODE (x) == SIGN_EXTRACT)
{
- wanted_mode = insn_data[(int) CODE_FOR_extv].operand[1].mode;
- if (wanted_mode == VOIDmode)
- wanted_mode = word_mode;
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extv, 1);
+ if (new_mode != MAX_MACHINE_MODE)
+ wanted_mode = new_mode;
}
-#endif
+
/* If we have a narrower mode, we can do something. */
if (wanted_mode != VOIDmode
&& GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
{
rtx dest = SET_DEST (x);
rtx src = SET_SRC (x);
-#ifdef HAVE_insv
rtx outerdest = dest;
-#endif
while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
|| GET_CODE (dest) == SIGN_EXTRACT
/* We will need to rerecognize this insn. */
INSN_CODE (insn) = -1;
-#ifdef HAVE_insv
- if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var)
+ if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var
+ && mode_for_extraction (EP_insv, -1) != MAX_MACHINE_MODE)
{
/* Since this case will return, ensure we fixup all the
operands here. */
enum machine_mode is_mode = GET_MODE (tem);
HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
- wanted_mode = insn_data[(int) CODE_FOR_insv].operand[0].mode;
- if (wanted_mode == VOIDmode)
- wanted_mode = word_mode;
+ wanted_mode = mode_for_extraction (EP_insv, 0);
/* If we have a narrower mode, we can do something. */
if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
XEXP (outerdest, 0) = tem1;
return;
}
-#endif
/* STRICT_LOW_PART is a no-op on memory references
and it can cause combinations to be unrecognizable,
#include "recog.h"
#include "regs.h"
#include "expr.h"
-#include "insn-codes.h"
#include "function.h"
#include "flags.h"
#include "real.h"
enum machine_mode is_mode = GET_MODE (XEXP (x, 0));
int pos = INTVAL (XEXP (x, 2));
-#ifdef HAVE_extzv
- if (code == ZERO_EXTRACT)
+ if (GET_CODE (x) == ZERO_EXTRACT)
{
- wanted_mode = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
- if (wanted_mode == VOIDmode)
- wanted_mode = word_mode;
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extzv, 1);
+ if (new_mode != MAX_MACHINE_MODE)
+ wanted_mode = new_mode;
}
-#endif
-#ifdef HAVE_extv
- if (code == SIGN_EXTRACT)
+ else if (GET_CODE (x) == SIGN_EXTRACT)
{
- wanted_mode = insn_data[(int) CODE_FOR_extv].operand[1].mode;
- if (wanted_mode == VOIDmode)
- wanted_mode = word_mode;
+ enum machine_mode new_mode
+ = mode_for_extraction (EP_extv, 1);
+ if (new_mode != MAX_MACHINE_MODE)
+ wanted_mode = new_mode;
}
-#endif
/* If we have a narrower mode, we can do something. */
if (wanted_mode != VOIDmode