summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog212
-rw-r--r--gcc/alias.c2
-rw-r--r--gcc/caller-save.c26
-rw-r--r--gcc/calls.c25
-rw-r--r--gcc/combine.c165
-rw-r--r--gcc/config/a29k/a29k.c12
-rw-r--r--gcc/config/alpha/alpha.c3
-rw-r--r--gcc/config/arm/arm.c12
-rw-r--r--gcc/config/d30v/d30v.c19
-rw-r--r--gcc/config/dsp16xx/dsp16xx.md4
-rw-r--r--gcc/config/h8300/h8300.md4
-rw-r--r--gcc/config/i370/i370.md21
-rw-r--r--gcc/config/i860/i860.c2
-rw-r--r--gcc/config/i860/i860.md16
-rw-r--r--gcc/config/i960/i960.md62
-rw-r--r--gcc/config/m68hc11/m68hc11.c8
-rw-r--r--gcc/config/m68k/m68k.md20
-rw-r--r--gcc/config/m88k/m88k.md4
-rw-r--r--gcc/config/mips/mips.c45
-rw-r--r--gcc/config/mips/mips.md134
-rw-r--r--gcc/config/mn10200/mn10200.c9
-rw-r--r--gcc/config/mn10300/mn10300.c9
-rw-r--r--gcc/config/ns32k/ns32k.md4
-rw-r--r--gcc/config/pa/pa.c8
-rw-r--r--gcc/config/pa/pa.md8
-rw-r--r--gcc/config/pdp11/pdp11.md14
-rw-r--r--gcc/config/romp/romp.c7
-rw-r--r--gcc/config/sh/sh.c19
-rw-r--r--gcc/config/sh/sh.h2
-rw-r--r--gcc/config/sh/sh.md8
-rw-r--r--gcc/config/sparc/sparc.c4
-rw-r--r--gcc/config/sparc/sparc.h37
-rw-r--r--gcc/config/sparc/sparc.md86
-rw-r--r--gcc/config/v850/v850.c4
-rw-r--r--gcc/cse.c41
-rw-r--r--gcc/dbxout.c13
-rw-r--r--gcc/dwarf2out.c6
-rw-r--r--gcc/dwarfout.c6
-rw-r--r--gcc/emit-rtl.c600
-rw-r--r--gcc/expmed.c33
-rw-r--r--gcc/expr.c8
-rw-r--r--gcc/final.c25
-rw-r--r--gcc/flow.c11
-rw-r--r--gcc/function.c47
-rw-r--r--gcc/gengenrtl.c1
-rw-r--r--gcc/global.c33
-rw-r--r--gcc/ifcvt.c5
-rw-r--r--gcc/integrate.c37
-rw-r--r--gcc/jump.c28
-rw-r--r--gcc/local-alloc.c38
-rw-r--r--gcc/recog.c150
-rw-r--r--gcc/reg-stack.c6
-rw-r--r--gcc/regmove.c4
-rw-r--r--gcc/regs.h20
-rw-r--r--gcc/reload.c165
-rw-r--r--gcc/reload1.c51
-rw-r--r--gcc/resource.c6
-rw-r--r--gcc/rtl.h17
-rw-r--r--gcc/rtl.texi21
-rw-r--r--gcc/rtlanal.c84
-rw-r--r--gcc/sched-vis.c2
-rw-r--r--gcc/sdbout.c12
-rw-r--r--gcc/stmt.c2
-rw-r--r--gcc/tm.texi24
64 files changed, 1639 insertions, 872 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e42b63a675b..a63667af04c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,215 @@
+2001-04-03 Jakub Jelinek <jakub@redhat.com>
+ David S. Miller <davem@pierdol.cobaltmicro.com>
+ Andrew MacLeod <amacleod@redhat.com>
+
+ Use byte offsets in SUBREGs instead of words.
+
+ * alias.c (nonlocal_mentioned_p): Use subreg_regno function.
+ * caller-save.c (mark_set_regs): Change callers of subreg_hard_regno
+ to pass new argument.
+ (add_stored_regs): Use subreg_regno_offset function.
+ * calls.c (expand_call): For non-paradoxical SUBREG take endianess
+ into account.
+ (precompute_arguments): Use gen_lowpart_SUBREG.
+ * combine.c (try_combine): Replace explicit XEXP with SUBREG_REG.
+ (combine_simplify_rtx): Rework to use SUBREG_BYTE.
+ (simplify_set): Rework to use SUBREG_BYTE.
+ (expand_field_assignment): Use SUBREG_BYTE.
+ (make_extraction): Use SUBREG_BYTE.
+ (if_then_else_cond): Use SUBREG_BYTE.
+ (apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments.
+ (gen_lowpart_for_combine): Compute full byte offset.
+ * cse.c (mention_regs): Use SUBREG_BYTE.
+ (remove_invalid_subreg_refs): Rework to use SUBREG_BYTE.
+ (canon_hash): Use SUBREG_BYTE.
+ (fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword.
+ (gen_lowpart_if_possible): Formatting.
+ * dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos
+ correctly.
+ * dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
+ (mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
+ (loc_descriptor): Fixup explicit XEXP into SUBREG_REG
+ * dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
+ (output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
+ (output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
+ * emit-rtl.c (gen_rtx_SUBREG): New function, used to verify
+ certain invariants about SUBREGs the compiler creates.
+ (gen_lowpart_SUBREG): New function.
+ (subreg_hard_regno): New function to get the final register number.
+ (gen_lowpart_common): Use SUBREG_BYTE.
+ (gen_imagpart): Spacing nits.
+ (subreg_realpart_p): Use SUBREG_BYTE.
+ (gen_highpart): Use SUBREG_BYTE.
+ (subreg_lowpart_p): Always compute endian corrected goal offset,
+ even at the byte level, then compare against that.
+ (constant_subword): New function, pulled out all constant cases
+ from operand_subword and changed second argument name to offset.
+ (operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early
+ and call constant_subword to do the work. Return const0_rtx if
+ looking for a word outside of OP.
+ (operand_subword_force): Change second arg name to offset.
+ * expmed.c (store_bit_field): Use SUBREG_BYTE.
+ (store_split_bit_field): Use SUBREG_BYTE.
+ (extract_bit_field): Use SUBREG_BYTE.
+ (extract_split_bit_field): Use SUBREG_BYTE.
+ (expand_shift): Use SUBREG_BYTE.
+ * expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG.
+ * final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE.
+ * flow.c (set_noop_p): Use SUBREG_BYTE.
+ (mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead.
+ * function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG.
+ (fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian
+ correction code.
+ (optimize_bit_field): Use SUBREG_BYTE.
+ (purge_addressof_1): Use SUBREG_BYTE.
+ (purge_single_hard_subreg_set): Use subreg_regno_offset function.
+ (assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are
+ actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true.
+ * gengenrtl.c (special_rtx): Add SUBREG.
+ * global.c (mark_reg_store): Use SUBREG_BYTE.
+ (set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE.
+ * ifcvt (noce_emit_move_insn): Use SUBREG_BYTE.
+ * integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure
+ final byte offset is congruent to subreg's mode size.
+ (subst_constants): Use SUBREG_BYTE.
+ (mark_stores): Use subreg_regno_offset function.
+ * jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset
+ function and SUBREG_BYTE.
+ * local-alloc.c (combine_regs): Use subreg_regno_offset function.
+ (reg_is_born): Use subreg_hard_regno.
+ * recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte
+ endian correction code. Don't combine subregs unless resulting
+ offset aligns with type. Fix subreg constant extraction for DImode.
+ Simplify SUBREG of VOIDmode CONST_DOUBLE.
+ (general_operand): Remove dead mode_altering_drug code.
+ (indirect_operand): Use SUBREG_BYTE.
+ (constrain_operands): Use subreg_regno_offset function.
+ * reg-stack.c (get_true_reg): Use subreg_regno_offset function.
+ * regmove.c (regmove_optimize): Use SUBREG_BYTE.
+ (optimize_reg_copy_3): Use gen_lowpart_SUBREG.
+ * regs.h (REG_SIZE): Allow target to override.
+ (REGMODE_NATURAL_SIZE): New macro which target can override.
+ * reload.c (reload_inner_reg_of_subreg): subreg_regno should be used
+ on the entire subreg rtx.
+ (push_reload): Use SUBREG_BYTE in comments and code.
+ (find_dummy_reload): Use subreg_regno_offset. Only adjust offsets
+ for hard registers inside subregs.
+ (operands_match_p): Use subreg_regno_offset.
+ (find_reloads): Use SUBREG_BYTE and only advance offset for subregs
+ containing hard regs.
+ (find_reload_toplev): Use SUBREG_BYTE. Remove byte endian
+ corrections when fixing up MEM subregs.
+ (find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and
+ subreg_regno_offset where appropriate.
+ (find_reloads_subreg_address): Use SUBREG_BYTE. Remove
+ byte endian corrections when fixing up MEM subregs.
+ (subst_reloads): When combining two subregs, make sure final
+ offset is congruent to subreg's mode size.
+ (find_replacement): Use SUBREG_BYTE and subreg_regno_offset.
+ (refers_to_regno_for_reload_p): Use subreg_regno.
+ (reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset.
+ * reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian
+ correction code for memory subreg fixups.
+ (forget_old_reload_1): Use subreg_regno_offset.
+ (choose_reload_regs): Use subreg_regno.
+ (emit_input_reload_insns): Use SUBREG_BYTE.
+ (reload_combine_note_store): Use subreg_regno_offset.
+ (move2add_note_store): Use subreg_regno_offset.
+ * resource.c (update_live_status, mark_referenced_resources): Use
+ subreg_regno function.
+ (mark_set_resources): Use subreg_regno function.
+ * rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE.
+ (subreg_regno_offset, subreg_regno): Define prototypes.
+ (subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions.
+ (gen_lowpart_SUBREG): Add prototype.
+ * rtl.texi (subreg): Update to reflect new byte offset representation.
+ Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now.
+ * rtlanal.c (refers_to_regno_p): Use subreg_regno.
+ (reg_overlap_mentioned_p): Use subreg_regno.
+ (replace_regs); Make sure final offset of combined subreg is
+ congruent to size of subreg's mode.
+ (subreg_regno_offset): New function.
+ (subreg_regno): New function.
+ * sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE.
+ * sdbout.c (sdbout_symbol): Compute offset using alter_subreg.
+ * stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG.
+ * tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead.
+ (SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides.
+ * config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno.
+ (a29k_get_reloaded_address): Use SUBREG_BYTE.
+ (print_operand): Use SUBREG_BYTE.
+ * config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE.
+ * config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE.
+ (arm_reload_out_hi): Use SUBREG_BYTE.
+ * config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset
+ instead of SUBREG_WORD.
+ (d30v_print_operand_memory_reference): Use subreg_regno_offset.
+ * config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix
+ SUBREG creation to use byte offset.
+ * config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit
+ inverted load insns): Fix explicit rtl subregs to use byte
+ offsets.
+ * config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3,
+ udivsi3, umodsi3): Generate SUBREGs with byte offsets.
+ * config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE.
+ * config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl
+ to use byte offsets.
+ (unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets.
+ * config/i960/i960.md (extendhisi2): Generate SUBREGs with byte
+ offsets, also make sure it is congruent to SUBREG's mode size.
+ (extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2,
+ unnamed ldob insn): Generate SUBREGs with byte offset.
+ (zero_extendqihi2): SUBREG's are byte offsets.
+ * config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE.
+ (m68hc11_gen_highpart): Use SUBREG_BYTE.
+ * config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2,
+ zero-extendqisi2): Generate SUBREGs with byte offset.
+ (umulsidi3, mulsidi3, subreghi1ashrdi_const32,
+ subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit
+ subregs in rtl to use byte offsets.
+ * config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset.
+ * config/mips/mips.c (mips_move_1word): Use subreg_regno_offset.
+ (mips_move_2words): Use subreg_regno_offset.
+ (mips_secondary_reload_class): Use subreg_regno_offset.
+ * config/mips/mips.md (DImode plus, minus, move, and logical op
+ splits): Fixup explicit subregs in rtl to use byte offsets.
+ * config/mn10200/mn10200.c (print_operand): Use subreg_regno function.
+ * config/mn10300/mn10300.c (print_operand): Use subreg_regno function.
+ * config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in
+ rtl to use byte offsets.
+ * config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE.
+ * config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit
+ subregs to use byte offsets.
+ * config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1):
+ Fixup explicit subregs in rtl to use byte offsets.
+ * config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE
+ and remove byte endian correction code.
+ * config/sh/sh.c (output_movedouble): Use subreg_regno.
+ (gen_ashift_hi): Use SUBREG_BYTE.
+ (regs_used): Use subreg_regno_offset.
+ (machine_dependent_reorg): Use subreg_regno_offset.
+ * config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE.
+ * config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno.
+ (movdf_i4): Subregs are byte offsets now.
+ * config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE.
+ * config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed.
+ (REGMODE_NATURAL_SIZE): Override.
+ (REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode.
+ * config/sparc/sparc.md (TFmode move splits): Generate SUBREGs
+ with byte offsets.
+ (zero_extendhisi2, zero_extendqidi2_insn, extendhisi2,
+ extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn,
+ extendqidi2): Generate SUBREGs with byte offsets, also make sure
+ it is congruent to SUBREG's mode size.
+ (smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte
+ offsets.
+ (cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc,
+ cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2,
+ lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper
+ SUBREG_BYTE offset for non-paradoxical subregs in patterns.
+ * config/v850/v850.c (print_operand, output_move_double): Use
+ subreg_regno function.
+
2001-04-03 Alexandre Oliva <aoliva@redhat.com>
* configure.in (target_subdir): Use target_alias, not target.
diff --git a/gcc/alias.c b/gcc/alias.c
index a1f2e0b785c..d69b38392fe 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1880,7 +1880,7 @@ nonlocal_mentioned_p (x)
{
/* Global registers are not local. */
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
- && global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)])
+ && global_regs[subreg_regno (x)])
return 1;
return 0;
}
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 787d45c818e..602159d5eb0 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -487,18 +487,21 @@ mark_set_regs (reg, setter, data)
{
register int regno, endregno, i;
enum machine_mode mode = GET_MODE (reg);
- int word = 0;
if (GET_CODE (reg) == SUBREG)
{
- word = SUBREG_WORD (reg);
- reg = SUBREG_REG (reg);
- }
+ rtx inner = SUBREG_REG (reg);
+ if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
+ return;
- if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+ regno = subreg_hard_regno (reg, 1);
+ }
+ else if (GET_CODE (reg) == REG
+ && REGNO (reg) < FIRST_PSEUDO_REGISTER)
+ regno = REGNO (reg);
+ else
return;
- regno = REGNO (reg) + word;
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)
@@ -517,21 +520,24 @@ add_stored_regs (reg, setter, data)
{
register int regno, endregno, i;
enum machine_mode mode = GET_MODE (reg);
- int word = 0;
+ int offset = 0;
if (GET_CODE (setter) == CLOBBER)
return;
- while (GET_CODE (reg) == SUBREG)
+ if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
{
- word += SUBREG_WORD (reg);
+ offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
+ GET_MODE (SUBREG_REG (reg)),
+ SUBREG_BYTE (reg),
+ GET_MODE (reg));
reg = SUBREG_REG (reg);
}
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
return;
- regno = REGNO (reg) + word;
+ regno = REGNO (reg) + offset;
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)
diff --git a/gcc/calls.c b/gcc/calls.c
index 228d9b8e112..694eeeee4e6 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1462,6 +1462,8 @@ precompute_arguments (flags, num_actuals, args)
if ((flags & (ECF_CONST | ECF_PURE))
|| calls_function (args[i].tree_value, !ACCUMULATE_OUTGOING_ARGS))
{
+ enum machine_mode mode;
+
/* If this is an addressable type, we cannot pre-evaluate it. */
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
abort ();
@@ -1481,11 +1483,11 @@ precompute_arguments (flags, num_actuals, args)
args[i].initial_value = args[i].value
= protect_from_queue (args[i].value, 0);
- if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
+ mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
+ if (mode != args[i].mode)
{
args[i].value
- = convert_modes (args[i].mode,
- TYPE_MODE (TREE_TYPE (args[i].tree_value)),
+ = convert_modes (args[i].mode, mode,
args[i].value, args[i].unsignedp);
#ifdef PROMOTE_FOR_CALL_ONLY
/* CSE will replace this only if it contains args[i].value
@@ -1495,8 +1497,7 @@ precompute_arguments (flags, num_actuals, args)
&& GET_MODE_CLASS (args[i].mode) == MODE_INT)
{
args[i].initial_value
- = gen_rtx_SUBREG (TYPE_MODE (TREE_TYPE (args[i].tree_value)),
- args[i].value, 0);
+ = gen_lowpart_SUBREG (mode, args[i].value);
SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
= args[i].unsignedp;
@@ -3272,13 +3273,25 @@ expand_call (exp, target, ignore)
{
tree type = TREE_TYPE (exp);
int unsignedp = TREE_UNSIGNED (type);
+ int offset = 0;
/* If we don't promote as expected, something is wrong. */
if (GET_MODE (target)
!= promote_mode (type, TYPE_MODE (type), &unsignedp, 1))
abort ();
- target = gen_rtx_SUBREG (TYPE_MODE (type), target, 0);
+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+ && GET_MODE_SIZE (GET_MODE (target))
+ > GET_MODE_SIZE (TYPE_MODE (type)))
+ {
+ offset = GET_MODE_SIZE (GET_MODE (target))
+ - GET_MODE_SIZE (TYPE_MODE (type));
+ if (! BYTES_BIG_ENDIAN)
+ offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+ else if (! WORDS_BIG_ENDIAN)
+ offset %= UNITS_PER_WORD;
+ }
+ target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
SUBREG_PROMOTED_VAR_P (target) = 1;
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
}
diff --git a/gcc/combine.c b/gcc/combine.c
index 4aa7721e880..ee5631c8263 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2249,7 +2249,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
be written as a ZERO_EXTEND. */
if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
- XEXP (*split, 0)));
+ SUBREG_REG (*split)));
#endif
newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
@@ -3773,27 +3773,17 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
rtx inner = SUBREG_REG (x);
- int endian_offset = 0;
+ int offset = SUBREG_BYTE (x);
/* Don't change the mode of the MEM
if that would change the meaning of the address. */
if (MEM_VOLATILE_P (SUBREG_REG (x))
|| mode_dependent_address_p (XEXP (inner, 0)))
return gen_rtx_CLOBBER (mode, const0_rtx);
- if (BYTES_BIG_ENDIAN)
- {
- if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
- endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (mode);
- if (GET_MODE_SIZE (GET_MODE (inner)) < UNITS_PER_WORD)
- endian_offset -= (UNITS_PER_WORD
- - GET_MODE_SIZE (GET_MODE (inner)));
- }
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
x = gen_rtx_MEM (mode,
- plus_constant (XEXP (inner, 0),
- (SUBREG_WORD (x) * UNITS_PER_WORD
- + endian_offset)));
+ plus_constant (XEXP (inner, 0), offset));
MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
@@ -3806,12 +3796,58 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
or not at all if changing back to starting mode. */
if (GET_CODE (SUBREG_REG (x)) == SUBREG)
{
- if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x)))
- && SUBREG_WORD (x) == 0 && SUBREG_WORD (SUBREG_REG (x)) == 0)
- return SUBREG_REG (SUBREG_REG (x));
+ int final_offset;
+ enum machine_mode outer_mode, inner_mode;
+
+ /* If the innermost mode is the same as the goal mode,
+ and the low word is being referenced in both SUBREGs,
+ return the innermost element. */
+ if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x))))
+ {
+ int inner_word = SUBREG_BYTE (SUBREG_REG (x));
+ int outer_word = SUBREG_BYTE (x);
+
+ inner_word = (inner_word / UNITS_PER_WORD) * UNITS_PER_WORD;
+ outer_word = (outer_word / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (inner_word == 0
+ && outer_word == 0)
+ return SUBREG_REG (SUBREG_REG (x));
+ }
+
+ outer_mode = GET_MODE (SUBREG_REG (x));
+ inner_mode = GET_MODE (SUBREG_REG (SUBREG_REG (x)));
+ final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (SUBREG_REG(x));
+
+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+ && GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (mode)
+ && GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (inner_mode))
+ {
+ /* Inner SUBREG is paradoxical, outer is not. On big endian
+ we have to special case this. */
+ if (SUBREG_BYTE (SUBREG_REG (x)))
+ abort(); /* Can a paradoxical subreg have nonzero offset? */
+ if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
+ final_offset = SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ + GET_MODE_SIZE (inner_mode);
+ else if (WORDS_BIG_ENDIAN)
+ final_offset = (final_offset % UNITS_PER_WORD)
+ + ((SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ + GET_MODE_SIZE (inner_mode))
+ * UNITS_PER_WORD) / UNITS_PER_WORD;
+ else
+ final_offset = ((final_offset * UNITS_PER_WORD)
+ / UNITS_PER_WORD)
+ + ((SUBREG_BYTE (x) - GET_MODE_SIZE (outer_mode)
+ + GET_MODE_SIZE (inner_mode))
+ % UNITS_PER_WORD);
+ }
- SUBST_INT (SUBREG_WORD (x),
- SUBREG_WORD (x) + SUBREG_WORD (SUBREG_REG (x)));
+ /* The SUBREG rules are that the byte offset must be
+ some multiple of the toplevel SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (mode));
+ final_offset = (final_offset * GET_MODE_SIZE (mode));
+
+ SUBST_INT (SUBREG_BYTE (x), final_offset);
SUBST (SUBREG_REG (x), SUBREG_REG (SUBREG_REG (x)));
}
@@ -3831,10 +3867,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
#endif
&& REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM)
{
- if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x),
- mode))
- return gen_rtx_REG (mode,
- REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+ int final_regno = subreg_hard_regno (x, 0);
+
+ if (HARD_REGNO_MODE_OK (final_regno, mode))
+ return gen_rtx_REG (mode, final_regno);
else
return gen_rtx_CLOBBER (mode, const0_rtx);
}
@@ -3849,7 +3885,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
&& GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_INT)
{
- temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x),
+ temp = operand_subword (SUBREG_REG (x),
+ (SUBREG_BYTE (x) / UNITS_PER_WORD),
0, op0_mode);
if (temp)
return temp;
@@ -3863,11 +3900,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (CONSTANT_P (SUBREG_REG (x))
&& ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
|| ! WORDS_BIG_ENDIAN)
- ? SUBREG_WORD (x) == 0
- : (SUBREG_WORD (x)
- == ((GET_MODE_SIZE (op0_mode)
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD)))
+ ? SUBREG_BYTE (x) == 0
+ : (SUBREG_BYTE (x)
+ == (GET_MODE_SIZE (op0_mode) - GET_MODE_SIZE (mode))))
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
&& (! WORDS_BIG_ENDIAN
|| GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
@@ -3879,8 +3914,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (op0_mode))
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
- && (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
- return operand_subword (SUBREG_REG (x), SUBREG_WORD (x), 0, mode);
+ && (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) != 0))
+ return constant_subword (SUBREG_REG (x),
+ SUBREG_BYTE (x) / UNITS_PER_WORD, mode);
return SUBREG_REG (x);
}
@@ -5157,14 +5193,14 @@ simplify_set (x)
if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL
- && SUBREG_WORD (src) == 0
+ && SUBREG_BYTE (src) == 0
&& (GET_MODE_SIZE (GET_MODE (src))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
&& GET_CODE (SUBREG_REG (src)) == MEM)
{
SUBST (SET_SRC (x),
gen_rtx (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
- GET_MODE (src), XEXP (src, 0)));
+ GET_MODE (src), SUBREG_REG (src)));
src = SET_SRC (x);
}
@@ -5756,9 +5792,11 @@ expand_field_assignment (x)
if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
&& GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
{
+ int byte_offset = SUBREG_BYTE (XEXP (SET_DEST (x), 0));
+
inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)));
- pos = GEN_INT (BITS_PER_WORD * SUBREG_WORD (XEXP (SET_DEST (x), 0)));
+ pos = GEN_INT (BITS_PER_WORD * (byte_offset / UNITS_PER_WORD));
}
else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
&& GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
@@ -5996,18 +6034,26 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* We can't call gen_lowpart_for_combine here since we always want
a SUBREG and it would sometimes return a new hard register. */
if (tmode != inner_mode)
- new = gen_rtx_SUBREG (tmode, inner,
- (WORDS_BIG_ENDIAN
- && (GET_MODE_SIZE (inner_mode)
- > UNITS_PER_WORD)
- ? (((GET_MODE_SIZE (inner_mode)
- - GET_MODE_SIZE (tmode))
- / UNITS_PER_WORD)
- - pos / BITS_PER_WORD)
- : pos / BITS_PER_WORD));
- else
- new = inner;
- }
+ {
+ int final_word = pos / BITS_PER_WORD;
+
+ if (WORDS_BIG_ENDIAN
+ && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
+ final_word = ((GET_MODE_SIZE (inner_mode)
+ - GET_MODE_SIZE (tmode))
+ / UNITS_PER_WORD) - final_word;
+
+ final_word *= UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN &&
+ GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (tmode))
+ final_word += (GET_MODE_SIZE (inner_mode)
+ - GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
+
+ new = gen_rtx_SUBREG (tmode, inner, final_word);
+ }
+ else
+ new = inner;
+ }
else
new = force_to_mode (inner, tmode,
len >= HOST_BITS_PER_WIDE_INT
@@ -7395,11 +7441,11 @@ if_then_else_cond (x, ptrue, pfalse)
|| GET_CODE (SUBREG_REG (x)) == MEM
|| CONSTANT_P (SUBREG_REG (x)))
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
- && (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
+ && (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) >= UNITS_PER_WORD))
{
- true0 = operand_subword (true0, SUBREG_WORD (x), 0,
+ true0 = operand_subword (true0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
- false0 = operand_subword (false0, SUBREG_WORD (x), 0,
+ false0 = operand_subword (false0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
}
*ptrue = force_to_mode (true0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
@@ -7772,7 +7818,7 @@ apply_distributive_law (x)
case SUBREG:
/* Non-paradoxical SUBREGs distributes over all operations, provided
- the inner modes and word numbers are the same, this is an extraction
+ the inner modes and byte offsets are the same, this is an extraction
of a low-order part, we don't convert an fp operation to int or
vice versa, and we would not be converting a single-word
operation into a multi-word operation. The latter test is not
@@ -7783,7 +7829,7 @@ apply_distributive_law (x)
We produce the result slightly differently in this case. */
if (GET_MODE (SUBREG_REG (lhs)) != GET_MODE (SUBREG_REG (rhs))
- || SUBREG_WORD (lhs) != SUBREG_WORD (rhs)
+ || SUBREG_BYTE (lhs) != SUBREG_BYTE (rhs)
|| ! subreg_lowpart_p (lhs)
|| (GET_MODE_CLASS (GET_MODE (lhs))
!= GET_MODE_CLASS (GET_MODE (SUBREG_REG (lhs))))
@@ -9853,13 +9899,19 @@ gen_lowpart_for_combine (mode, x)
include an explicit SUBREG or we may simplify it further in combine. */
else
{
- int word = 0;
+ int offset = 0;
- if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
- word = ((GET_MODE_SIZE (GET_MODE (x))
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD);
- return gen_rtx_SUBREG (mode, x, word);
+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+ && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode))
+ {
+ int difference = (GET_MODE_SIZE (GET_MODE (x))
+ - GET_MODE_SIZE (mode));
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
+ return gen_rtx_SUBREG (mode, x, offset);
}
}
@@ -11927,6 +11979,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
that accesses one word of a multi-word item, some
piece of everything register in the expression is used by
this insn, so remove any old death. */
+ /* ??? So why do we test for equality of the sizes? */
if (GET_CODE (dest) == ZERO_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART
diff --git a/gcc/config/a29k/a29k.c b/gcc/config/a29k/a29k.c
index c6d7ba28e4a..65c6240a3bc 100644
--- a/gcc/config/a29k/a29k.c
+++ b/gcc/config/a29k/a29k.c
@@ -262,9 +262,10 @@ gpc_reg_operand (op, mode)
regno = REGNO (op);
else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
{
- regno = REGNO (SUBREG_REG (op));
- if (regno < FIRST_PSEUDO_REGISTER)
- regno += SUBREG_WORD (op);
+ if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
+ regno = subreg_regno (op);
+ else
+ regno = REGNO (SUBREG_REG (op));
}
else
return 0;
@@ -467,7 +468,7 @@ a29k_get_reloaded_address (op)
{
if (GET_CODE (op) == SUBREG)
{
- if (SUBREG_WORD (op) != 0)
+ if (SUBREG_BYTE (op) != 0)
abort ();
op = SUBREG_REG (op);
@@ -1187,7 +1188,8 @@ print_operand (file, x, code)
if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
fprintf (file, "$float");
else
- fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0)));
+ fprintf (file, "$double%d",
+ (SUBREG_BYTE (XEXP (x, 0)) / GET_MODE_SIZE (GET_MODE (x))));
memcpy ((char *) &u,
(char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), sizeof u);
fprintf (file, "(%.20e)", u.d);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 18a61d6c7f6..c6aa2eec7fa 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -4098,7 +4098,8 @@ print_operand_address (file, addr)
basereg = REGNO (addr);
else if (GET_CODE (addr) == SUBREG
&& GET_CODE (SUBREG_REG (addr)) == REG)
- basereg = REGNO (SUBREG_REG (addr)) + SUBREG_WORD (addr);
+ basereg = REGNO (SUBREG_REG (addr))
+ + SUBREG_BYTE (addr) / GET_MODE_SIZE (GET_MODE (addr));
else if (GET_CODE (addr) == CONST_INT)
offset = INTVAL (addr);
else
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 0f0c5e9d9a3..b89392efad2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4748,11 +4748,7 @@ arm_reload_in_hi (operands)
if (GET_CODE (ref) == SUBREG)
{
- offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- - MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
+ offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
}
@@ -4865,11 +4861,7 @@ arm_reload_out_hi (operands)
if (GET_CODE (ref) == SUBREG)
{
- offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- - MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
+ offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
}
diff --git a/gcc/config/d30v/d30v.c b/gcc/config/d30v/d30v.c
index a4f5e8d8473..b8f30aa7c5f 100644
--- a/gcc/config/d30v/d30v.c
+++ b/gcc/config/d30v/d30v.c
@@ -2667,10 +2667,13 @@ d30v_split_double (value, p_high, p_low)
switch (GET_CODE (value))
{
case SUBREG:
- offset = SUBREG_WORD (value);
- value = SUBREG_REG (value);
- if (GET_CODE (value) != REG)
+ if (GET_CODE (SUBREG_REG (value)) != REG)
abort ();
+ offset = subreg_regno_offset (REGNO (SUBREG_REG (value)),
+ GET_MODE (SUBREG_REG (value)),
+ SUBREG_BYTE (value),
+ GET_MODE (value));
+ value = SUBREG_REG (value);
/* fall through */
@@ -2795,7 +2798,10 @@ d30v_print_operand_memory_reference (stream, x)
if (GET_CODE (x0) == SUBREG)
{
- offset0 = SUBREG_WORD (x0);
+ offset0 = subreg_regno_offset (REGNO (SUBREG_REG (x0)),
+ GET_MODE (SUBREG_REG (x0)),
+ SUBREG_BYTE (x0),
+ GET_MODE (x0));
x0 = SUBREG_REG (x0);
}
@@ -2828,7 +2834,10 @@ d30v_print_operand_memory_reference (stream, x)
switch (GET_CODE (x1))
{
case SUBREG:
- offset1 = SUBREG_WORD (x1);
+ offset1 = subreg_regno_offset (REGNO (SUBREG_REG (x1)),
+ GET_MODE (SUBREG_REG (x1)),
+ SUBREG_BYTE (x1),
+ GET_MODE (x1));
x1 = SUBREG_REG (x1);
if (GET_CODE (x1) != REG)
fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x);
diff --git a/gcc/config/dsp16xx/dsp16xx.md b/gcc/config/dsp16xx/dsp16xx.md
index ce7fb96b850..4c65a89bfbe 100644
--- a/gcc/config/dsp16xx/dsp16xx.md
+++ b/gcc/config/dsp16xx/dsp16xx.md
@@ -1258,7 +1258,7 @@
"
{
operands[2] = gen_reg_rtx (HImode);
- operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
+ operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
}")
;;(define_insn "extendqihi2"
@@ -1308,7 +1308,7 @@
"
{
operands[2] = gen_reg_rtx (HImode);
- operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
+ operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
}")
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index 2ea2463f91b..d79750aeb23 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -1925,7 +1925,7 @@
(subreg:HI (zero_extract:SI
(match_operand:HI 1 "register_operand" "r")
(const_int 1)
- (match_operand:HI 2 "immediate_operand" "n")) 1))]
+ (match_operand:HI 2 "immediate_operand" "n")) 2))]
""
"sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0"
[(set_attr "cc" "clobber")
@@ -1966,7 +1966,7 @@
(subreg:HI
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "Ur")
- (match_operand:SI 2 "const_int_operand" "n")) 1))
+ (match_operand:SI 2 "const_int_operand" "n")) 2))
(const_int 1)))]
"INTVAL (operands[2]) < 16"
"sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
diff --git a/gcc/config/i370/i370.md b/gcc/config/i370/i370.md
index 614e3d6fb6b..5de8931d21b 100644
--- a/gcc/config/i370/i370.md
+++ b/gcc/config/i370/i370.md
@@ -537,12 +537,12 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
force_operand (XEXP (mem2, 0), NULL_RTX));
- emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), len);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);
/* Compare! */
emit_insn (gen_cmpstrsi_1 (result, reg1, reg2));
@@ -1409,11 +1409,11 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), zippo);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), zippo);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), zippo);
/* Copy! */
emit_insn (gen_movstrsi_1 (reg1, reg2));
@@ -1476,12 +1476,12 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
force_operand (XEXP (mem2, 0), NULL_RTX));
- emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), len);
+ emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);
/* Copy! */
emit_insn (gen_movstrsi_1 (reg1, reg2));
@@ -2425,11 +2425,12 @@ check_label_emit ();
* Dunno how to untwist it elegantly; but it seems to work for now.
*/
emit_insn (gen_rtx_SET (VOIDmode,
- gen_rtx_SUBREG (SImode, r, 1), operands[1]));
+ gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)),
+ operands[1]));
emit_insn (gen_rtx_SET (VOIDmode, r,
gen_rtx_MULT (DImode, r, operands[2])));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SUBREG (SImode, r, 1)));
+ gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode))));
}
DONE;
}")
@@ -2534,7 +2535,7 @@ check_label_emit ();
emit_insn (gen_rtx_SET (VOIDmode, r,
gen_rtx_DIV (DImode, r, operands[2])));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SUBREG (SImode, r, 1)));
+ gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode))));
DONE;
}")
@@ -2552,7 +2553,7 @@ check_label_emit ();
{
rtx dr = gen_reg_rtx (DImode);
rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0);
- rtx dr_1 = gen_rtx_SUBREG (SImode, dr, 1);
+ rtx dr_1 = gen_rtx_SUBREG (SImode, dr, GET_MODE_SIZE (SImode));
if (GET_CODE (operands[2]) == CONST_INT)
diff --git a/gcc/config/i860/i860.c b/gcc/config/i860/i860.c
index 7cc9d51e22e..4789f70fe00 100644
--- a/gcc/config/i860/i860.c
+++ b/gcc/config/i860/i860.c
@@ -340,7 +340,7 @@ single_insn_src_p (op, mode)
return 1;
case SUBREG:
- if (SUBREG_WORD (op) != 0)
+ if (SUBREG_BYTE (op) != 0)
return 0;
return single_insn_src_p (SUBREG_REG (op), mode);
diff --git a/gcc/config/i860/i860.md b/gcc/config/i860/i860.md
index 8cc1fd883f7..5778964f5be 100644
--- a/gcc/config/i860/i860.md
+++ b/gcc/config/i860/i860.md
@@ -1730,12 +1730,12 @@
}")
(define_expand "mulsi3_big"
- [(set (subreg:SI (match_dup 4) 1) (match_operand:SI 1 "general_operand" ""))
- (set (subreg:SI (match_dup 5) 1) (match_operand:SI 2 "general_operand" ""))
+ [(set (subreg:SI (match_dup 4) 4) (match_operand:SI 1 "general_operand" ""))
+ (set (subreg:SI (match_dup 5) 4) (match_operand:SI 2 "general_operand" ""))
(clobber (match_dup 3))
- (set (subreg:SI (match_dup 3) 1)
- (mult:SI (subreg:SI (match_dup 4) 1) (subreg:SI (match_dup 5) 1)))
- (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 1))]
+ (set (subreg:SI (match_dup 3) 4)
+ (mult:SI (subreg:SI (match_dup 4) 4) (subreg:SI (match_dup 5) 4)))
+ (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 4))]
"WORDS_BIG_ENDIAN"
"
{
@@ -1752,9 +1752,9 @@
"fmlow.dd %2,%1,%0")
(define_insn ""
- [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 1)
- (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 1)
- (subreg:SI (match_operand:DI 2 "register_operand" "f") 1)))]
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 4)
+ (mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 4)
+ (subreg:SI (match_operand:DI 2 "register_operand" "f") 4)))]
"WORDS_BIG_ENDIAN"
"fmlow.dd %2,%1,%0")
diff --git a/gcc/config/i960/i960.md b/gcc/config/i960/i960.md
index b7680e10361..424fb87056e 100644
--- a/gcc/config/i960/i960.md
+++ b/gcc/config/i960/i960.md
@@ -1211,15 +1211,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subreg_word = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
+ op1_subreg_byte /= GET_MODE_SIZE (SImode);
+ op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
@@ -1246,15 +1248,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subreg_word = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
+ op1_subreg_byte /= GET_MODE_SIZE (SImode);
+ op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
@@ -1282,24 +1286,28 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op0_subreg_word = 0;
- int op1_subreg_word = 0;
+ int op0_subreg_byte = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
+ op1_subreg_byte /= GET_MODE_SIZE (SImode);
+ op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
if (GET_CODE (operand0) == SUBREG)
{
- op0_subreg_word = SUBREG_WORD (operand0);
+ op0_subreg_byte = SUBREG_BYTE (operand0);
+ op0_subreg_byte /= GET_MODE_SIZE (SImode);
+ op0_subreg_byte *= GET_MODE_SIZE (SImode);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
- operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
+ operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
@@ -1327,15 +1335,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subreg_word = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
+ op1_subreg_byte /= GET_MODE_SIZE (SImode);
+ op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
@@ -1367,15 +1377,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subreg_word = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
- operand1 = SUBREG_REG (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
+ op1_subreg_byte /= GET_MODE_SIZE (SImode);
+ op1_subreg_byte *= GET_MODE_SIZE (SImode);
+ operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
@@ -1403,24 +1415,24 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op0_subreg_word = 0;
- int op1_subreg_word = 0;
+ int op0_subreg_byte = 0;
+ int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subreg_word = SUBREG_WORD (operand1);
+ op1_subreg_byte = SUBREG_BYTE (operand1);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
- operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
+ operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
if (GET_CODE (operand0) == SUBREG)
{
- op0_subreg_word = SUBREG_WORD (operand0);
+ op0_subreg_byte = SUBREG_BYTE (operand0);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
- operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
+ operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index b1cf541b4c2..0075c39abc6 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -1739,12 +1739,12 @@ m68hc11_gen_lowpart (mode, x)
return gen_rtx (REG, mode, HARD_B_REGNUM);
/* gen_lowpart crashes when it is called with a SUBREG. */
- if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
+ if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
{
if (mode == SImode)
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 2);
+ return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
else if (mode == HImode)
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 1);
+ return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 1);
else
abort ();
}
@@ -1844,7 +1844,7 @@ m68hc11_gen_highpart (mode, x)
}
/* gen_highpart crashes when it is called with a SUBREG. */
- if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
+ if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
{
return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));
}
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 1eff7f43723..c74b1424e57 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -1554,7 +1554,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (HImode, SUBREG_REG (operands[0]),
- SUBREG_WORD (operands[0]));
+ SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
}")
@@ -1570,7 +1570,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
- SUBREG_WORD (operands[0]));
+ SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
}")
@@ -1586,7 +1586,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
- SUBREG_WORD (operands[0]));
+ SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
}")
@@ -3096,7 +3096,7 @@
;; the high-numbered word of the DImode operand[0] and operand[1].
(define_expand "umulsidi3"
[(parallel
- [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
(mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (subreg:SI (match_dup 0) 0)
@@ -3135,7 +3135,7 @@
(define_expand "mulsidi3"
[(parallel
- [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
(mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (subreg:SI (match_dup 0) 0)
@@ -4731,7 +4731,7 @@
(define_insn "subreghi1ashrdi_const32"
[(set (match_operand:HI 0 "general_operand" "=rm")
(subreg:HI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
- (const_int 32)) 1))]
+ (const_int 32)) 4))]
""
"*
{
@@ -4743,7 +4743,7 @@
(define_insn "subregsi1ashrdi_const32"
[(set (match_operand:SI 0 "general_operand" "=rm")
(subreg:SI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
- (const_int 32)) 1))]
+ (const_int 32)) 4))]
""
"*
{
@@ -4894,10 +4894,10 @@
;;(define_insn ""
;; [(set (cc0)
;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
-;; (const_int 32)) 1))
+;; (const_int 32)) 4))
;; (set (match_operand:SI 1 "general_operand" "=dm")
;; (subreg:SI (lshiftrt:DI (match_dup 0)
-;; (const_int 32)) 1))]
+;; (const_int 32)) 4))]
;; ""
;; "*
;;{
@@ -4924,7 +4924,7 @@
(define_insn "subreg1lshrdi_const32"
[(set (match_operand:SI 0 "general_operand" "=rm")
(subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
- (const_int 32)) 1))]
+ (const_int 32)) 4))]
""
"*
{
diff --git a/gcc/config/m88k/m88k.md b/gcc/config/m88k/m88k.md
index d8e7a738bcf..7a1ac64ed18 100644
--- a/gcc/config/m88k/m88k.md
+++ b/gcc/config/m88k/m88k.md
@@ -2295,10 +2295,10 @@
;;- sign extension instructions
(define_expand "extendsidi2"
- [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1)
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 4)
(match_operand:SI 1 "general_operand" "g"))
(set (subreg:SI (match_dup 0) 0)
- (ashiftrt:SI (subreg:SI (match_dup 0) 1)
+ (ashiftrt:SI (subreg:SI (match_dup 0) 4)
(const_int 31)))]
""
"")
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index e33cb9b65a3..aeccb3fae20 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -1833,20 +1833,26 @@ mips_move_1word (operands, insn, unsignedp)
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
enum machine_mode mode = GET_MODE (op0);
- int subreg_word0 = 0;
- int subreg_word1 = 0;
+ int subreg_offset0 = 0;
+ int subreg_offset1 = 0;
enum delay_type delay = DELAY_NONE;
while (code0 == SUBREG)
{
- subreg_word0 += SUBREG_WORD (op0);
+ subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
+ GET_MODE (SUBREG_REG (op0)),
+ SUBREG_BYTE (op0),
+ GET_MODE (op0));
op0 = SUBREG_REG (op0);
code0 = GET_CODE (op0);
}
while (code1 == SUBREG)
{
- subreg_word1 += SUBREG_WORD (op1);
+ subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
+ GET_MODE (SUBREG_REG (op1)),
+ SUBREG_BYTE (op1),
+ GET_MODE (op1));
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
}
@@ -1857,11 +1863,11 @@ mips_move_1word (operands, insn, unsignedp)
if (code0 == REG)
{
- int regno0 = REGNO (op0) + subreg_word0;
+ int regno0 = REGNO (op0) + subreg_offset0;
if (code1 == REG)
{
- int regno1 = REGNO (op1) + subreg_word1;
+ int regno1 = REGNO (op1) + subreg_offset1;
/* Just in case, don't do anything for assigning a register
to itself, unless we are filling a delay slot. */
@@ -2146,7 +2152,7 @@ mips_move_1word (operands, insn, unsignedp)
if (code1 == REG)
{
- int regno1 = REGNO (op1) + subreg_word1;
+ int regno1 = REGNO (op1) + subreg_offset1;
if (GP_REG_P (regno1))
{
@@ -2225,13 +2231,16 @@ mips_move_2words (operands, insn)
rtx op1 = operands[1];
enum rtx_code code0 = GET_CODE (operands[0]);
enum rtx_code code1 = GET_CODE (operands[1]);
- int subreg_word0 = 0;
- int subreg_word1 = 0;
+ int subreg_offset0 = 0;
+ int subreg_offset1 = 0;
enum delay_type delay = DELAY_NONE;
while (code0 == SUBREG)
{
- subreg_word0 += SUBREG_WORD (op0);
+ subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
+ GET_MODE (SUBREG_REG (op0)),
+ SUBREG_BYTE (op0),
+ GET_MODE (op0));
op0 = SUBREG_REG (op0);
code0 = GET_CODE (op0);
}
@@ -2244,7 +2253,10 @@ mips_move_2words (operands, insn)
while (code1 == SUBREG)
{
- subreg_word1 += SUBREG_WORD (op1);
+ subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
+ GET_MODE (SUBREG_REG (op1)),
+ SUBREG_BYTE (op1),
+ GET_MODE (op1));
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
}
@@ -2262,11 +2274,11 @@ mips_move_2words (operands, insn)
if (code0 == REG)
{
- int regno0 = REGNO (op0) + subreg_word0;
+ int regno0 = REGNO (op0) + subreg_offset0;
if (code1 == REG)
{
- int regno1 = REGNO (op1) + subreg_word1;
+ int regno1 = REGNO (op1) + subreg_offset1;
/* Just in case, don't do anything for assigning a register
to itself, unless we are filling a delay slot. */
@@ -2603,7 +2615,7 @@ mips_move_2words (operands, insn)
{
if (code1 == REG)
{
- int regno1 = REGNO (op1) + subreg_word1;
+ int regno1 = REGNO (op1) + subreg_offset1;
if (FP_REG_P (regno1))
ret = "s.d\t%1,%0";
@@ -7888,7 +7900,10 @@ mips_secondary_reload_class (class, mode, x, in_p)
{
while (GET_CODE (x) == SUBREG)
{
- off += SUBREG_WORD (x);
+ off += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x));
x = SUBREG_REG (x);
}
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index ceb4f6a2b11..d7c421327d6 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -790,12 +790,12 @@
(ltu:SI (subreg:SI (match_dup 0) 0)
(subreg:SI (match_dup 2) 0)))
- (set (subreg:SI (match_dup 0) 1)
- (plus:SI (subreg:SI (match_dup 1) 1)
- (subreg:SI (match_dup 2) 1)))
+ (set (subreg:SI (match_dup 0) 4)
+ (plus:SI (subreg:SI (match_dup 1) 4)
+ (subreg:SI (match_dup 2) 4)))
- (set (subreg:SI (match_dup 0) 1)
- (plus:SI (subreg:SI (match_dup 0) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (plus:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))]
"")
@@ -812,13 +812,13 @@
&& (REGNO (operands[0]) != REGNO (operands[1])
|| REGNO (operands[0]) != REGNO (operands[2]))"
- [(set (subreg:SI (match_dup 0) 1)
- (plus:SI (subreg:SI (match_dup 1) 1)
- (subreg:SI (match_dup 2) 1)))
+ [(set (subreg:SI (match_dup 0) 4)
+ (plus:SI (subreg:SI (match_dup 1) 4)
+ (subreg:SI (match_dup 2) 4)))
(set (match_dup 3)
- (ltu:SI (subreg:SI (match_dup 0) 1)
- (subreg:SI (match_dup 2) 1)))
+ (ltu:SI (subreg:SI (match_dup 0) 4)
+ (subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 0)
(plus:SI (subreg:SI (match_dup 1) 0)
@@ -865,8 +865,8 @@
(ltu:SI (subreg:SI (match_dup 0) 0)
(match_dup 2)))
- (set (subreg:SI (match_dup 0) 1)
- (plus:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (plus:SI (subreg:SI (match_dup 1) 4)
(match_dup 3)))]
"")
@@ -881,12 +881,12 @@
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
&& INTVAL (operands[2]) > 0"
- [(set (subreg:SI (match_dup 0) 1)
- (plus:SI (subreg:SI (match_dup 1) 1)
+ [(set (subreg:SI (match_dup 0) 4)
+ (plus:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
- (ltu:SI (subreg:SI (match_dup 0) 1)
+ (ltu:SI (subreg:SI (match_dup 0) 4)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
@@ -1307,12 +1307,12 @@
(minus:SI (subreg:SI (match_dup 1) 0)
(subreg:SI (match_dup 2) 0)))
- (set (subreg:SI (match_dup 0) 1)
- (minus:SI (subreg:SI (match_dup 1) 1)
- (subreg:SI (match_dup 2) 1)))
+ (set (subreg:SI (match_dup 0) 4)
+ (minus:SI (subreg:SI (match_dup 1) 4)
+ (subreg:SI (match_dup 2) 4)))
- (set (subreg:SI (match_dup 0) 1)
- (minus:SI (subreg:SI (match_dup 0) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (minus:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))]
"")
@@ -1328,12 +1328,12 @@
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (match_dup 3)
- (ltu:SI (subreg:SI (match_dup 1) 1)
- (subreg:SI (match_dup 2) 1)))
+ (ltu:SI (subreg:SI (match_dup 1) 4)
+ (subreg:SI (match_dup 2) 4)))
- (set (subreg:SI (match_dup 0) 1)
- (minus:SI (subreg:SI (match_dup 1) 1)
- (subreg:SI (match_dup 2) 1)))
+ (set (subreg:SI (match_dup 0) 4)
+ (minus:SI (subreg:SI (match_dup 1) 4)
+ (subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 0)
(minus:SI (subreg:SI (match_dup 1) 0)
@@ -1378,8 +1378,8 @@
(minus:SI (subreg:SI (match_dup 1) 0)
(match_dup 2)))
- (set (subreg:SI (match_dup 0) 1)
- (minus:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (minus:SI (subreg:SI (match_dup 1) 4)
(match_dup 3)))]
"")
@@ -1395,11 +1395,11 @@
&& INTVAL (operands[2]) > 0"
[(set (match_dup 3)
- (ltu:SI (subreg:SI (match_dup 1) 1)
+ (ltu:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
- (set (subreg:SI (match_dup 0) 1)
- (minus:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (minus:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
@@ -3121,7 +3121,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
- (set (subreg:SI (match_dup 0) 1) (not:SI (subreg:SI (match_dup 1) 1)))]
+ (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
"")
@@ -3224,7 +3224,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
- (set (subreg:SI (match_dup 0) 1) (and:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
+ (set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_insn "anddi3_internal1"
@@ -3325,7 +3325,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
- (set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
+ (set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_expand "xorsi3"
@@ -3429,7 +3429,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
- (set (subreg:SI (match_dup 0) 1) (xor:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
+ (set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_insn "xordi3_immed"
@@ -3478,7 +3478,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (and:SI (not:SI (subreg:SI (match_dup 1) 0)) (not:SI (subreg:SI (match_dup 2) 0))))
- (set (subreg:SI (match_dup 0) 1) (and:SI (not:SI (subreg:SI (match_dup 1) 1)) (not:SI (subreg:SI (match_dup 2) 1))))]
+ (set (subreg:SI (match_dup 0) 4) (and:SI (not:SI (subreg:SI (match_dup 1) 4)) (not:SI (subreg:SI (match_dup 2) 4))))]
"")
;;
@@ -4917,7 +4917,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
- (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))]
+ (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
(define_insn "movdi_internal2"
@@ -6147,7 +6147,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
- (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))]
+ (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
;; Instructions to load the global pointer register.
@@ -6516,7 +6516,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 1) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+ [(set (subreg:SI (match_dup 0) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -6533,8 +6533,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
- (set (subreg:SI (match_dup 0) 1) (const_int 0))]
+ [(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+ (set (subreg:SI (match_dup 0) 4) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -6574,16 +6574,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
- [(set (subreg:SI (match_dup 0) 1)
- (ashift:SI (subreg:SI (match_dup 1) 1)
+ [(set (subreg:SI (match_dup 0) 4)
+ (ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(lshiftrt:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
- (set (subreg:SI (match_dup 0) 1)
- (ior:SI (subreg:SI (match_dup 0) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)
@@ -6614,15 +6614,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
- (lshiftrt:SI (subreg:SI (match_dup 1) 1)
+ (lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
- (set (subreg:SI (match_dup 0) 1)
- (ashift:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@@ -6871,8 +6871,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
- (set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (const_int 31)))]
+ [(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+ (set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -6887,7 +6887,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+ [(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -6932,15 +6932,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
- (ashift:SI (subreg:SI (match_dup 1) 1)
+ (ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
- (set (subreg:SI (match_dup 0) 1)
- (ashiftrt:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (ashiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@@ -6962,16 +6962,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
- [(set (subreg:SI (match_dup 0) 1)
- (lshiftrt:SI (subreg:SI (match_dup 1) 1)
+ [(set (subreg:SI (match_dup 0) 4)
+ (lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
- (set (subreg:SI (match_dup 0) 1)
- (ior:SI (subreg:SI (match_dup 0) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)
@@ -7255,8 +7255,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
- (set (subreg:SI (match_dup 0) 1) (const_int 0))]
+ [(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
+ (set (subreg:SI (match_dup 0) 4) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -7272,7 +7272,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
- [(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
+ [(set (subreg:SI (match_dup 0) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@@ -7317,15 +7317,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
- (ashift:SI (subreg:SI (match_dup 1) 1)
+ (ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
- (set (subreg:SI (match_dup 0) 1)
- (lshiftrt:SI (subreg:SI (match_dup 1) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@@ -7347,16 +7347,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
- [(set (subreg:SI (match_dup 0) 1)
- (lshiftrt:SI (subreg:SI (match_dup 1) 1)
+ [(set (subreg:SI (match_dup 0) 4)
+ (lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
- (set (subreg:SI (match_dup 0) 1)
- (ior:SI (subreg:SI (match_dup 0) 1)
+ (set (subreg:SI (match_dup 0) 4)
+ (ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)
diff --git a/gcc/config/mn10200/mn10200.c b/gcc/config/mn10200/mn10200.c
index 1e520a84c60..1a4f9dd0f03 100644
--- a/gcc/config/mn10200/mn10200.c
+++ b/gcc/config/mn10200/mn10200.c
@@ -162,8 +162,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
+ fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_DOUBLE:
@@ -222,8 +221,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
+ fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
break;
case CONST_DOUBLE:
@@ -322,8 +320,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
+ fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_INT:
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 225c8789994..7f1c0363587 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -143,8 +143,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
+ fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_DOUBLE:
@@ -204,8 +203,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
+ fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
break;
case CONST_DOUBLE:
@@ -289,8 +287,7 @@ print_operand (file, x, code)
break;
case SUBREG:
- fprintf (file, "%s",
- reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
+ fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
/* This will only be single precision.... */
diff --git a/gcc/config/ns32k/ns32k.md b/gcc/config/ns32k/ns32k.md
index 2b811621be7..f7646d391d6 100644
--- a/gcc/config/ns32k/ns32k.md
+++ b/gcc/config/ns32k/ns32k.md
@@ -1275,7 +1275,7 @@
;; Retain this insn which *does* have a pattern indicating what it does,
;; just in case the compiler is smart enough to recognize a substitution.
(define_insn "udivmoddisi4"
- [(set (subreg:SI (match_operand:DI 0 "nonimmediate_operand" "=rm") 1)
+ [(set (subreg:SI (match_operand:DI 0 "nonimmediate_operand" "=rm") 4)
(truncate:SI (udiv:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))))
(set (subreg:SI (match_operand:DI 3 "nonimmediate_operand" "=0") 0)
@@ -1338,7 +1338,7 @@
"deiw %2,%0")
(define_insn "udivmoddihi4"
- [(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 1)
+ [(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 2)
(truncate:HI (udiv:DI (match_operand:DI 1 "register_operand" "0")
(zero_extend:DI (match_operand:HI 2 "nonimmediate_operand" "rm")))))
(set (subreg:HI (match_operand:DI 3 "register_operand" "=0") 0)
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 26e80966c95..502d204e74d 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -1192,11 +1192,11 @@ emit_move_sequence (operands, mode, scratch_reg)
&& GET_CODE (SUBREG_REG (operand0)) == REG
&& REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
{
- /* We must not alter SUBREG_WORD (operand0) since that would confuse
+ /* We must not alter SUBREG_BYTE (operand0) since that would confuse
the code which tracks sets/uses for delete_output_reload. */
rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
- SUBREG_WORD (operand0));
+ SUBREG_BYTE (operand0));
operand0 = alter_subreg (temp);
}
@@ -1209,11 +1209,11 @@ emit_move_sequence (operands, mode, scratch_reg)
&& GET_CODE (SUBREG_REG (operand1)) == REG
&& REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
{
- /* We must not alter SUBREG_WORD (operand0) since that would confuse
+ /* We must not alter SUBREG_BYTE (operand0) since that would confuse
the code which tracks sets/uses for delete_output_reload. */
rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
- SUBREG_WORD (operand1));
+ SUBREG_BYTE (operand1));
operand1 = alter_subreg (temp);
}
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index ceea64cfa82..baeef934243 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -3505,9 +3505,9 @@
(set_attr "length" "4")])
(define_expand "floatunssisf2"
- [(set (subreg:SI (match_dup 2) 1)
+ [(set (subreg:SI (match_dup 2) 4)
(match_operand:SI 1 "register_operand" ""))
- (set (subreg:SI (match_dup 2) 0)
+ (set (subreg:SI (match_dup 2) 4)
(const_int 0))
(set (match_operand:SF 0 "register_operand" "")
(float:SF (match_dup 2)))]
@@ -3523,7 +3523,7 @@
}")
(define_expand "floatunssidf2"
- [(set (subreg:SI (match_dup 2) 1)
+ [(set (subreg:SI (match_dup 2) 4)
(match_operand:SI 1 "register_operand" ""))
(set (subreg:SI (match_dup 2) 0)
(const_int 0))
@@ -3891,7 +3891,7 @@
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SUBREG (SImode, scratch, 1)));
+ gen_rtx_SUBREG (SImode, scratch, GET_MODE_SIZE (SImode))));
DONE;
}
operands[3] = gen_reg_rtx (SImode);
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index 9171a773386..7fc7f8dc281 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -766,7 +766,7 @@
(define_expand "zero_extendhisi2"
[(set (subreg:HI
(match_dup 0)
- 1)
+ 2)
(match_operand:HI 1 "register_operand" "r"))
(set (subreg:HI
(match_operand:SI 0 "register_operand" "=r")
@@ -1782,16 +1782,16 @@
[(set_attr "length" "2")])
(define_expand "modhi3"
- [(set (subreg:HI (match_dup 1) 1)
+ [(set (subreg:HI (match_dup 1) 2)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
(set (match_operand:HI 0 "general_operand" "=r")
- (subreg:HI (match_dup 1) 1))]
+ (subreg:HI (match_dup 1) 2))]
"TARGET_45"
"")
(define_insn ""
- [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 1)
+ [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 4)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
"TARGET_45"
@@ -1802,11 +1802,11 @@
; [(parallel [(set (subreg:HI (match_dup 1) 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
-; (set (subreg:HI (match_dup 1) 1)
+; (set (subreg:HI (match_dup 1) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))])
; (set (match_operand:HI 3 "general_operand" "=r")
-; (subreg:HI (match_dup 1) 1))
+; (subreg:HI (match_dup 1) 2))
; (set (match_operand:HI 0 "general_operand" "=r")
; (subreg:HI (match_dup 1) 0))]
; "TARGET_45"
@@ -1816,7 +1816,7 @@
; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
-; (set (subreg:HI (match_dup 0) 1)
+; (set (subreg:HI (match_dup 0) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))]
; "TARGET_45"
diff --git a/gcc/config/romp/romp.c b/gcc/config/romp/romp.c
index 7aedeb60024..8cabb46e825 100644
--- a/gcc/config/romp/romp.c
+++ b/gcc/config/romp/romp.c
@@ -269,12 +269,7 @@ memory_offset_in_range_p (op, mode, low, high)
while (GET_CODE (op) == SUBREG)
{
- offset += SUBREG_WORD (op) * UNITS_PER_WORD;
-#if BYTES_BIG_ENDIAN
- offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- - min (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))));
-#endif
+ offset += SUBREG_BYTE (op);
op = SUBREG_REG (op);
}
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 4cb5cf27fb0..d8d4ef3581b 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -666,7 +666,7 @@ output_movedouble (insn, operands, mode)
if (GET_CODE (inside) == REG)
ptrreg = REGNO (inside);
else if (GET_CODE (inside) == SUBREG)
- ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
+ ptrreg = subreg_regno (inside);
else if (GET_CODE (inside) == PLUS)
{
ptrreg = REGNO (XEXP (inside, 0));
@@ -1143,13 +1143,13 @@ gen_ashift_hi (type, n, reg)
gen_ashift_hi is only called in contexts where we know that the
sign extension works out correctly. */
{
- int word = 0;
+ int offset = 0;
if (GET_CODE (reg) == SUBREG)
{
- word = SUBREG_WORD (reg);
+ offset = SUBREG_BYTE (reg);
reg = SUBREG_REG (reg);
}
- gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, word));
+ gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));
break;
}
case ASHIFT:
@@ -2516,7 +2516,11 @@ regs_used (x, is_dest)
break;
if (REGNO (y) < 16)
return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
- << (REGNO (y) + SUBREG_WORD (x) + is_dest));
+ << (REGNO (y) +
+ subreg_regno_offset (REGNO (y),
+ GET_MODE (y),
+ SUBREG_BYTE (x),
+ GET_MODE (x)) + is_dest));
return 0;
}
case SET:
@@ -3260,7 +3264,10 @@ machine_dependent_reorg (first)
mode = HImode;
while (GET_CODE (dst) == SUBREG)
{
- offset += SUBREG_WORD (dst);
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (dst)),
+ GET_MODE (SUBREG_REG (dst)),
+ SUBREG_BYTE (dst),
+ GET_MODE (dst));
dst = SUBREG_REG (dst);
}
dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 7045148ae29..a71ba3cc796 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1401,7 +1401,7 @@ extern int current_function_anonymous_args;
((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
|| (GET_CODE (X) == SUBREG \
&& GET_CODE (SUBREG_REG (X)) == REG \
- && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_WORD (X))))
+ && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
/* Jump to LABEL if X is a valid address RTX. This must also take
REG_OK_STRICT into account when deciding about valid registers, but it uses
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 3a03c2d7b41..420c33630a8 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -2591,7 +2591,7 @@
if (GET_CODE (operands[0]) == REG)
regno = REGNO (operands[0]);
else if (GET_CODE (operands[0]) == SUBREG)
- regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]);
+ regno = subreg_regno (operands[0]);
else if (GET_CODE (operands[0]) == MEM)
regno = -1;
@@ -2729,7 +2729,7 @@
mem = operands[1];
store_p = 0;
}
- if (GET_CODE (mem) == SUBREG && SUBREG_WORD (mem) == 0)
+ if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
mem = SUBREG_REG (mem);
if (GET_CODE (mem) == MEM)
{
@@ -2751,7 +2751,7 @@
mem = copy_rtx (mem);
PUT_MODE (mem, SImode);
word0 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 0));
- word1 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 1));
+ word1 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 4));
if (store_p || ! refers_to_regno_p (REGNO (word0),
REGNO (word0) + 1, addr, 0))
{
@@ -2963,7 +2963,7 @@
if (GET_CODE (operands[0]) == REG)
regno = REGNO (operands[0]);
else if (GET_CODE (operands[0]) == SUBREG)
- regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]);
+ regno = subreg_regno (operands[0]);
else if (GET_CODE (operands[0]) == MEM)
regno = -1;
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 9cb4c5ccf09..782d2a725d3 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -7494,8 +7494,8 @@ ultra_find_type (type_mask, list, start)
&& GET_CODE (SET_SRC (pat)) == SUBREG
&& REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
REGNO (SUBREG_REG (SET_SRC (pat)))
- && SUBREG_WORD (SET_DEST (slot_pat)) ==
- SUBREG_WORD (SET_SRC (pat)))))
+ && SUBREG_BYTE (SET_DEST (slot_pat)) ==
+ SUBREG_BYTE (SET_SRC (pat)))))
|| (check_fpmode_conflict == 1
&& GET_CODE (slot_insn) == INSN
&& GET_CODE (slot_pat) == SET
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 9e49eadb02d..d65908eb353 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1146,25 +1146,34 @@ while (0)
: (GET_MODE_SIZE (MODE) + 3) / 4) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-/* A subreg in 64 bit mode will have the wrong offset for a floating point
- register. The least significant part is at offset 1, compared to 0 for
- integer registers. This only applies when FMODE is a larger mode.
- We also need to handle a special case of TF-->DF conversions. */
-#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO) \
- (TARGET_ARCH64 \
- && (REGNO) >= SPARC_FIRST_FP_REG \
- && (REGNO) <= SPARC_LAST_V9_FP_REG \
- && (TMODE) == SImode \
- && !((FMODE) == QImode || (FMODE) == HImode) \
- ? ((REGNO) + 1) \
- : ((TMODE) == DFmode && (FMODE) == TFmode) \
- ? ((REGNO) + ((WORD) * 2)) \
- : ((REGNO) + (WORD)))
+/* Due to the ARCH64 descrepancy above we must override these
+ next two macros too. */
+#define REG_SIZE(R) \
+ (TARGET_ARCH64 \
+ && ((GET_CODE (R) == REG \
+ && ((REGNO (R) >= FIRST_PSEUDO_REGISTER \
+ && FLOAT_MODE_P (GET_MODE (R))) \
+ || (REGNO (R) < FIRST_PSEUDO_REGISTER \
+ && REGNO (R) >= 32))) \
+ || (GET_CODE (R) == SUBREG \
+ && ((REGNO (SUBREG_REG (R)) >= FIRST_PSEUDO_REGISTER \
+ && FLOAT_MODE_P (GET_MODE (SUBREG_REG (R)))) \
+ || (REGNO (SUBREG_REG (R)) < FIRST_PSEUDO_REGISTER \
+ && REGNO (SUBREG_REG (R)) >= 32)))) \
+ ? (GET_MODE_SIZE (GET_MODE (R)) + 3) / 4 \
+ : (GET_MODE_SIZE (GET_MODE (R)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+#define REGMODE_NATURAL_SIZE(MODE) \
+ ((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
extern int *hard_regno_mode_classes;
extern int sparc_mode_class[];
+
+/* ??? Because of the funny way we pass parameters we should allow certain
+ ??? types of float/complex values to be in integer registers during
+ ??? RTL generation. This only matters on arch32. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 8167af887ec..cf7ae098196 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -4546,15 +4546,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
DONE;
@@ -4624,15 +4626,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
DONE;
@@ -4794,7 +4798,7 @@
(define_insn "*cmp_siqi_trunc"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
(const_int 0)))]
""
"andcc\\t%0, 0xff, %%g0"
@@ -4803,10 +4807,10 @@
(define_insn "*cmp_siqi_trunc_set"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (match_dup 1) 0))]
+ (subreg:QI (match_dup 1) 3))]
""
"andcc\\t%1, 0xff, %0"
[(set_attr "type" "compare")
@@ -4814,7 +4818,7 @@
(define_insn "*cmp_diqi_trunc"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
(const_int 0)))]
"TARGET_ARCH64"
"andcc\\t%0, 0xff, %%g0"
@@ -4823,10 +4827,10 @@
(define_insn "*cmp_diqi_trunc_set"
[(set (reg:CC 100)
- (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
+ (compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
- (subreg:QI (match_dup 1) 0))]
+ (subreg:QI (match_dup 1) 7))]
"TARGET_ARCH64"
"andcc\\t%1, 0xff, %0"
[(set_attr "type" "compare")
@@ -4846,15 +4850,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
DONE;
@@ -4876,23 +4882,27 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subword = 0;
- int op0_subword = 0;
+ int op1_subbyte = 0;
+ int op0_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
if (GET_CODE (operand0) == SUBREG)
{
- op0_subword = SUBREG_WORD (operand0);
+ op0_subbyte = SUBREG_BYTE (operand0);
+ op0_subbyte /= GET_MODE_SIZE (SImode);
+ op0_subbyte *= GET_MODE_SIZE (SImode);
operand0 = XEXP (operand0, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
if (GET_MODE (operand0) != SImode)
- operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword);
+ operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
}")
@@ -4913,15 +4923,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (SImode);
+ op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
+ emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
@@ -4943,15 +4955,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_56 = GEN_INT (56);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_56));
emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
DONE;
@@ -4973,15 +4987,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
- int op1_subword = 0;
+ int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
- op1_subword = SUBREG_WORD (operand1);
+ op1_subbyte = SUBREG_BYTE (operand1);
+ op1_subbyte /= GET_MODE_SIZE (DImode);
+ op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
- emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
+ emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
DONE;
@@ -6275,7 +6291,7 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
(match_operand:SI 3 "const_int_operand" "i,i"))
- 1))
+ 4))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
@@ -8346,7 +8362,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 32)) 0)
+ (const_int 32)) 4)
(match_operand:SI 2 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& ((GET_CODE (operands[2]) == CONST_INT
@@ -8366,7 +8382,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 32)) 0)
+ (const_int 32)) 4)
(match_operand:SI 2 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& ((GET_CODE (operands[2]) == CONST_INT
@@ -8386,7 +8402,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:SI 2 "small_int_or_double" "n")) 0)
+ (match_operand:SI 2 "small_int_or_double" "n")) 4)
(match_operand:SI 3 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
@@ -8405,7 +8421,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:SI 2 "small_int_or_double" "n")) 0)
+ (match_operand:SI 2 "small_int_or_double" "n")) 4)
(match_operand:SI 3 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 34369d46325..a074d953604 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -541,7 +541,7 @@ print_operand (file, x, code)
fputs (reg_names[REGNO (x)], file);
break;
case SUBREG:
- fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
+ fputs (reg_names[subreg_regno (x)], file);
break;
case CONST_INT:
case SYMBOL_REF:
@@ -823,7 +823,7 @@ output_move_double (operands)
if (GET_CODE (inside) == REG)
ptrreg = REGNO (inside);
else if (GET_CODE (inside) == SUBREG)
- ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
+ ptrreg = subreg_regno (inside);
else if (GET_CODE (inside) == PLUS)
ptrreg = REGNO (XEXP (inside, 0));
else if (GET_CODE (inside) == LO_SUM)
diff --git a/gcc/cse.c b/gcc/cse.c
index 38ba919f115..2b487510eae 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -1220,11 +1220,11 @@ mention_regs (x)
/* If reg_tick has been incremented more than once since
reg_in_table was last set, that means that the entire
register has been set before, so discard anything memorized
- for the entrire register, including all SUBREG expressions. */
+ for the entire register, including all SUBREG expressions. */
if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
remove_invalid_refs (i);
else
- remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
+ remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
}
REG_IN_TABLE (i) = REG_TICK (i);
@@ -2004,32 +2004,31 @@ remove_invalid_refs (regno)
}
}
-/* Likewise for a subreg with subreg_reg WORD and mode MODE. */
+/* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
+ and mode MODE. */
static void
-remove_invalid_subreg_refs (regno, word, mode)
+remove_invalid_subreg_refs (regno, offset, mode)
unsigned int regno;
- unsigned int word;
+ unsigned int offset;
enum machine_mode mode;
{
unsigned int i;
struct table_elt *p, *next;
- unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
+ unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
for (i = 0; i < HASH_SIZE; i++)
for (p = table[i]; p; p = next)
{
- rtx exp;
+ rtx exp = p->exp;
next = p->next_same_hash;
- exp = p->exp;
- if (GET_CODE (p->exp) != REG
+ if (GET_CODE (exp) != REG
&& (GET_CODE (exp) != SUBREG
|| GET_CODE (SUBREG_REG (exp)) != REG
|| REGNO (SUBREG_REG (exp)) != regno
- || (((SUBREG_WORD (exp)
- + (GET_MODE_SIZE (GET_MODE (exp)) - 1) / UNITS_PER_WORD)
- >= word)
- && SUBREG_WORD (exp) <= end))
+ || (((SUBREG_BYTE (exp)
+ + (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
+ && SUBREG_BYTE (exp) <= end))
&& refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
remove_from_table (p, i);
}
@@ -2302,7 +2301,8 @@ canon_hash (x, mode)
if (GET_CODE (SUBREG_REG (x)) == REG)
{
hash += (((unsigned) SUBREG << 7)
- + REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+ + REGNO (SUBREG_REG (x))
+ + (SUBREG_BYTE (x) / UNITS_PER_WORD));
return hash;
}
break;
@@ -3413,7 +3413,8 @@ fold_rtx (x, insn)
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
- new = operand_subword (folded_arg0, SUBREG_WORD (x), 0,
+ new = operand_subword (folded_arg0,
+ (SUBREG_BYTE (x) / UNITS_PER_WORD), 0,
GET_MODE (SUBREG_REG (x)));
if (new == 0 && subreg_lowpart_p (x))
new = gen_lowpart_if_possible (mode, folded_arg0);
@@ -4393,10 +4394,12 @@ gen_lowpart_if_possible (mode, x)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
if (BYTES_BIG_ENDIAN)
- /* Adjust the address so that the address-after-the-data is
- unchanged. */
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
+ {
+ /* Adjust the address so that the address-after-the-data is
+ unchanged. */
+ offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
+ - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
+ }
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
if (! memory_address_p (mode, XEXP (new, 0)))
return 0;
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index fd9fc0c0284..207ba2a155d 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -2024,20 +2024,15 @@ dbxout_symbol_location (decl, type, suffix, home)
else if (GET_CODE (home) == SUBREG)
{
rtx value = home;
- int offset = 0;
+
while (GET_CODE (value) == SUBREG)
- {
- offset += SUBREG_WORD (value);
- value = SUBREG_REG (value);
- }
+ value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
- regno = REGNO (value);
- if (regno >= FIRST_PSEUDO_REGISTER)
+ if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return 0;
- regno += offset;
}
- alter_subreg (home);
+ regno = REGNO (alter_subreg (home));
}
/* The kind-of-variable letter depends on where
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 2e71518fa80..873d0b6d97e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3494,7 +3494,7 @@ is_pseudo_reg (rtl)
{
return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
|| (GET_CODE (rtl) == SUBREG
- && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
+ && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
}
/* Return a reference to a type, with its const and volatile qualifiers
@@ -7038,7 +7038,7 @@ mem_loc_descriptor (rtl, mode)
up an entire register. For now, just assume that it is
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
- rtl = XEXP (rtl, 0);
+ rtl = SUBREG_REG (rtl);
/* Fall through. */
@@ -7182,7 +7182,7 @@ loc_descriptor (rtl)
up an entire register. For now, just assume that it is
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
- rtl = XEXP (rtl, 0);
+ rtl = SUBREG_REG (rtl);
/* Fall through. */
diff --git a/gcc/dwarfout.c b/gcc/dwarfout.c
index 370d14f4d88..80b06ae1754 100644
--- a/gcc/dwarfout.c
+++ b/gcc/dwarfout.c
@@ -817,7 +817,7 @@ is_pseudo_reg (rtl)
{
return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
|| ((GET_CODE (rtl) == SUBREG)
- && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
+ && (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)));
}
inline static tree
@@ -1630,7 +1630,7 @@ output_mem_loc_descriptor (rtl)
legitimate to make the Dwarf info refer to the whole register
which contains the given subreg. */
- rtl = XEXP (rtl, 0);
+ rtl = SUBREG_REG (rtl);
/* Drop thru. */
case REG:
@@ -1714,7 +1714,7 @@ output_loc_descriptor (rtl)
legitimate to make the Dwarf info refer to the whole register
which contains the given subreg. */
- rtl = XEXP (rtl, 0);
+ rtl = SUBREG_REG (rtl);
/* Drop thru. */
case REG:
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 93f11f43de9..7b715c6f69d 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -348,6 +348,55 @@ gen_rtx_MEM (mode, addr)
return rt;
}
+
+rtx
+gen_rtx_SUBREG (mode, reg, offset)
+ enum machine_mode mode;
+ rtx reg;
+ int offset;
+{
+ /* This is the most common failure type.
+ Catch it early so we can see who does it. */
+ if ((offset % GET_MODE_SIZE (mode)) != 0)
+ abort ();
+
+ /* This check isn't usable right now because combine will
+ throw arbitrary crap like a CALL into a SUBREG in
+ gen_lowpart_for_combine so we must just eat it. */
+#if 0
+ /* Check for this too. */
+ if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
+ abort ();
+#endif
+ return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
+}
+
+/* Generate a SUBREG representing the least-significant part
+ * of REG if MODE is smaller than mode of REG, otherwise
+ * paradoxical SUBREG. */
+rtx
+gen_lowpart_SUBREG (mode, reg)
+ enum machine_mode mode;
+ rtx reg;
+{
+ enum machine_mode inmode;
+ int offset;
+
+ inmode = GET_MODE (reg);
+ if (inmode == VOIDmode)
+ inmode = mode;
+ offset = 0;
+ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
+ && (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
+ {
+ offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
+ if (! BYTES_BIG_ENDIAN)
+ offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+ else if (! WORDS_BIG_ENDIAN)
+ offset %= UNITS_PER_WORD;
+ }
+ return gen_rtx_SUBREG (mode, reg, offset);
+}
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
@@ -650,6 +699,38 @@ get_first_label_num ()
return first_label_num;
}
+/* Return the final regno of X, which is a SUBREG of a hard
+ register. */
+int
+subreg_hard_regno (x, check_mode)
+ register rtx x;
+ int check_mode;
+{
+ enum machine_mode mode = GET_MODE (x);
+ unsigned int byte_offset, base_regno, final_regno;
+ rtx reg = SUBREG_REG (x);
+
+ /* This is where we attempt to catch illegal subregs
+ created by the compiler. */
+ if (GET_CODE (x) != SUBREG
+ || GET_CODE (reg) != REG)
+ abort ();
+ base_regno = REGNO (reg);
+ if (base_regno >= FIRST_PSEUDO_REGISTER)
+ abort ();
+ if (! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
+ abort ();
+
+ /* Catch non-congruent offsets too. */
+ byte_offset = SUBREG_BYTE (x);
+ if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
+ abort ();
+
+ final_regno = subreg_regno (x);
+
+ return final_regno;
+}
+
/* Return a value representing some low-order bits of X, where the number
of low-order bits is given by MODE. Note that no conversion is done
between floating-point and fixed-point values, rather, the bit
@@ -666,22 +747,29 @@ gen_lowpart_common (mode, x)
enum machine_mode mode;
register rtx x;
{
- int word = 0;
+ int msize = GET_MODE_SIZE (mode);
+ int xsize = GET_MODE_SIZE (GET_MODE (x));
+ int offset = 0;
if (GET_MODE (x) == mode)
return x;
/* MODE must occupy no more words than the mode of X. */
if (GET_MODE (x) != VOIDmode
- && ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
- > ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
- / UNITS_PER_WORD)))
+ && ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
+ > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
return 0;
- if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
- word = ((GET_MODE_SIZE (GET_MODE (x))
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD);
+ if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
+ && xsize > msize)
+ {
+ int difference = xsize - msize;
+
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
@@ -703,39 +791,40 @@ gen_lowpart_common (mode, x)
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
else if (GET_CODE (x) == SUBREG
- && (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- || GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
|| GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
- return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
- ? SUBREG_REG (x)
- : gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + word));
+ {
+ int final_offset;
+
+ if (GET_MODE (SUBREG_REG (x)) == mode && subreg_lowpart_p (x))
+ return SUBREG_REG (x);
+
+ /* When working with SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = SUBREG_BYTE (x) + offset;
+ final_offset = (final_offset / GET_MODE_SIZE (mode));
+ final_offset = (final_offset * GET_MODE_SIZE (mode));
+ return gen_rtx_SUBREG (mode, SUBREG_REG (x), final_offset);
+ }
else if (GET_CODE (x) == REG)
{
- /* Let the backend decide how many registers to skip. This is needed
- in particular for Sparc64 where fp regs are smaller than a word. */
- /* ??? Note that subregs are now ambiguous, in that those against
- pseudos are sized by the Word Size, while those against hard
- regs are sized by the underlying register size. Better would be
- to always interpret the subreg offset parameter as bytes or bits. */
-
- if (WORDS_BIG_ENDIAN && REGNO (x) < FIRST_PSEUDO_REGISTER
- && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode))
- word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
- - HARD_REGNO_NREGS (REGNO (x), mode));
-
- /* If the register is not valid for MODE, return 0. If we don't
- do this, there is no way to fix up the resulting REG later.
- But we do do this if the current REG is not valid for its
- mode. This latter is a kludge, but is required due to the
- way that parameters are passed on some machines, most
- notably Sparc. */
- if (REGNO (x) < FIRST_PSEUDO_REGISTER
- && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)
- && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
- return 0;
- else if (REGNO (x) < FIRST_PSEUDO_REGISTER
+ /* Hard registers are done specially in certain cases. */
+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+ {
+ int final_regno = REGNO (x) +
+ subreg_regno_offset (REGNO (x), GET_MODE (x),
+ offset, mode);
+
+ /* If the final regno is not valid for MODE, punt. */
+ /* ??? We do allow it if the current REG is not valid for
+ ??? it's mode. It is a kludge to work around how float/complex
+ ??? arguments are passed on 32-bit Sparc and should be fixed. */
+ if (! HARD_REGNO_MODE_OK (final_regno, mode)
+ && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
+ return 0;
+
/* integrate.c can't handle parts of a return value register. */
- && (! REG_FUNCTION_VALUE_P (x)
+ if ((! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x))
@@ -752,9 +841,9 @@ gen_lowpart_common (mode, x)
&& x != arg_pointer_rtx
#endif
&& x != stack_pointer_rtx)
- return gen_rtx_REG (mode, REGNO (x) + word);
- else
- return gen_rtx_SUBREG (mode, x, word);
+ return gen_rtx_REG (mode, final_regno);
+ }
+ return gen_rtx_SUBREG (mode, x, offset);
}
/* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
from the low-order part of the constant. */
@@ -847,7 +936,7 @@ gen_lowpart_common (mode, x)
&& GET_CODE (x) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
- return operand_subword (x, word, 0, GET_MODE (x));
+ return constant_subword (x, (offset / UNITS_PER_WORD), GET_MODE (x));
/* Similarly, if this is converting a floating-point value into a
two-word integer, we can do this one word at a time and make an
@@ -863,11 +952,14 @@ gen_lowpart_common (mode, x)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
{
- rtx lowpart
- = operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));
- rtx highpart
- = operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
-
+ rtx lowpart, highpart;
+
+ lowpart = constant_subword (x,
+ (offset / UNITS_PER_WORD) + WORDS_BIG_ENDIAN,
+ GET_MODE (x));
+ highpart = constant_subword (x,
+ (offset / UNITS_PER_WORD) + (! WORDS_BIG_ENDIAN),
+ GET_MODE (x));
if (lowpart && GET_CODE (lowpart) == CONST_INT
&& highpart && GET_CODE (highpart) == CONST_INT)
return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
@@ -1021,7 +1113,7 @@ gen_imagpart (mode, x)
return XEXP (x, 1);
else if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
- else if (!WORDS_BIG_ENDIAN
+ else if (! WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
&& REG_P (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
@@ -1043,7 +1135,7 @@ subreg_realpart_p (x)
if (GET_CODE (x) != SUBREG)
abort ();
- return ((unsigned int) SUBREG_WORD (x) * UNITS_PER_WORD
+ return ((unsigned int) SUBREG_BYTE (x)
< GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
}
@@ -1101,10 +1193,13 @@ gen_highpart (mode, x)
enum machine_mode mode;
register rtx x;
{
+ unsigned int msize = GET_MODE_SIZE (mode);
+ unsigned int xsize = GET_MODE_SIZE (GET_MODE (x));
+
/* This case loses if X is a subreg. To catch bugs early,
complain if an invalid MODE is used even in other cases. */
- if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
- && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
+ if (msize > UNITS_PER_WORD
+ && msize != GET_MODE_UNIT_SIZE (GET_MODE (x)))
abort ();
if (GET_CODE (x) == CONST_DOUBLE
#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
@@ -1121,15 +1216,14 @@ gen_highpart (mode, x)
else if (GET_CODE (x) == MEM)
{
register int offset = 0;
+
if (! WORDS_BIG_ENDIAN)
- offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+ offset = (MAX (xsize, UNITS_PER_WORD)
+ - MAX (msize, UNITS_PER_WORD));
if (! BYTES_BIG_ENDIAN
- && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
- offset -= (GET_MODE_SIZE (mode)
- - MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (x))));
+ && msize < UNITS_PER_WORD)
+ offset -= (msize - MIN (UNITS_PER_WORD, xsize));
return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
}
@@ -1138,46 +1232,47 @@ gen_highpart (mode, x)
/* The only time this should occur is when we are looking at a
multi-word item with a SUBREG whose mode is the same as that of the
item. It isn't clear what we would do if it wasn't. */
- if (SUBREG_WORD (x) != 0)
+ if (SUBREG_BYTE (x) != 0)
abort ();
return gen_highpart (mode, SUBREG_REG (x));
}
else if (GET_CODE (x) == REG)
{
- int word;
-
- /* Let the backend decide how many registers to skip. This is needed
- in particular for sparc64 where fp regs are smaller than a word. */
- /* ??? Note that subregs are now ambiguous, in that those against
- pseudos are sized by the word size, while those against hard
- regs are sized by the underlying register size. Better would be
- to always interpret the subreg offset parameter as bytes or bits. */
+ int offset = 0;
if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
abort ();
- else if (WORDS_BIG_ENDIAN)
- word = 0;
- else if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
- - HARD_REGNO_NREGS (REGNO (x), mode));
- else
- word = ((GET_MODE_SIZE (GET_MODE (x))
- - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
- / UNITS_PER_WORD);
-
- if (REGNO (x) < FIRST_PSEUDO_REGISTER
- /* integrate.c can't handle parts of a return value register. */
- && (! REG_FUNCTION_VALUE_P (x)
- || ! rtx_equal_function_value_matters)
+
+ if ((! WORDS_BIG_ENDIAN || ! BYTES_BIG_ENDIAN)
+ && xsize > msize)
+ {
+ int difference = xsize - msize;
+
+ if (! WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (! BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+ {
+ int final_regno = REGNO (x) +
+ subreg_regno_offset (REGNO (x), GET_MODE (x), offset, mode);
+
+ /* integrate.c can't handle parts of a return value register.
+ ??? Then integrate.c should be fixed!
+ ??? What about CLASS_CANNOT_CHANGE_SIZE? */
+ if ((! REG_FUNCTION_VALUE_P (x)
+ || ! rtx_equal_function_value_matters)
/* We want to keep the stack, frame, and arg pointers special. */
- && x != frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && x != arg_pointer_rtx
+ && x != frame_pointer_rtx
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && x != arg_pointer_rtx
#endif
- && x != stack_pointer_rtx)
- return gen_rtx_REG (mode, REGNO (x) + word);
- else
- return gen_rtx_SUBREG (mode, x, word);
+ && x != stack_pointer_rtx)
+ return gen_rtx_REG (mode, final_regno);
+ }
+ /* Just generate a normal SUBREG. */
+ return gen_rtx_SUBREG (mode, x, offset);
}
else
abort ();
@@ -1191,154 +1286,44 @@ int
subreg_lowpart_p (x)
rtx x;
{
+ unsigned int offset = 0;
+ int difference = (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+ - GET_MODE_SIZE (GET_MODE (x)));
+
if (GET_CODE (x) != SUBREG)
return 1;
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
return 0;
- if (WORDS_BIG_ENDIAN
- && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
- return (SUBREG_WORD (x)
- == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
- / UNITS_PER_WORD));
+ if (difference > 0)
+ {
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
- return SUBREG_WORD (x) == 0;
+ return SUBREG_BYTE (x) == offset;
}
-/* Return subword I of operand OP.
- The word number, I, is interpreted as the word number starting at the
- low-order address. Word 0 is the low-order word if not WORDS_BIG_ENDIAN,
- otherwise it is the high-order word.
-
- If we cannot extract the required word, we return zero. Otherwise, an
- rtx corresponding to the requested word will be returned.
- VALIDATE_ADDRESS is nonzero if the address should be validated. Before
- reload has completed, a valid address will always be returned. After
- reload, if a valid address cannot be returned, we return zero.
-
- If VALIDATE_ADDRESS is zero, we simply form the required address; validating
- it is the responsibility of the caller.
-
- MODE is the mode of OP in case it is a CONST_INT. */
+/* Helper routine for all the constant cases of operand_subword.
+ Some places invoke this directly. */
rtx
-operand_subword (op, i, validate_address, mode)
+constant_subword (op, offset, mode)
rtx op;
- unsigned int i;
- int validate_address;
+ int offset;
enum machine_mode mode;
{
- HOST_WIDE_INT val;
int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
-
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode == VOIDmode)
- abort ();
-
- /* If OP is narrower than a word, fail. */
- if (mode != BLKmode
- && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
- return 0;
-
- /* If we want a word outside OP, return zero. */
- if (mode != BLKmode
- && (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
- return const0_rtx;
+ HOST_WIDE_INT val;
/* If OP is already an integer word, return it. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
- /* If OP is a REG or SUBREG, we can handle it very simply. */
- if (GET_CODE (op) == REG)
- {
- /* ??? There is a potential problem with this code. It does not
- properly handle extractions of a subword from a hard register
- that is larger than word_mode. Presumably the check for
- HARD_REGNO_MODE_OK catches these most of these cases. */
-
- /* If OP is a hard register, but OP + I is not a hard register,
- then extracting a subword is impossible.
-
- For example, consider if OP is the last hard register and it is
- larger than word_mode. If we wanted word N (for N > 0) because a
- part of that hard register was known to contain a useful value,
- then OP + I would refer to a pseudo, not the hard register we
- actually wanted. */
- if (REGNO (op) < FIRST_PSEUDO_REGISTER
- && REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
- return 0;
-
- /* If the register is not valid for MODE, return 0. Note we
- have to check both OP and OP + I since they may refer to
- different parts of the register file.
-
- Consider if OP refers to the last 96bit FP register and we want
- subword 3 because that subword is known to contain a value we
- needed. */
- if (REGNO (op) < FIRST_PSEUDO_REGISTER
- && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
- || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
- return 0;
- else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || (REG_FUNCTION_VALUE_P (op)
- && rtx_equal_function_value_matters)
- /* We want to keep the stack, frame, and arg pointers
- special. */
- || op == frame_pointer_rtx
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || op == arg_pointer_rtx
-#endif
- || op == stack_pointer_rtx)
- return gen_rtx_SUBREG (word_mode, op, i);
- else
- return gen_rtx_REG (word_mode, REGNO (op) + i);
- }
- else if (GET_CODE (op) == SUBREG)
- return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));
- else if (GET_CODE (op) == CONCAT)
- {
- unsigned int partwords
- = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
-
- if (i < partwords)
- return operand_subword (XEXP (op, 0), i, validate_address, mode);
- return operand_subword (XEXP (op, 1), i - partwords,
- validate_address, mode);
- }
-
- /* Form a new MEM at the requested address. */
- if (GET_CODE (op) == MEM)
- {
- rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);
- rtx new;
-
- if (validate_address)
- {
- if (reload_completed)
- {
- if (! strict_memory_address_p (word_mode, addr))
- return 0;
- }
- else
- addr = memory_address (word_mode, addr);
- }
-
- new = gen_rtx_MEM (word_mode, addr);
- MEM_COPY_ATTRIBUTES (new, op);
- return new;
- }
-
- /* The only remaining cases are when OP is a constant. If the host and
- target floating formats are the same, handling two-word floating
- constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
- are defined as returning one or two 32 bit values, respectively,
- and not values of BITS_PER_WORD bits. */
#ifdef REAL_ARITHMETIC
/* The output is some bits, the width of the target machine's word.
A wider-word host can surely hold them in a CONST_INT. A narrower-word
@@ -1365,12 +1350,12 @@ operand_subword (op, i, validate_address, mode)
So we explicitly mask and sign-extend as necessary. */
if (BITS_PER_WORD == 32)
{
- val = k[i];
+ val = k[offset];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
#if HOST_BITS_PER_WIDE_INT >= 64
- else if (BITS_PER_WORD >= 64 && i == 0)
+ else if (BITS_PER_WORD >= 64 && offset == 0)
{
val = k[! WORDS_BIG_ENDIAN];
val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
@@ -1380,8 +1365,8 @@ operand_subword (op, i, validate_address, mode)
#endif
else if (BITS_PER_WORD == 16)
{
- val = k[i >> 1];
- if ((i & 1) == !WORDS_BIG_ENDIAN)
+ val = k[offset >> 1];
+ if ((offset & 1) == ! WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
return GEN_INT (val);
@@ -1402,16 +1387,16 @@ operand_subword (op, i, validate_address, mode)
if (BITS_PER_WORD == 32)
{
- val = k[i];
+ val = k[offset];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
#if HOST_BITS_PER_WIDE_INT >= 64
- else if (BITS_PER_WORD >= 64 && i <= 1)
+ else if (BITS_PER_WORD >= 64 && offset <= 1)
{
- val = k[i*2 + ! WORDS_BIG_ENDIAN];
+ val = k[offset * 2 + ! WORDS_BIG_ENDIAN];
val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
- val |= (HOST_WIDE_INT) k[i*2 + WORDS_BIG_ENDIAN] & 0xffffffff;
+ val |= (HOST_WIDE_INT) k[offset * 2 + WORDS_BIG_ENDIAN] & 0xffffffff;
return GEN_INT (val);
}
#endif
@@ -1431,10 +1416,10 @@ operand_subword (op, i, validate_address, mode)
compilers don't like a conditional inside macro args, so we have two
copies of the return. */
#ifdef HOST_WORDS_BIG_ENDIAN
- return GEN_INT (i == WORDS_BIG_ENDIAN
+ return GEN_INT (offset == WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#else
- return GEN_INT (i != WORDS_BIG_ENDIAN
+ return GEN_INT (offset != WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#endif
}
@@ -1460,7 +1445,7 @@ operand_subword (op, i, validate_address, mode)
if (BITS_PER_WORD == 16)
{
- if ((i & 1) == !WORDS_BIG_ENDIAN)
+ if ((offset & 1) == ! WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
}
@@ -1504,7 +1489,7 @@ operand_subword (op, i, validate_address, mode)
/* The only remaining cases that we can handle are integers.
Convert to proper endianness now since these cases need it.
- At this point, i == 0 means the low-order word.
+ At this point, offset == 0 means the low-order word.
We do not want to handle the case when BITS_PER_WORD <= HOST_BITS_PER_INT
in general. However, if OP is (const_int 0), we can just return
@@ -1519,39 +1504,184 @@ operand_subword (op, i, validate_address, mode)
return 0;
if (WORDS_BIG_ENDIAN)
- i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
+ offset = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - offset;
/* Find out which word on the host machine this value is in and get
it from the constant. */
- val = (i / size_ratio == 0
+ val = (offset / size_ratio == 0
? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))
: (GET_CODE (op) == CONST_INT
? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));
/* Get the value we want into the low bits of val. */
if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)
- val = ((val >> ((i % size_ratio) * BITS_PER_WORD)));
+ val = ((val >> ((offset % size_ratio) * BITS_PER_WORD)));
val = trunc_int_for_mode (val, word_mode);
return GEN_INT (val);
}
+/* Return subword OFFSET of operand OP.
+ The word number, OFFSET, is interpreted as the word number starting
+ at the low-order address. OFFSET 0 is the low-order word if not
+ WORDS_BIG_ENDIAN, otherwise it is the high-order word.
+
+ If we cannot extract the required word, we return zero. Otherwise,
+ an rtx corresponding to the requested word will be returned.
+
+ VALIDATE_ADDRESS is nonzero if the address should be validated. Before
+ reload has completed, a valid address will always be returned. After
+ reload, if a valid address cannot be returned, we return zero.
+
+ If VALIDATE_ADDRESS is zero, we simply form the required address; validating
+ it is the responsibility of the caller.
+
+ MODE is the mode of OP in case it is a CONST_INT.
+
+ ??? This is still rather broken for some cases. The problem for the
+ moment is that all callers of this thing provide no 'goal mode' to
+ tell us to work with. This exists because all callers were written
+ in a word based SUBREG world. */
+
+rtx
+operand_subword (op, offset, validate_address, mode)
+ rtx op;
+ unsigned int offset;
+ int validate_address;
+ enum machine_mode mode;
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (mode == VOIDmode)
+ abort ();
+
+ /* If OP is narrower than a word, fail. */
+ if (mode != BLKmode
+ && (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
+ return 0;
+
+ /* If we want a word outside OP, return zero. */
+ if (mode != BLKmode
+ && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
+ return const0_rtx;
+
+ switch (GET_CODE (op))
+ {
+ case REG:
+ case SUBREG:
+ case CONCAT:
+ case MEM:
+ break;
+
+ default:
+ /* The only remaining cases are when OP is a constant. If the host and
+ target floating formats are the same, handling two-word floating
+ constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
+ are defined as returning one or two 32 bit values, respectively,
+ and not values of BITS_PER_WORD bits. */
+ return constant_subword (op, offset, mode);
+ }
+
+ /* If OP is already an integer word, return it. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == UNITS_PER_WORD)
+ return op;
+
+ /* If OP is a REG or SUBREG, we can handle it very simply. */
+ if (GET_CODE (op) == REG)
+ {
+ if (REGNO (op) < FIRST_PSEUDO_REGISTER)
+ {
+ int final_regno = REGNO (op) +
+ subreg_regno_offset (REGNO (op), GET_MODE (op),
+ offset * UNITS_PER_WORD,
+ word_mode);
+
+ /* If the register is not valid for MODE, return 0. If we don't
+ do this, there is no way to fix up the resulting REG later. */
+ if (! HARD_REGNO_MODE_OK (final_regno, word_mode))
+ return 0;
+
+ /* integrate.c can't handle parts of a return value register.
+ ??? Then integrate.c should be fixed!
+ ??? What about CLASS_CANNOT_CHANGE_SIZE? */
+ if ((! REG_FUNCTION_VALUE_P (op)
+ || ! rtx_equal_function_value_matters)
+ /* ??? What about CLASS_CANNOT_CHANGE_SIZE? */
+ /* We want to keep the stack, frame, and arg pointers
+ special. */
+ && op != frame_pointer_rtx
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && op != arg_pointer_rtx
+#endif
+ && op != stack_pointer_rtx)
+ return gen_rtx_REG (word_mode, final_regno);
+ }
+
+ /* Just return a normal SUBREG. */
+ return gen_rtx_SUBREG (word_mode, op,
+ (offset * UNITS_PER_WORD));
+ }
+ else if (GET_CODE (op) == SUBREG)
+ {
+ int final_offset = ((offset * UNITS_PER_WORD) + SUBREG_BYTE (op));
+
+ /* When working with SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (word_mode));
+ final_offset = (final_offset * GET_MODE_SIZE (word_mode));
+ return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), final_offset);
+ }
+ else if (GET_CODE (op) == CONCAT)
+ {
+ unsigned int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
+ if (offset < partwords)
+ return operand_subword (XEXP (op, 0), offset, validate_address, mode);
+ return operand_subword (XEXP (op, 1), offset - partwords,
+ validate_address, mode);
+ }
+
+ /* Form a new MEM at the requested address. */
+ if (GET_CODE (op) == MEM)
+ {
+ rtx addr = plus_constant (XEXP (op, 0), (offset * UNITS_PER_WORD));
+ rtx new;
+
+ if (validate_address)
+ {
+ if (reload_completed)
+ {
+ if (! strict_memory_address_p (word_mode, addr))
+ return 0;
+ }
+ else
+ addr = memory_address (word_mode, addr);
+ }
+
+ new = gen_rtx_MEM (word_mode, addr);
+ MEM_COPY_ATTRIBUTES (new, op);
+ return new;
+ }
+
+ /* Unreachable... (famous last words) */
+ abort ();
+}
+
/* Similar to `operand_subword', but never return 0. If we can't extract
the required subword, put OP into a register and try again. If that fails,
- abort. We always validate the address in this case. It is not valid
- to call this function after reload; it is mostly meant for RTL
- generation.
+ abort. We always validate the address in this case.
MODE is the mode of OP, in case it is CONST_INT. */
rtx
-operand_subword_force (op, i, mode)
+operand_subword_force (op, offset, mode)
rtx op;
- unsigned int i;
+ unsigned int offset;
enum machine_mode mode;
{
- rtx result = operand_subword (op, i, 1, mode);
+ rtx result = operand_subword (op, offset, 1, mode);
if (result)
return result;
@@ -1566,7 +1696,7 @@ operand_subword_force (op, i, mode)
op = force_reg (mode, op);
}
- result = operand_subword (op, i, 1, mode);
+ result = operand_subword (op, offset, 1, mode);
if (result == 0)
abort ();
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 7fdbdf5d2bf..a7684508b5b 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -261,7 +261,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs
always get higher addresses. */
- offset += SUBREG_WORD (op0);
+ offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
/* We used to adjust BITPOS here, but now we do the whole adjustment
right after the loop. */
op0 = SUBREG_REG (op0);
@@ -311,7 +311,9 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
abort ();
}
if (GET_CODE (op0) == REG)
- op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
+ op0 = gen_rtx_SUBREG (fieldmode, op0,
+ (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ + (offset * UNITS_PER_WORD));
else
op0 = change_address (op0, fieldmode,
plus_constant (XEXP (op0, 0), offset));
@@ -373,7 +375,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
}
emit_insn (GEN_FCN (icode)
- (gen_rtx_SUBREG (fieldmode, op0, offset), value));
+ (gen_rtx_SUBREG (fieldmode, op0,
+ (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ + (offset * UNITS_PER_WORD)),
+ value));
return value;
}
@@ -447,7 +452,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
abort ();
}
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
- op0, offset);
+ op0, (offset * UNITS_PER_WORD));
}
offset = 0;
}
@@ -550,7 +555,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
if (GET_CODE (xop0) == SUBREG)
/* We can't just change the mode, because this might clobber op0,
and we will need the original value of op0 if insv fails. */
- xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_WORD (xop0));
+ xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
@@ -910,8 +915,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG)
{
- word = operand_subword_force (SUBREG_REG (op0),
- SUBREG_WORD (op0) + offset,
+ int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
+ word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0)));
offset = 0;
}
@@ -1008,7 +1013,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
- offset += SUBREG_WORD (op0);
+ offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
inner_size = MIN (inner_size, BITS_PER_WORD);
@@ -1104,7 +1109,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
abort ();
}
if (GET_CODE (op0) == REG)
- op0 = gen_rtx_SUBREG (mode1, op0, offset);
+ op0 = gen_rtx_SUBREG (mode1, op0,
+ (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ + (offset * UNITS_PER_WORD));
else
op0 = change_address (op0, mode1,
plus_constant (XEXP (op0, 0), offset));
@@ -1213,7 +1220,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
if (GET_CODE (op0) != REG)
op0 = copy_to_reg (op0);
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
- op0, offset);
+ op0, (offset * UNITS_PER_WORD));
}
offset = 0;
}
@@ -1808,8 +1815,8 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG)
{
- word = operand_subword_force (SUBREG_REG (op0),
- SUBREG_WORD (op0) + offset,
+ int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
+ word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0)));
offset = 0;
}
@@ -1928,7 +1935,7 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
- && SUBREG_WORD (op1) == 0)
+ && SUBREG_BYTE (op1) == 0)
op1 = SUBREG_REG (op1);
}
#endif
diff --git a/gcc/expr.c b/gcc/expr.c
index c2661722cb3..7d78acd33ae 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4134,7 +4134,7 @@ store_expr (exp, target, want_value)
if (want_value && GET_MODE (temp) != GET_MODE (target)
&& GET_MODE (temp) != VOIDmode)
{
- temp = gen_rtx_SUBREG (GET_MODE (target), temp, 0);
+ temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp)
= SUBREG_PROMOTED_UNSIGNED_P (target);
@@ -6346,7 +6346,7 @@ expand_expr (exp, target, tmode, modifier)
!= promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
abort ();
- temp = gen_rtx_SUBREG (mode, DECL_RTL (exp), 0);
+ temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
return temp;
@@ -6466,7 +6466,7 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
{
- temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
+ temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
}
@@ -6489,7 +6489,7 @@ expand_expr (exp, target, tmode, modifier)
{
/* Compute the signedness and make the proper SUBREG. */
promote_mode (type, mode, &unsignedp, 0);
- temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
+ temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
return temp;
diff --git a/gcc/final.c b/gcc/final.c
index fef6641a3a6..88519bd73bf 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -3119,20 +3119,8 @@ alter_subreg (x)
if (GET_CODE (y) == REG)
{
- int regno;
- /* If the word size is larger than the size of this register,
- adjust the register number to compensate. */
- /* ??? Note that this just catches stragglers created by/for
- integrate. It would be better if we either caught these
- earlier, or kept _all_ subregs until now and eliminate
- gen_lowpart and friends. */
-
-#ifdef ALTER_HARD_SUBREG
- regno = ALTER_HARD_SUBREG (GET_MODE (x), SUBREG_WORD (x),
- GET_MODE (y), REGNO (y));
-#else
- regno = REGNO (y) + SUBREG_WORD (x);
-#endif
+ int regno = subreg_hard_regno (x, 1);
+
PUT_CODE (x, REG);
REGNO (x) = regno;
ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
@@ -3142,11 +3130,12 @@ alter_subreg (x)
}
else if (GET_CODE (y) == MEM)
{
- register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ register int offset = SUBREG_BYTE (x);
+
+ /* Catch these instead of generating incorrect code. */
+ if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
+ abort ();
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
MEM_COPY_ATTRIBUTES (x, y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
diff --git a/gcc/flow.c b/gcc/flow.c
index d057bc5e264..388bd2a9d8a 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -3088,7 +3088,7 @@ set_noop_p (set)
if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
{
- if (SUBREG_WORD (src) != SUBREG_WORD (dst))
+ if (SUBREG_BYTE (src) != SUBREG_BYTE (dst))
return 0;
src = SUBREG_REG (src);
dst = SUBREG_REG (dst);
@@ -4669,12 +4669,9 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
regno_last = regno_first = REGNO (SUBREG_REG (reg));
if (regno_first < FIRST_PSEUDO_REGISTER)
{
-#ifdef ALTER_HARD_SUBREG
- regno_first = ALTER_HARD_SUBREG (outer_mode, SUBREG_WORD (reg),
- inner_mode, regno_first);
-#else
- regno_first += SUBREG_WORD (reg);
-#endif
+ regno_first += subreg_regno_offset (regno_first, inner_mode,
+ SUBREG_BYTE (reg),
+ outer_mode);
regno_last = (regno_first
+ HARD_REGNO_NREGS (regno_first, outer_mode) - 1);
diff --git a/gcc/function.c b/gcc/function.c
index 6eebf34f284..c31029bc566 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2221,7 +2221,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
dest = XEXP (dest, 0);
if (GET_CODE (src) == SUBREG)
- src = XEXP (src, 0);
+ src = SUBREG_REG (src);
/* If VAR does not appear at the top level of the SET
just scan the lower levels of the tree. */
@@ -2505,7 +2505,7 @@ fixup_memory_subreg (x, insn, uncritical)
rtx insn;
int uncritical;
{
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ int offset = SUBREG_BYTE (x);
rtx addr = XEXP (SUBREG_REG (x), 0);
enum machine_mode mode = GET_MODE (x);
rtx result;
@@ -2515,9 +2515,6 @@ fixup_memory_subreg (x, insn, uncritical)
&& ! uncritical)
abort ();
- if (BYTES_BIG_ENDIAN)
- offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
addr = plus_constant (addr, offset);
if (!flag_force_addr && memory_address_p (mode, addr))
/* Shortcut if no insns need be emitted. */
@@ -2711,7 +2708,8 @@ optimize_bit_field (body, insn, equiv_mem)
offset /= BITS_PER_UNIT;
if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
{
- offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
+ offset += (SUBREG_BYTE (XEXP (bitfield, 0))
+ / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
@@ -2736,7 +2734,7 @@ optimize_bit_field (body, insn, equiv_mem)
{
rtx src = SET_SRC (body);
while (GET_CODE (src) == SUBREG
- && SUBREG_WORD (src) == 0)
+ && SUBREG_BYTE (src) == 0)
src = SUBREG_REG (src);
if (GET_MODE (src) != GET_MODE (memref))
src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
@@ -2757,7 +2755,7 @@ optimize_bit_field (body, insn, equiv_mem)
rtx dest = SET_DEST (body);
while (GET_CODE (dest) == SUBREG
- && SUBREG_WORD (dest) == 0
+ && SUBREG_BYTE (dest) == 0
&& (GET_MODE_CLASS (GET_MODE (dest))
== GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
@@ -3067,7 +3065,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
code did. This is especially true of
REG_RETVAL. */
- if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
+ if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
z = SUBREG_REG (z);
if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
@@ -3443,17 +3441,22 @@ purge_single_hard_subreg_set (pattern)
{
rtx reg = SET_DEST (pattern);
enum machine_mode mode = GET_MODE (SET_DEST (pattern));
- int word = 0;
-
- while (GET_CODE (reg) == SUBREG)
+ int offset = 0;
+
+ if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG
+ && REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER)
{
- word += SUBREG_WORD (reg);
+ offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
+ GET_MODE (SUBREG_REG (reg)),
+ SUBREG_BYTE (reg),
+ GET_MODE (reg));
reg = SUBREG_REG (reg);
}
-
+
+
if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
{
- reg = gen_rtx_REG (mode, REGNO (reg) + word);
+ reg = gen_rtx_REG (mode, REGNO (reg) + offset);
SET_DEST (pattern) = reg;
}
}
@@ -4737,6 +4740,20 @@ assign_parms (fndecl)
push_to_sequence (conversion_insns);
tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
+ if (GET_CODE (tempreg) == SUBREG
+ && GET_MODE (tempreg) == nominal_mode
+ && GET_CODE (SUBREG_REG (tempreg)) == REG
+ && nominal_mode == passed_mode
+ && GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (entry_parm)
+ && GET_MODE_SIZE (GET_MODE (tempreg))
+ < GET_MODE_SIZE (GET_MODE (entry_parm)))
+ {
+ /* The argument is already sign/zero extended, so note it
+ into the subreg. */
+ SUBREG_PROMOTED_VAR_P (tempreg) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (tempreg) = unsignedp;
+ }
+
/* TREE_USED gets set erroneously during expand_assignment. */
save_tree_used = TREE_USED (parm);
expand_assignment (parm,
diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c
index 21f46df1461..d41e0d27975 100644
--- a/gcc/gengenrtl.c
+++ b/gcc/gengenrtl.c
@@ -208,6 +208,7 @@ special_rtx (idx)
return (strcmp (defs[idx].enumname, "CONST_INT") == 0
|| strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
|| strcmp (defs[idx].enumname, "REG") == 0
+ || strcmp (defs[idx].enumname, "SUBREG") == 0
|| strcmp (defs[idx].enumname, "MEM") == 0);
}
diff --git a/gcc/global.c b/gcc/global.c
index 8aa172a5e36..2f757bd9ade 100644
--- a/gcc/global.c
+++ b/gcc/global.c
@@ -1422,17 +1422,8 @@ mark_reg_store (reg, setter, data)
{
register int regno;
- /* WORD is which word of a multi-register group is being stored.
- For the case where the store is actually into a SUBREG of REG.
- Except we don't use it; I believe the entire REG needs to be
- made live. */
- int word = 0;
-
if (GET_CODE (reg) == SUBREG)
- {
- word = SUBREG_WORD (reg);
- reg = SUBREG_REG (reg);
- }
+ reg = SUBREG_REG (reg);
if (GET_CODE (reg) != REG)
return;
@@ -1456,7 +1447,7 @@ mark_reg_store (reg, setter, data)
}
if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno] /* + word */;
+ regno = reg_renumber[regno];
/* Handle hardware regs (and pseudos allocated to hard regs). */
if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
@@ -1606,7 +1597,15 @@ set_preference (dest, src)
else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
{
src_regno = REGNO (SUBREG_REG (src));
- offset += SUBREG_WORD (src);
+
+ if (REGNO (SUBREG_REG (src)) < FIRST_PSEUDO_REGISTER)
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (src)),
+ GET_MODE (SUBREG_REG (src)),
+ SUBREG_BYTE (src),
+ GET_MODE (src));
+ else
+ offset += (SUBREG_BYTE (src)
+ / REGMODE_NATURAL_SIZE (GET_MODE (src)));
}
else
return;
@@ -1616,7 +1615,15 @@ set_preference (dest, src)
else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
{
dest_regno = REGNO (SUBREG_REG (dest));
- offset -= SUBREG_WORD (dest);
+
+ if (REGNO (SUBREG_REG (dest)) < FIRST_PSEUDO_REGISTER)
+ offset -= subreg_regno_offset (REGNO (SUBREG_REG (dest)),
+ GET_MODE (SUBREG_REG (dest)),
+ SUBREG_BYTE (dest),
+ GET_MODE (dest));
+ else
+ offset -= (SUBREG_BYTE (dest)
+ / REGMODE_NATURAL_SIZE (GET_MODE (dest)));
}
else
return;
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index f0df3da0371..b642643f3ae 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -557,10 +557,7 @@ noce_emit_move_insn (x, y)
inner = XEXP (outer, 0);
outmode = GET_MODE (outer);
inmode = GET_MODE (inner);
- bitpos = SUBREG_WORD (outer) * BITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- bitpos += (GET_MODE_BITSIZE (inmode) - GET_MODE_BITSIZE (outmode))
- % BITS_PER_WORD;
+ bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
store_bit_field (inner, GET_MODE_BITSIZE (outmode),
bitpos, outmode, y, GET_MODE_BITSIZE (inmode),
GET_MODE_BITSIZE (inmode));
diff --git a/gcc/integrate.c b/gcc/integrate.c
index ed6540e4bfd..327e8fa5f25 100644
--- a/gcc/integrate.c
+++ b/gcc/integrate.c
@@ -1895,23 +1895,33 @@ copy_rtx_and_substitute (orig, map, for_lhs)
copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
/* SUBREG is ordinary, but don't make nested SUBREGs. */
if (GET_CODE (copy) == SUBREG)
- return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
- SUBREG_WORD (orig) + SUBREG_WORD (copy));
+ {
+ int final_offset = SUBREG_BYTE (orig) + SUBREG_BYTE (copy);
+
+ /* When working with SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
+ final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
+ return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
+ final_offset);
+ }
else if (GET_CODE (copy) == CONCAT)
{
rtx retval = subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1);
+ int final_offset;
if (GET_MODE (retval) == GET_MODE (orig))
return retval;
- else
- return gen_rtx_SUBREG (GET_MODE (orig), retval,
- (SUBREG_WORD (orig) %
- (GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)))
- / (unsigned) UNITS_PER_WORD)));
+
+ final_offset = SUBREG_BYTE (orig) %
+ GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)));
+ final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
+ final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
+ return gen_rtx_SUBREG (GET_MODE (orig), retval, final_offset);
}
else
return gen_rtx_SUBREG (GET_MODE (orig), copy,
- SUBREG_WORD (orig));
+ SUBREG_BYTE (orig));
case ADDRESSOF:
copy = gen_rtx_ADDRESSOF (mode,
@@ -2397,8 +2407,8 @@ subst_constants (loc, insn, map, memonly)
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
&& GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
- new = operand_subword (inner, SUBREG_WORD (x), 0,
- GET_MODE (SUBREG_REG (x)));
+ new = operand_subword (inner, SUBREG_BYTE (x) / UNITS_PER_WORD,
+ 0, GET_MODE (SUBREG_REG (x)));
cancel_changes (num_changes);
if (new == 0 && subreg_lowpart_p (x))
@@ -2675,7 +2685,12 @@ mark_stores (dest, x, data)
regno = REGNO (dest), mode = GET_MODE (dest);
else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
{
- regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
+ regno = REGNO (SUBREG_REG (dest));
+ if (regno < FIRST_PSEUDO_REGISTER)
+ regno += subreg_regno_offset (REGNO (SUBREG_REG (dest)),
+ GET_MODE (SUBREG_REG (dest)),
+ SUBREG_BYTE (dest),
+ GET_MODE (dest));
mode = GET_MODE (SUBREG_REG (dest));
}
diff --git a/gcc/jump.c b/gcc/jump.c
index 2b111d4bd59..5c5807394dc 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -3543,7 +3543,7 @@ rtx_renumbered_equal_p (x, y)
&& GET_CODE (SUBREG_REG (y)) == REG)))
{
int reg_x = -1, reg_y = -1;
- int word_x = 0, word_y = 0;
+ int byte_x = 0, byte_y = 0;
if (GET_MODE (x) != GET_MODE (y))
return 0;
@@ -3556,15 +3556,17 @@ rtx_renumbered_equal_p (x, y)
if (code == SUBREG)
{
reg_x = REGNO (SUBREG_REG (x));
- word_x = SUBREG_WORD (x);
+ byte_x = SUBREG_BYTE (x);
if (reg_renumber[reg_x] >= 0)
{
- reg_x = reg_renumber[reg_x] + word_x;
- word_x = 0;
+ reg_x = subreg_regno_offset (reg_renumber[reg_x],
+ GET_MODE (SUBREG_REG (x)),
+ byte_x,
+ GET_MODE (x));
+ byte_x = 0;
}
}
-
else
{
reg_x = REGNO (x);
@@ -3575,15 +3577,17 @@ rtx_renumbered_equal_p (x, y)
if (GET_CODE (y) == SUBREG)
{
reg_y = REGNO (SUBREG_REG (y));
- word_y = SUBREG_WORD (y);
+ byte_y = SUBREG_BYTE (y);
if (reg_renumber[reg_y] >= 0)
{
- reg_y = reg_renumber[reg_y];
- word_y = 0;
+ reg_y = subreg_regno_offset (reg_renumber[reg_y],
+ GET_MODE (SUBREG_REG (y)),
+ byte_y,
+ GET_MODE (y));
+ byte_y = 0;
}
}
-
else
{
reg_y = REGNO (y);
@@ -3591,7 +3595,7 @@ rtx_renumbered_equal_p (x, y)
reg_y = reg_renumber[reg_y];
}
- return reg_x >= 0 && reg_x == reg_y && word_x == word_y;
+ return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
}
/* Now we have disposed of all the cases
@@ -3722,7 +3726,9 @@ true_regnum (x)
{
int base = true_regnum (SUBREG_REG (x));
if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
- return SUBREG_WORD (x) + base;
+ return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x), GET_MODE (x));
}
return -1;
}
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index c743ad63fe8..c83d4f145f5 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -1813,25 +1813,49 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
may_save_copy = 0;
- offset += SUBREG_WORD (usedreg);
+ if (REGNO (SUBREG_REG (usedreg)) < FIRST_PSEUDO_REGISTER)
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (usedreg)),
+ GET_MODE (SUBREG_REG (usedreg)),
+ SUBREG_BYTE (usedreg),
+ GET_MODE (usedreg));
+ else
+ offset += (SUBREG_BYTE (usedreg)
+ / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
usedreg = SUBREG_REG (usedreg);
}
if (GET_CODE (usedreg) != REG)
return 0;
ureg = REGNO (usedreg);
- usize = REG_SIZE (usedreg);
+ if (ureg < FIRST_PSEUDO_REGISTER)
+ usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
+ else
+ usize = ((GET_MODE_SIZE (GET_MODE (usedreg))
+ + (REGMODE_NATURAL_SIZE (GET_MODE (usedreg)) - 1))
+ / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
while (GET_CODE (setreg) == SUBREG)
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (setreg))) > UNITS_PER_WORD)
may_save_copy = 0;
- offset -= SUBREG_WORD (setreg);
+ if (REGNO (SUBREG_REG (setreg)) < FIRST_PSEUDO_REGISTER)
+ offset -= subreg_regno_offset (REGNO (SUBREG_REG (setreg)),
+ GET_MODE (SUBREG_REG (setreg)),
+ SUBREG_BYTE (setreg),
+ GET_MODE (setreg));
+ else
+ offset -= (SUBREG_BYTE (setreg)
+ / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
setreg = SUBREG_REG (setreg);
}
if (GET_CODE (setreg) != REG)
return 0;
sreg = REGNO (setreg);
- ssize = REG_SIZE (setreg);
+ if (sreg < FIRST_PSEUDO_REGISTER)
+ ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
+ else
+ ssize = ((GET_MODE_SIZE (GET_MODE (setreg))
+ + (REGMODE_NATURAL_SIZE (GET_MODE (setreg)) - 1))
+ / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
/* If UREG is a pseudo-register that hasn't already been assigned a
quantity number, it means that it is not local to this block or dies
@@ -2032,7 +2056,11 @@ reg_is_born (reg, birth)
register int regno;
if (GET_CODE (reg) == SUBREG)
- regno = REGNO (SUBREG_REG (reg)) + SUBREG_WORD (reg);
+ {
+ regno = REGNO (SUBREG_REG (reg));
+ if (regno < FIRST_PSEUDO_REGISTER)
+ regno = subreg_hard_regno (reg, 1);
+ }
else
regno = REGNO (reg);
diff --git a/gcc/recog.c b/gcc/recog.c
index 1596a019067..e278f985529 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -517,13 +517,15 @@ validate_replace_rtx_1 (loc, from, to, object)
if (GET_CODE (XEXP (x, 0)) == SUBREG)
{
if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD)
- to = operand_subword (to, SUBREG_WORD (XEXP (x, 0)),
+ to = operand_subword (to,
+ (SUBREG_BYTE (XEXP (x, 0))
+ / UNITS_PER_WORD),
0, GET_MODE (from));
else if (GET_MODE_CLASS (GET_MODE (from)) == MODE_INT
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
<= HOST_BITS_PER_WIDE_INT))
{
- int i = SUBREG_WORD (XEXP (x, 0)) * BITS_PER_WORD;
+ int i = SUBREG_BYTE (XEXP (x, 0)) * BITS_PER_UNIT;
HOST_WIDE_INT valh;
unsigned HOST_WIDE_INT vall;
@@ -569,26 +571,21 @@ validate_replace_rtx_1 (loc, from, to, object)
break;
case SUBREG:
- /* In case we are replacing by constant, attempt to simplify it to non-SUBREG
- expression. We can't do this later, since the information about inner mode
- may be lost. */
+ /* In case we are replacing by constant, attempt to simplify it to
+ non-SUBREG expression. We can't do this later, since the information
+ about inner mode may be lost. */
if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
{
- if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
- && GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
- {
- rtx temp = operand_subword (to, SUBREG_WORD (x),
- 0, GET_MODE (from));
- if (temp)
- {
- validate_change (object, loc, temp, 1);
- return;
- }
- }
- if (subreg_lowpart_p (x))
+ int offset, part;
+ unsigned HOST_WIDE_INT val;
+
+ /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
+ since we are saying that the high bits don't matter. */
+ if (GET_MODE (to) == VOIDmode
+ && (GET_MODE_SIZE (GET_MODE (x))
+ >= GET_MODE_SIZE (GET_MODE (from))))
{
- rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
+ rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
if (new)
{
validate_change (object, loc, new, 1);
@@ -596,13 +593,67 @@ validate_replace_rtx_1 (loc, from, to, object)
}
}
- /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
- since we are saying that the high bits don't matter. */
- if (GET_MODE (to) == VOIDmode
- && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (from)))
+ offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
+ switch (GET_CODE (to))
{
- validate_change (object, loc, to, 1);
- return;
+ case CONST_DOUBLE:
+ if (GET_MODE (to) != VOIDmode)
+ break;
+
+ part = offset >= HOST_BITS_PER_WIDE_INT;
+ if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
+ && BYTES_BIG_ENDIAN)
+ || (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
+ && WORDS_BIG_ENDIAN))
+ part = !part;
+ val = part ? CONST_DOUBLE_HIGH (to) : CONST_DOUBLE_LOW (to);
+ offset %= HOST_BITS_PER_WIDE_INT;
+
+ /* FALLTHROUGH */
+ case CONST_INT:
+ if (GET_CODE (to) == CONST_INT)
+ val = INTVAL (to);
+
+ {
+ /* Avoid creating bogus SUBREGs */
+ enum machine_mode mode = GET_MODE (x);
+ enum machine_mode inner_mode = GET_MODE (from);
+
+ /* We've already picked the word we want from a double, so
+ pretend this is actually an integer. */
+ if (GET_CODE (to) == CONST_DOUBLE)
+ inner_mode = SImode;
+
+ if (GET_MODE_CLASS (mode) != MODE_INT)
+ abort ();
+
+ if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
+ {
+ if (WORDS_BIG_ENDIAN)
+ offset = GET_MODE_BITSIZE (inner_mode)
+ - GET_MODE_BITSIZE (mode) - offset;
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
+ && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+ offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode)
+ - 2 * (offset % BITS_PER_WORD);
+ }
+
+ if (offset >= HOST_BITS_PER_WIDE_INT)
+ to = ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
+ else
+ {
+ val >>= offset;
+ if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
+ val = trunc_int_for_mode (val, mode);
+ to = GEN_INT (val);
+ }
+
+ validate_change (object, loc, to, 1);
+ return;
+ }
+
+ default:
+ break;
}
}
@@ -612,15 +663,26 @@ validate_replace_rtx_1 (loc, from, to, object)
&& rtx_equal_p (SUBREG_REG (x), from))
{
if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
- && SUBREG_WORD (x) == 0 && SUBREG_WORD (to) == 0)
+ && SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0)
{
validate_change (object, loc, SUBREG_REG (to), 1);
return;
}
- validate_change (object, loc,
- gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
- SUBREG_WORD (x) + SUBREG_WORD (to)), 1);
+ /* Make sure the 2 byte counts added together are an even unit
+ of x's mode, and combine them if so. Otherwise we run
+ into problems with something like:
+ (subreg:HI (subreg:QI (SI:55) 3) 0)
+ we end up with an odd offset into a HI which is invalid. */
+
+ if (SUBREG_BYTE (to) % GET_MODE_SIZE (GET_MODE (x)) == 0)
+ validate_change (object, loc,
+ gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
+ SUBREG_BYTE(x) + SUBREG_BYTE (to)),
+ 1);
+ else
+ validate_change (object, loc, to, 1);
+
return;
}
@@ -636,15 +698,10 @@ validate_replace_rtx_1 (loc, from, to, object)
&& ! MEM_VOLATILE_P (to)
&& GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
{
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
rtx new;
- if (BYTES_BIG_ENDIAN)
- offset += (MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
-
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
@@ -694,8 +751,8 @@ validate_replace_rtx_1 (loc, from, to, object)
int offset = pos / BITS_PER_UNIT;
rtx newmem;
- /* If the bytes and bits are counted differently, we
- must adjust the offset. */
+ /* If the bytes and bits are counted differently, we
+ must adjust the offset. */
if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode)
- offset);
@@ -1040,7 +1097,6 @@ general_operand (op, mode)
enum machine_mode mode;
{
register enum rtx_code code = GET_CODE (op);
- int mode_altering_drug = 0;
if (mode == VOIDmode)
mode = GET_MODE (op);
@@ -1078,11 +1134,6 @@ general_operand (op, mode)
op = SUBREG_REG (op);
code = GET_CODE (op);
-#if 0
- /* No longer needed, since (SUBREG (MEM...))
- will load the MEM into a reload reg in the MEM's own mode. */
- mode_altering_drug = 1;
-#endif
}
if (code == REG)
@@ -1113,8 +1164,6 @@ general_operand (op, mode)
return 0;
win:
- if (mode_altering_drug)
- return ! mode_dependent_address_p (XEXP (op, 0));
return 1;
}
@@ -1467,13 +1516,9 @@ indirect_operand (op, mode)
if (! reload_completed
&& GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
{
- register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
+ register int offset = SUBREG_BYTE (op);
rtx inner = SUBREG_REG (op);
- if (BYTES_BIG_ENDIAN)
- offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner))));
-
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
@@ -2482,7 +2527,10 @@ constrain_operands (strict)
{
if (GET_CODE (SUBREG_REG (op)) == REG
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
- offset = SUBREG_WORD (op);
+ offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
+ GET_MODE (SUBREG_REG (op)),
+ SUBREG_BYTE (op),
+ GET_MODE (op));
op = SUBREG_REG (op);
}
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 54c3f086a48..6c204467423 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -557,7 +557,11 @@ get_true_reg (pat)
rtx subreg;
if (FP_REG_P (subreg = SUBREG_REG (*pat)))
{
- *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
+ int regno_off = subreg_regno_offset (REGNO (subreg),
+ GET_MODE (subreg),
+ SUBREG_BYTE (*pat),
+ GET_MODE (*pat));
+ *pat = FP_MODE_REG (REGNO (subreg) + regno_off,
GET_MODE (subreg));
default:
return pat;
diff --git a/gcc/regmove.c b/gcc/regmove.c
index 26c4546fce3..227c662c537 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -717,7 +717,7 @@ optimize_reg_copy_3 (insn, dest, src)
/* Now walk forward making additional replacements. We want to be able
to undo all the changes if a later substitution fails. */
- subreg = gen_rtx_SUBREG (old_mode, src_reg, 0);
+ subreg = gen_lowpart_SUBREG (old_mode, src_reg);
while (p = NEXT_INSN (p), p != insn)
{
if (! INSN_P (p))
@@ -1168,7 +1168,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
{
src_subreg
= gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
- src, SUBREG_WORD (dst));
+ src, SUBREG_BYTE (dst));
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG
diff --git a/gcc/regs.h b/gcc/regs.h
index 08229666021..61b9a49ac02 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -24,12 +24,28 @@ Boston, MA 02111-1307, USA. */
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
-/* Get the number of consecutive hard regs required to hold the REG rtx R.
+/* Get the number of consecutive hard regs required to hold the REG or
+ SUBREG rtx R.
When something may be an explicit hard reg, REG_SIZE is the only
- valid way to get this value. You cannot get it from the regno. */
+ valid way to get this value. You cannot get it from the regno.
+ A target may override this definition, the case where you would do
+ this is where there are registers which are smaller than WORD_SIZE
+ such as the SFmode registers on sparc64. */
+
+#ifndef REG_SIZE
#define REG_SIZE(R) \
((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#endif
+
+/* When you only have the mode of a pseudo register before it has a hard
+ register chosen for it, this reports the size of each hard register
+ a pseudo in such a mode would get allocated to. Like REG_SIZE, a
+ target may override this. */
+
+#ifndef REGMODE_NATURAL_SIZE
+#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
+#endif
#ifndef SMALL_REGISTER_CLASSES
#define SMALL_REGISTER_CLASSES 0
diff --git a/gcc/reload.c b/gcc/reload.c
index 9849aed299b..ea5bea62331 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -791,7 +791,7 @@ reload_inner_reg_of_subreg (x, mode)
return 0;
/* If INNER is not ok for MODE, then INNER will need reloading. */
- if (! HARD_REGNO_MODE_OK (REGNO (inner) + SUBREG_WORD (x), mode))
+ if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
return 1;
/* If the outer part is a word or smaller, INNER larger than a
@@ -938,13 +938,12 @@ push_reload (in, out, inloc, outloc, class,
Finally, reload the inner expression if it is a register that is in
the class whose registers cannot be referenced in a different size
- and M1 is not the same size as M2. If SUBREG_WORD is nonzero, we
+ and M1 is not the same size as M2. If SUBREG_BYTE is nonzero, we
cannot reload just the inside since we might end up with the wrong
register class. But if it is inside a STRICT_LOW_PART, we have
no choice, so we hope we do get the right register class there. */
if (in != 0 && GET_CODE (in) == SUBREG
- && (SUBREG_WORD (in) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
@@ -978,7 +977,7 @@ push_reload (in, out, inloc, outloc, class,
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
/* The case where out is nonzero
is handled differently in the following statement. */
- && (out == 0 || SUBREG_WORD (in) == 0)
+ && (out == 0 || SUBREG_BYTE (in) == 0)
&& ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
> UNITS_PER_WORD)
@@ -986,9 +985,7 @@ push_reload (in, out, inloc, outloc, class,
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)))))
- || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (in))
- + SUBREG_WORD (in)),
- inmode)))
+ || ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
&& (SECONDARY_INPUT_RELOAD_CLASS (class,
@@ -1028,7 +1025,7 @@ push_reload (in, out, inloc, outloc, class,
that case. */
/* Similar issue for (SUBREG constant ...) if it was not handled by the
- code above. This can happen if SUBREG_WORD != 0. */
+ code above. This can happen if SUBREG_BYTE != 0. */
if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
{
@@ -1038,7 +1035,11 @@ push_reload (in, out, inloc, outloc, class,
RELOAD_OTHER, we are guaranteed that this inner reload will be
output before the outer reload. */
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
- find_valid_class (inmode, SUBREG_WORD (in)),
+ find_valid_class (inmode,
+ subreg_regno_offset (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)),
+ SUBREG_BYTE (in),
+ GET_MODE (in))),
VOIDmode, VOIDmode, 0, 0, opnum, type);
dont_remove_subreg = 1;
}
@@ -1050,7 +1051,7 @@ push_reload (in, out, inloc, outloc, class,
(except in the case of STRICT_LOW_PART,
and in that case the constraint should label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
- && (SUBREG_WORD (out) == 0 || strict_low)
+ && (SUBREG_BYTE (out) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
@@ -1080,9 +1081,7 @@ push_reload (in, out, inloc, outloc, class,
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)))))
- || ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (out))
- + SUBREG_WORD (out)),
- outmode)))
+ || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
&& (SECONDARY_OUTPUT_RELOAD_CLASS (class,
@@ -1129,7 +1128,11 @@ push_reload (in, out, inloc, outloc, class,
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
&SUBREG_REG (out),
- find_valid_class (outmode, SUBREG_WORD (out)),
+ find_valid_class (outmode,
+ subreg_regno_offset (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
+ GET_MODE (out))),
VOIDmode, VOIDmode, 0, 0,
opnum, RELOAD_OTHER);
}
@@ -1146,16 +1149,14 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
- in = gen_rtx_REG (GET_MODE (in),
- REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
+ in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
/* Similarly for OUT. */
if (out != 0 && GET_CODE (out) == SUBREG
&& GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
- out = gen_rtx_REG (GET_MODE (out),
- REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
+ out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
@@ -1810,15 +1811,28 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
|| GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
return 0;
+ /* Note that {in,out}_offset are needed only when 'in' or 'out'
+ respectively refers to a hard register. */
+
/* Find the inside of any subregs. */
while (GET_CODE (out) == SUBREG)
{
- out_offset = SUBREG_WORD (out);
+ if (GET_CODE (SUBREG_REG (out)) == REG
+ && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
+ out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
+ GET_MODE (out));
out = SUBREG_REG (out);
}
while (GET_CODE (in) == SUBREG)
{
- in_offset = SUBREG_WORD (in);
+ if (GET_CODE (SUBREG_REG (in)) == REG
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
+ in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)),
+ SUBREG_BYTE (in),
+ GET_MODE (in));
in = SUBREG_REG (in);
}
@@ -2035,7 +2049,10 @@ operands_match_p (x, y)
i = REGNO (SUBREG_REG (x));
if (i >= FIRST_PSEUDO_REGISTER)
goto slow;
- i += SUBREG_WORD (x);
+ i += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x));
}
else
i = REGNO (x);
@@ -2045,7 +2062,10 @@ operands_match_p (x, y)
j = REGNO (SUBREG_REG (y));
if (j >= FIRST_PSEUDO_REGISTER)
goto slow;
- j += SUBREG_WORD (y);
+ j += subreg_regno_offset (REGNO (SUBREG_REG (y)),
+ GET_MODE (SUBREG_REG (y)),
+ SUBREG_BYTE (y),
+ GET_MODE (y));
}
else
j = REGNO (y);
@@ -2777,7 +2797,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
while (GET_CODE (operand) == SUBREG)
{
- offset += SUBREG_WORD (operand);
+ /* Offset only matters when operand is a REG and
+ it is a hard reg. This is because it is passed
+ to reg_fits_class_p if it is a REG and all pseudos
+ return 0 from that function. */
+ if (GET_CODE (SUBREG_REG (operand)) == REG
+ && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
+ {
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand));
+ }
operand = SUBREG_REG (operand);
/* Force reload if this is a constant or PLUS or if there may
be a problem accessing OPERAND in the outer mode. */
@@ -2828,6 +2859,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
)
#endif
)
+ /* This following hunk of code should no longer be
+ needed at all with SUBREG_BYTE. If you need this
+ code back, please explain to me why so I can
+ fix the real problem. -DaveM */
+#if 0
/* Subreg of a hard reg which can't handle the subreg's mode
or which would handle that mode in the wrong number of
registers for subregging to work. */
@@ -2841,7 +2877,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
!= HARD_REGNO_NREGS (REGNO (operand),
GET_MODE (operand))))
|| ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
- operand_mode[i]))))
+ operand_mode[i])))
+#endif
+ )
force_reload = 1;
}
@@ -3716,7 +3754,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx operand = recog_data.operand[i];
while (GET_CODE (operand) == SUBREG)
- operand = XEXP (operand, 0);
+ operand = SUBREG_REG (operand);
if ((GET_CODE (operand) == MEM
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
@@ -3766,7 +3804,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
operand = *recog_data.operand_loc[i];
while (GET_CODE (operand) == SUBREG)
- operand = XEXP (operand, 0);
+ operand = SUBREG_REG (operand);
if (GET_CODE (operand) == REG)
{
if (modified[i] != RELOAD_WRITE)
@@ -3789,7 +3827,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx operand = recog_data.operand[i];
while (GET_CODE (operand) == SUBREG)
- operand = XEXP (operand, 0);
+ operand = SUBREG_REG (operand);
if ((GET_CODE (operand) == MEM
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
@@ -4303,7 +4341,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
&& regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0
&& (tem = operand_subword (reg_equiv_constant[regno],
- SUBREG_WORD (x), 0,
+ SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)))) != 0)
{
/* TEM is now a word sized constant for the bits from X that
@@ -4329,7 +4367,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
&& (GET_MODE_SIZE (GET_MODE (x))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
- int shift = SUBREG_WORD (x) * BITS_PER_WORD;
+ int shift = SUBREG_BYTE (x) * BITS_PER_UNIT;
if (WORDS_BIG_ENDIAN)
shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- GET_MODE_BITSIZE (GET_MODE (x))
@@ -4383,13 +4421,18 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
the meaning of the memory access. */
enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
+ /* SUBREG_REG (x) is a MEM, so we cant take the offset, instead we
+ calculate the register number as :
+ SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode) */
if (is_set_dest)
push_reload (NULL_RTX, SUBREG_REG (x), NULL_PTR, &SUBREG_REG (x),
- find_valid_class (subreg_mode, SUBREG_WORD (x)),
+ find_valid_class (subreg_mode,
+ SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
VOIDmode, subreg_mode, 0, 0, opnum, type);
else
push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), NULL_PTR,
- find_valid_class (subreg_mode, SUBREG_WORD (x)),
+ find_valid_class (subreg_mode,
+ SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
subreg_mode, VOIDmode, 0, 0, opnum, type);
}
@@ -5075,7 +5118,11 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
code0 = GET_CODE (op0);
if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
op0 = gen_rtx_REG (word_mode,
- REGNO (op0) + SUBREG_WORD (orig_op0));
+ (REGNO (op0) +
+ subreg_regno_offset (REGNO (SUBREG_REG (orig_op0)),
+ GET_MODE (SUBREG_REG (orig_op0)),
+ SUBREG_BYTE (orig_op0),
+ GET_MODE (orig_op0))));
}
if (GET_CODE (op1) == SUBREG)
@@ -5083,8 +5130,14 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
+ /* ??? Why is this given op1's mode and above for
+ ??? op0 SUBREGs we use word_mode? */
op1 = gen_rtx_REG (GET_MODE (op1),
- REGNO (op1) + SUBREG_WORD (orig_op1));
+ (REGNO (op1) +
+ subreg_regno_offset (REGNO (SUBREG_REG (orig_op1)),
+ GET_MODE (SUBREG_REG (orig_op1)),
+ SUBREG_BYTE (orig_op1),
+ GET_MODE (orig_op1))));
}
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
@@ -5492,7 +5545,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
needless copies if SUBREG_REG is multi-word. */
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
- int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ int regno = subreg_regno (x);
if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
@@ -5646,15 +5699,10 @@ find_reloads_subreg_address (x, force_replace, opnum, type,
if (force_replace
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ int offset = SUBREG_BYTE (x);
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
- if (BYTES_BIG_ENDIAN)
- {
- offset += MIN (inner_size, UNITS_PER_WORD);
- offset -= MIN (outer_size, UNITS_PER_WORD);
- }
XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
PUT_MODE (tem, GET_MODE (x));
@@ -5741,8 +5789,18 @@ subst_reloads (insn)
*r->subreg_loc = SUBREG_REG (reloadreg);
else
{
+ int final_offset =
+ SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
+
+ /* When working with SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset /
+ GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
+ final_offset = (final_offset *
+ GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
+
*r->where = SUBREG_REG (reloadreg);
- SUBREG_WORD (*r->subreg_loc) += SUBREG_WORD (reloadreg);
+ SUBREG_BYTE (*r->subreg_loc) = final_offset;
}
}
else
@@ -5843,12 +5901,24 @@ find_replacement (loc)
if (GET_CODE (reloadreg) == REG)
return gen_rtx_REG (GET_MODE (*loc),
- REGNO (reloadreg) + SUBREG_WORD (*loc));
+ (REGNO (reloadreg) +
+ subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
+ GET_MODE (SUBREG_REG (*loc)),
+ SUBREG_BYTE (*loc),
+ GET_MODE (*loc))));
else if (GET_MODE (reloadreg) == GET_MODE (*loc))
return reloadreg;
else
- return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
- SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc));
+ {
+ int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
+
+ /* When working with SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
+ final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
+ return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
+ final_offset);
+ }
}
}
@@ -5925,7 +5995,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
- unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
@@ -6020,7 +6090,10 @@ reg_overlap_mentioned_for_reload_p (x, in)
{
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
- regno += SUBREG_WORD (x);
+ regno += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x));
}
else if (GET_CODE (x) == REG)
{
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 6194b875244..16cc3be5d60 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -2509,7 +2509,7 @@ eliminate_regs (x, mem_mode, insn)
return x;
case SUBREG:
- /* Similar to above processing, but preserve SUBREG_WORD.
+ /* Similar to above processing, but preserve SUBREG_BYTE.
Convert (subreg (mem)) to (mem) if not paradoxical.
Also, if we have a non-paradoxical (subreg (pseudo)) and the
pseudo didn't get a hard reg, we must replace this with the
@@ -2526,7 +2526,7 @@ eliminate_regs (x, mem_mode, insn)
else
new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
- if (new != XEXP (x, 0))
+ if (new != SUBREG_REG (x))
{
int x_size = GET_MODE_SIZE (GET_MODE (x));
int new_size = GET_MODE_SIZE (GET_MODE (new));
@@ -2547,20 +2547,15 @@ eliminate_regs (x, mem_mode, insn)
|| (x_size == new_size))
)
{
- int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
- if (BYTES_BIG_ENDIAN)
- offset += (MIN (UNITS_PER_WORD,
- GET_MODE_SIZE (GET_MODE (new)))
- - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
-
PUT_MODE (new, mode);
XEXP (new, 0) = plus_constant (XEXP (new, 0), offset);
return new;
}
else
- return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_WORD (x));
+ return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
}
return x;
@@ -4088,10 +4083,14 @@ forget_old_reloads_1 (x, ignored, data)
unsigned int nr;
int offset = 0;
- /* note_stores does give us subregs of hard regs. */
+ /* note_stores does give us subregs of hard regs,
+ subreg_regno_offset will abort if it is not a hard reg. */
while (GET_CODE (x) == SUBREG)
{
- offset += SUBREG_WORD (x);
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x));
x = SUBREG_REG (x);
}
@@ -5401,7 +5400,7 @@ choose_reload_regs (chain)
if (inheritance)
{
- int word = 0;
+ int byte = 0;
register int regno = -1;
enum machine_mode mode = VOIDmode;
@@ -5420,10 +5419,10 @@ choose_reload_regs (chain)
else if (GET_CODE (rld[r].in_reg) == SUBREG
&& GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
{
- word = SUBREG_WORD (rld[r].in_reg);
+ byte = SUBREG_BYTE (rld[r].in_reg);
regno = REGNO (SUBREG_REG (rld[r].in_reg));
if (regno < FIRST_PSEUDO_REGISTER)
- regno += word;
+ regno = subreg_regno (rld[r].in_reg);
mode = GET_MODE (rld[r].in_reg);
}
#ifdef AUTO_INC_DEC
@@ -5444,7 +5443,7 @@ choose_reload_regs (chain)
that can invalidate an inherited reload of part of a pseudoreg. */
else if (GET_CODE (rld[r].in) == SUBREG
&& GET_CODE (SUBREG_REG (rld[r].in)) == REG)
- regno = REGNO (SUBREG_REG (rld[r].in)) + SUBREG_WORD (rld[r].in);
+ regno = subreg_regno (rld[r].in);
#endif
if (regno >= 0 && reg_last_reload_reg[regno] != 0)
@@ -5453,15 +5452,15 @@ choose_reload_regs (chain)
rtx last_reg = reg_last_reload_reg[regno];
enum machine_mode need_mode;
- i = REGNO (last_reg) + word;
+ i = REGNO (last_reg);
+ i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
last_class = REGNO_REG_CLASS (i);
- if (word == 0)
+ if (byte == 0)
need_mode = mode;
else
need_mode
- = smallest_mode_for_size (GET_MODE_SIZE (mode)
- + word * UNITS_PER_WORD,
+ = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
GET_MODE_CLASS (mode));
if (
@@ -5631,7 +5630,7 @@ choose_reload_regs (chain)
Make a new REG since this might be used in an
address and not all machines support SUBREGs
there. */
- regno = REGNO (SUBREG_REG (equiv)) + SUBREG_WORD (equiv);
+ regno = subreg_regno (equiv);
equiv = gen_rtx_REG (rld[r].mode, regno);
}
else
@@ -6261,7 +6260,7 @@ emit_input_reload_insns (chain, rl, old, j)
oldequiv = SUBREG_REG (oldequiv);
if (GET_MODE (oldequiv) != VOIDmode
&& mode != GET_MODE (oldequiv))
- oldequiv = gen_rtx_SUBREG (mode, oldequiv, 0);
+ oldequiv = gen_lowpart_SUBREG (mode, oldequiv);
/* Switch to the right place to emit the reload insns. */
switch (rl->when_needed)
@@ -8885,7 +8884,10 @@ reload_combine_note_store (dst, set, data)
if (GET_CODE (dst) == SUBREG)
{
- regno = SUBREG_WORD (dst);
+ regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
+ GET_MODE (SUBREG_REG (dst)),
+ SUBREG_BYTE (dst),
+ GET_MODE (dst));
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG)
@@ -9276,7 +9278,10 @@ move2add_note_store (dst, set, data)
if (GET_CODE (dst) == SUBREG)
{
- regno = SUBREG_WORD (dst);
+ regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
+ GET_MODE (SUBREG_REG (dst)),
+ SUBREG_BYTE (dst),
+ GET_MODE (dst));
dst = SUBREG_REG (dst);
}
diff --git a/gcc/resource.c b/gcc/resource.c
index 0b3a892ce2c..17f7d034d93 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -100,7 +100,7 @@ update_live_status (dest, x, data)
return;
if (GET_CODE (dest) == SUBREG)
- first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
+ first_regno = subreg_regno (dest);
else
first_regno = REGNO (dest);
@@ -222,7 +222,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
mark_referenced_resources (SUBREG_REG (x), res, 0);
else
{
- unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ unsigned int regno = subreg_regno (x);
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
@@ -780,7 +780,7 @@ mark_set_resources (x, res, in_dest, mark_type)
mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
else
{
- unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ unsigned int regno = subreg_regno (x);
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
diff --git a/gcc/rtl.h b/gcc/rtl.h
index dbadd70f958..e4f2ab03714 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -789,10 +789,17 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
#define CONST_DOUBLE_MEM(r) XCEXP (r, 0, CONST_DOUBLE)
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
- SUBREG_WORD extracts the word-number. */
+ SUBREG_BYTE extracts the byte-number. */
#define SUBREG_REG(RTX) XCEXP(RTX, 0, SUBREG)
-#define SUBREG_WORD(RTX) XCUINT(RTX, 1, SUBREG)
+#define SUBREG_BYTE(RTX) XCUINT(RTX, 1, SUBREG)
+
+/* in rtlanal.c */
+extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
+ enum machine_mode,
+ unsigned int,
+ enum machine_mode));
+extern unsigned int subreg_regno PARAMS ((rtx));
/* 1 if the REG contained in SUBREG_REG is already known to be
sign- or zero-extended from the mode of the SUBREG to the mode of
@@ -1179,6 +1186,7 @@ extern int rtx_equal_p PARAMS ((rtx, rtx));
extern rtvec gen_rtvec_v PARAMS ((int, rtx *));
extern rtx gen_reg_rtx PARAMS ((enum machine_mode));
extern rtx gen_label_rtx PARAMS ((void));
+extern int subreg_hard_regno PARAMS ((rtx, int));
extern rtx gen_lowpart_common PARAMS ((enum machine_mode, rtx));
extern rtx gen_lowpart PARAMS ((enum machine_mode, rtx));
@@ -1191,6 +1199,8 @@ extern rtx gen_realpart PARAMS ((enum machine_mode, rtx));
extern rtx gen_imagpart PARAMS ((enum machine_mode, rtx));
extern rtx operand_subword PARAMS ((rtx, unsigned int, int,
enum machine_mode));
+extern rtx constant_subword PARAMS ((rtx, int,
+ enum machine_mode));
/* In emit-rtl.c */
extern rtx operand_subword_force PARAMS ((rtx, unsigned int,
@@ -1569,8 +1579,11 @@ extern rtx gen_rtx_CONST_DOUBLE PARAMS ((enum machine_mode, rtx,
extern rtx gen_rtx_CONST_INT PARAMS ((enum machine_mode, HOST_WIDE_INT));
extern rtx gen_raw_REG PARAMS ((enum machine_mode, int));
extern rtx gen_rtx_REG PARAMS ((enum machine_mode, int));
+extern rtx gen_rtx_SUBREG PARAMS ((enum machine_mode, rtx, int));
extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
+extern rtx gen_lowpart_SUBREG PARAMS ((enum machine_mode, rtx));
+
/* We need the cast here to ensure that we get the same result both with
and without prototypes. */
#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (HOST_WIDE_INT) (N))
diff --git a/gcc/rtl.texi b/gcc/rtl.texi
index cfae3a9b987..665a40766c7 100644
--- a/gcc/rtl.texi
+++ b/gcc/rtl.texi
@@ -1166,16 +1166,16 @@ This virtual register is replaced by the sum of the register given by
@end table
@findex subreg
-@item (subreg:@var{m} @var{reg} @var{wordnum})
+@item (subreg:@var{m} @var{reg} @var{bytenum})
@code{subreg} expressions are used to refer to a register in a machine
mode other than its natural one, or to refer to one register of
-a multi-word @code{reg} that actually refers to several registers.
+a multi-part @code{reg} that actually refers to several registers.
Each pseudo-register has a natural mode. If it is necessary to
operate on it in a different mode---for example, to perform a fullword
move instruction on a pseudo-register that contains a single
byte---the pseudo-register must be enclosed in a @code{subreg}. In
-such a case, @var{wordnum} is zero.
+such a case, @var{bytenum} is zero.
Usually @var{m} is at least as narrow as the mode of @var{reg}, in which
case it is restricting consideration to only the bits of @var{reg} that
@@ -1192,7 +1192,7 @@ a multi-register value. Machine modes such as @code{DImode} and
@code{TImode} can indicate values longer than a word, values which
usually require two or more consecutive registers. To access one of the
registers, use a @code{subreg} with mode @code{SImode} and a
-@var{wordnum} that says which register.
+@var{bytenum} offset that says which register.
Storing in a non-paradoxical @code{subreg} has undefined results for
bits belonging to the same word as the @code{subreg}. This laxity makes
@@ -1202,8 +1202,13 @@ the @code{subreg}, use @code{strict_low_part} around the @code{subreg}.
@cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
-that word number zero is the most significant part; otherwise, it is
-the least significant part.
+that byte number zero is part of the most significant word; otherwise,
+it is part of the least significant word.
+
+@cindex @code{BYTES_BIG_ENDIAN}, effect on @code{subreg}
+The compilation parameter @code{BYTES_BIG_ENDIAN}, if set to 1, says
+that byte number zero is the most significant byte within a word;
+otherwise, it is the least significant byte within a word.
@cindex @code{FLOAT_WORDS_BIG_ENDIAN}, (lack of) effect on @code{subreg}
On a few targets, @code{FLOAT_WORDS_BIG_ENDIAN} disagrees with
@@ -1239,10 +1244,10 @@ a single machine register. The reload pass prevents @code{subreg}
expressions such as these from being formed.
@findex SUBREG_REG
-@findex SUBREG_WORD
+@findex SUBREG_BYTE
The first operand of a @code{subreg} expression is customarily accessed
with the @code{SUBREG_REG} macro and the second operand is customarily
-accessed with the @code{SUBREG_WORD} macro.
+accessed with the @code{SUBREG_BYTE} macro.
@findex scratch
@cindex scratch operands
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index db8e6968010..36c3c9ff42f 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1083,7 +1083,7 @@ refers_to_regno_p (regno, endregno, x, loc)
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
- unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+ unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
@@ -1170,7 +1170,7 @@ reg_overlap_mentioned_p (x, in)
case SUBREG:
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
- regno += SUBREG_WORD (x);
+ regno = subreg_regno (x);
goto do_reg;
case REG:
@@ -2229,18 +2229,32 @@ replace_regs (x, reg_map, nregs, replace_dest)
return map_inner;
else
{
+ int final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (map_val);
+
+ /* When working with REG SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (x)));
+ final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (x)));
+
/* We cannot call gen_rtx here since we may be linked with
genattrtab.c. */
/* Let's try clobbering the incoming SUBREG and see
if this is really safe. */
SUBREG_REG (x) = map_inner;
- SUBREG_WORD (x) += SUBREG_WORD (map_val);
+ SUBREG_BYTE (x) = final_offset;
return x;
#if 0
rtx new = rtx_alloc (SUBREG);
+ int final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (map_val);
+
+ /* When working with REG SUBREGs the rule is that the byte
+ offset must be a multiple of the SUBREG's mode. */
+ final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (x)));
+ final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (x)));
+
PUT_MODE (new, GET_MODE (x));
SUBREG_REG (new) = map_inner;
- SUBREG_WORD (new) = SUBREG_WORD (x) + SUBREG_WORD (map_val);
+ SUBREG_BYTE (new) = final_offset;
#endif
}
}
@@ -2613,3 +2627,65 @@ loc_mentioned_in_p (loc, in)
}
return 0;
}
+
+/* This function returns the regno offset of a subreg expression.
+ xregno - A regno of an inner hard subreg_reg (or what will become one).
+ xmode - The mode of xregno.
+ offset - The byte offset.
+ ymode - The mode of a top level SUBREG (or what may become one).
+ RETURN - The regno offset which would be used.
+ This function can be overridden by defining SUBREG_REGNO_OFFSET,
+ taking the same parameters. */
+unsigned int
+subreg_regno_offset (xregno, xmode, offset, ymode)
+ unsigned int xregno;
+ enum machine_mode xmode;
+ unsigned int offset;
+ enum machine_mode ymode;
+{
+ unsigned ret;
+ int nregs_xmode, nregs_ymode;
+ int mode_multiple, nregs_multiple;
+ int y_offset;
+
+/* Check for an override, and use it instead. */
+#ifdef SUBREG_REGNO_OFFSET
+ ret = SUBREG_REGNO_OFFSET (xregno, xmode, offset, ymode)
+#else
+ if (xregno >= FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
+ nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+ if (offset == 0 || nregs_xmode == nregs_ymode)
+ return 0;
+
+ /* size of ymode must not be greater than the size of xmode. */
+ mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+ if (mode_multiple == 0)
+ abort ();
+
+ y_offset = offset / GET_MODE_SIZE (ymode);
+ nregs_multiple = nregs_xmode / nregs_ymode;
+ ret = (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
+#endif
+
+ return ret;
+}
+
+/* Return the final regno that a subreg expression refers to. */
+unsigned int
+subreg_regno (x)
+ rtx x;
+{
+ unsigned int ret;
+ rtx subreg = SUBREG_REG (x);
+ int regno = REGNO (subreg);
+
+ ret = regno + subreg_regno_offset (regno,
+ GET_MODE (subreg),
+ SUBREG_BYTE (x),
+ GET_MODE (x));
+ return ret;
+
+}
diff --git a/gcc/sched-vis.c b/gcc/sched-vis.c
index 4cd07790130..4aad9f931c1 100644
--- a/gcc/sched-vis.c
+++ b/gcc/sched-vis.c
@@ -591,7 +591,7 @@ print_value (buf, x, verbose)
case SUBREG:
print_value (t, SUBREG_REG (x), verbose);
cur = safe_concat (buf, cur, t);
- sprintf (t, "#%d", SUBREG_WORD (x));
+ sprintf (t, "#%d", SUBREG_BYTE (x));
cur = safe_concat (buf, cur, t);
break;
case SCRATCH:
diff --git a/gcc/sdbout.c b/gcc/sdbout.c
index 649bc0aa67d..dfccee06f79 100644
--- a/gcc/sdbout.c
+++ b/gcc/sdbout.c
@@ -776,19 +776,15 @@ sdbout_symbol (decl, local)
else if (GET_CODE (value) == SUBREG)
{
int offset = 0;
+
while (GET_CODE (value) == SUBREG)
- {
- offset += SUBREG_WORD (value);
- value = SUBREG_REG (value);
- }
+ value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
- regno = REGNO (value);
- if (regno >= FIRST_PSEUDO_REGISTER)
+ if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return;
- regno += offset;
}
- alter_subreg (DECL_RTL (decl));
+ regno = REGNO (alter_subreg (DECL_RTL (decl)));
value = DECL_RTL (decl);
}
/* Don't output anything if an auto variable
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 12f1562cbf6..e9c49dcffd4 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -4166,7 +4166,7 @@ expand_anon_union_decl (decl, cleanup, decl_elts)
if (mode == GET_MODE (x))
SET_DECL_RTL (decl_elt, x);
else
- SET_DECL_RTL (decl_elt, gen_rtx_SUBREG (mode, x, 0));
+ SET_DECL_RTL (decl_elt, gen_lowpart_SUBREG (mode, x));
}
else
abort ();
diff --git a/gcc/tm.texi b/gcc/tm.texi
index e3dd5309b20..1956979f1bd 100644
--- a/gcc/tm.texi
+++ b/gcc/tm.texi
@@ -1697,17 +1697,6 @@ definition of this macro is
/ UNITS_PER_WORD)
@end smallexample
-@findex ALTER_HARD_SUBREG
-@item ALTER_HARD_SUBREG (@var{tgt_mode}, @var{word}, @var{src_mode}, @var{regno})
-A C expression that returns an adjusted hard register number for
-
-@smallexample
-(subreg:@var{tgt_mode} (reg:@var{src_mode} @var{regno}) @var{word})
-@end smallexample
-
-This may be needed if the target machine has mixed sized big-endian
-registers, like Sparc v9.
-
@findex HARD_REGNO_MODE_OK
@item HARD_REGNO_MODE_OK (@var{regno}, @var{mode})
A C expression that is nonzero if it is permissible to store a value
@@ -1790,6 +1779,19 @@ allocation.
Define this macro if the compiler should avoid copies to/from @code{CCmode}
registers. You should only define this macro if support for copying to/from
@code{CCmode} is incomplete.
+
+@findex SUBREG_REGNO_OFFSET
+@item SUBREG_REGNO_OFFSET
+Define this macro if the compiler needs to handle subregs in a non-standard
+way. The macro returns the correct regno offset for mode @code{YMODE} given
+a subreg of type @code{XMODE}.
+This macro takes 4 parameters:
+@code{XREGNO} - A regno of an inner hard subreg_reg (or what will become one).
+@code{XMODE} - The mode of xregno.
+@code{OFFSET} - The byte offset.
+@code{YMODE} - The mode of a top level SUBREG (or what may become one).
+The default function can be found in rtlanal.c, function
+@code{subreg_regno_offset}. Normally this does not need to be defined.
@end table
@node Leaf Functions