]> gcc.gnu.org Git - gcc.git/commitdiff
Use byte offsets in SUBREGs instead of words.
authorJakub Jelinek <jakub@redhat.com>
Tue, 3 Apr 2001 15:06:12 +0000 (17:06 +0200)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 3 Apr 2001 15:06:12 +0000 (15:06 +0000)
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.

Co-Authored-By: Andrew MacLeod <amacleod@redhat.com>
Co-Authored-By: David S. Miller <davem@pierdol.cobaltmicro.com>
From-SVN: r41058

64 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/caller-save.c
gcc/calls.c
gcc/combine.c
gcc/config/a29k/a29k.c
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/d30v/d30v.c
gcc/config/dsp16xx/dsp16xx.md
gcc/config/h8300/h8300.md
gcc/config/i370/i370.md
gcc/config/i860/i860.c
gcc/config/i860/i860.md
gcc/config/i960/i960.md
gcc/config/m68hc11/m68hc11.c
gcc/config/m68k/m68k.md
gcc/config/m88k/m88k.md
gcc/config/mips/mips.c
gcc/config/mips/mips.md
gcc/config/mn10200/mn10200.c
gcc/config/mn10300/mn10300.c
gcc/config/ns32k/ns32k.md
gcc/config/pa/pa.c
gcc/config/pa/pa.md
gcc/config/pdp11/pdp11.md
gcc/config/romp/romp.c
gcc/config/sh/sh.c
gcc/config/sh/sh.h
gcc/config/sh/sh.md
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md
gcc/config/v850/v850.c
gcc/cse.c
gcc/dbxout.c
gcc/dwarf2out.c
gcc/dwarfout.c
gcc/emit-rtl.c
gcc/expmed.c
gcc/expr.c
gcc/final.c
gcc/flow.c
gcc/function.c
gcc/gengenrtl.c
gcc/global.c
gcc/ifcvt.c
gcc/integrate.c
gcc/jump.c
gcc/local-alloc.c
gcc/recog.c
gcc/reg-stack.c
gcc/regmove.c
gcc/regs.h
gcc/reload.c
gcc/reload1.c
gcc/resource.c
gcc/rtl.h
gcc/rtl.texi
gcc/rtlanal.c
gcc/sched-vis.c
gcc/sdbout.c
gcc/stmt.c
gcc/tm.texi

index e42b63a675b96ffc65f455a42240824a968d165f..a63667af04c9b83b3e6efa58b3b0690e004c4263 100644 (file)
@@ -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.
index a1f2e0b785cdb22fec923c58196816d77b2fe205..d69b38392fe6963ffaed9428a626d6922674a922 100644 (file)
@@ -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;
        }
index 787d45c818ef5ebf20ccf6b9884d7cf0d5386034..602159d5eb07e18df1dcbf265fb262ef601f4332 100644 (file)
@@ -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++)
index 228d9b8e112fdbf0c66385d4db15afd286d8d6a2..694eeeee4e603408beb21d40a3288720fc5069fc 100644 (file)
@@ -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;
        }
index 4aa7721e8807ad1120f18a6aebcdbe9224846619..ee5631c82636647eb9cc0e6f58d85f9d9060e404 100644 (file)
@@ -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);
     }
 }
 \f
@@ -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
index c6d7ba28e4a415ef0a953c5d9faaab556c8ad2c1..65c6240a3bc60f106e97cdcde34a479cee470aaa 100644 (file)
@@ -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);
index 18a61d6c7f6e252cd0db6acaa5b153e70bf964a9..c6aa2eec7faca045ceab07396da5a38675385355 100644 (file)
@@ -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
index 0f0c5e9d9a3186583f7ba11e1fbfd4834ce14c52..b89392efad2639962f8b310551e9469377344403 100644 (file)
@@ -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);
     }
 
index a4f5e8d847378b1d8907a4b931417240ab0932e1..b8f30aa7c5fcfc4f817a2fbcba63b4b56ff8ee59 100644 (file)
@@ -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);
index ce7fb96b8500eff04d10a4a55614627121f8a28a..4c65a89bfbe393b804f4a2be1658cbfc7ba85976 100644 (file)
   "
 {
        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"
   "
 {
        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));
 }")
 
 
index 2ea2463f91b7fe0880b909f72df4d97c23b973ca..d79750aeb23dacfa686558835342816ed41b19b4 100644 (file)
        (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")
                  (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"
index 614e3d6fb6ba0a1686c343068a3f1670e405ba70..5de8931d21bf8bfaef3f54f8b54b039a6bb56bb8 100644 (file)
@@ -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)
index 7cc9d51e22eec3dce97d92f377e89f0ca05b0ed0..4789f70fe0008c0de9736bf2304a86f8a8907a18 100644 (file)
@@ -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);
 
index 8cc1fd883f7f7308e814f79a44196530739ff5ee..5778964f5bee181cf0fab52f3882b86bab0291cb 100644 (file)
 }")
 
 (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"
   "
 {
   "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")
 \f
index b7680e103617945eb6b578c12a6ca3942386dcbb..424fb87056e4edc243d2c61025c11d0b1ad21aaa 100644 (file)
     {
       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));
     {
       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));
     {
       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));
     {
       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));
     {
       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));
     {
       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));
index b1cf541b4c2e7a68030f8a71d07d005d3f91b39a..0075c39abc654f8e6ff461ee006788c583658725 100644 (file)
@@ -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));
     }
index 1eff7f437234a88f0f317459610ea65fa3bb4a81..c74b1424e57fb54b481899da309effaed5366bc0 100644 (file)
   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);
 }")
   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);
 }")
   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);
 }")
 ;; 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)
 
 (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)
 (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))]
   ""
   "*
 {
 (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))]
   ""
   "*
 {
 ;;(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))]
 ;;  ""
 ;;  "*
 ;;{
 (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))]
   ""
   "*
 {
index d8e7a738bcff3b8dcdb089f9de3518d780eb91b6..7a1ac64ed1839b367d06d7d0a78ab7e572729691 100644 (file)
 ;;- 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)))]
   ""
   "")
index e33cb9b65a365bc8e8cd363b5a6c972ba2e8df61..aeccb3fae20e7633ed66392dd3dcc49e18942d99 100644 (file)
@@ -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);
            }
 
index ceb4f6a2b11a708ee21de5c2a74e923b7cc132f1..d7c421327d6ba2fb65af77a943aae4df5345bccc 100644 (file)
        (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)))]
   "")
 
    && (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)
        (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)))]
   "")
 
    && 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)
        (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)))]
   "")
 
    && 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)
        (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)))]
   "")
 
    && 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)))]
   "")
 
 \f
@@ -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))))]
   "")
 \f
 ;;
@@ -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)
index 1e520a84c605d4b6dbfca8905b4d35659266b6ca..1a4f9dd0f030826eb7d8c4d92152160b637ba10a 100644 (file)
@@ -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:
index 225c8789994a5eef381cfc3d237e0f05e604630c..7f1c0363587b997b1e0c8c786929ed9635cb6c40 100644 (file)
@@ -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....  */
index 2b811621be73d52d538eb054105de15c2ac1ed91..f7646d391d61910e3f146ceaeabbd264f2a30871 100644 (file)
 ;; 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)
   "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)
index 26e80966c95c73cc0787d688d7f71783a4e3757e..502d204e74da2e964bb313b22c0deff106b70dab 100644 (file)
@@ -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);
     }
 
index ceea64cfa82fc82ef37bca8a144291099c6f0179..baeef934243f365a56173749f28e550d2b9b15c8 100644 (file)
    (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)))]
 }")
 
 (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))
          
        }
       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);
index 9171a773386f26b84d5aceec87aefe694397bf85..7fc7f8dc2818fe4f3672d4b5d5bbc04d06b7a847 100644 (file)
 (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")
   [(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"
 ;  [(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"
 ;  [(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"
index 7aedeb600241abf50ec29a3f1e6efc176d58ab10..8cabb46e825cf57eb86964fb339b31b13652ef6e 100644 (file)
@@ -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);
     }
 
index 4cb5cf27fb0b056b71c7d93c22809196262ae93b..d8d4ef3581b497ec34724e824e0845d1cc72bba2 100644 (file)
@@ -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);
index 7045148ae291d64f3f6891bf3552fbfd5eda3bed..a71ba3cc79643374eb880eddd77e305103dfd856 100644 (file)
@@ -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
index 3a03c2d7b41d68947de812b78d7c2dfeda75820f..420c33630a8ce2587a3bc0cccd94efe5b0759940 100644 (file)
   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;
 
       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)
     {
          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))
            {
   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;
 
index 9cb4c5ccf09f51804c1b3c3adb9da69fe37d387b..782d2a725d346bf9bc8b6f2780514627a990c82d 100644 (file)
@@ -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
index 9e49eadb02daa6031c47ed24d48878c0d1f4bd2f..d65908eb35373c0008cf6a1eb9d14fa496aff716 100644 (file)
@@ -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)
 
index 8167af887ecd0029e9cb44b4320f24c4ff4a195d..cf7ae09819652b3d1de4652a09b27f33ffaba424 100644 (file)
 {
   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;
 {
   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;
 
 (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"
 
 (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")
 
 (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"
 
 (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")
 {
   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;
 {
   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;
 }")
 {
   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;
 {
   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;
 {
   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;
          (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"
   "@
 (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
 (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
 (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
 (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
index 34369d46325d6b45d4eab53c3f869b99d5cf5ef2..a074d953604c1e443a71a7a4d9aa7fa1fd891c97 100644 (file)
@@ -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)
index 38ba919f115abe387795afd8099739e5f2752478..2b487510eae630648fba747120652358cb074110 100644 (file)
--- 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;
index fd9fc0c0284acb0b9ed9148488a3ef66c8a2600b..207ba2a155dd5d64154dd2b07af2e38a3fec320e 100644 (file)
@@ -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
index 2e71518fa80567e3f005f617ff9ca0c2f47c50f5..873d0b6d97e2598bf2dae2adf0137c457c47ee57 100644 (file)
@@ -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.  */
 
index 370d14f4d88c52086523bc3ff4c6cb7aa5d5c504..80b06ae1754093b55b65f7b01d1a74b42ca30b33 100644 (file)
@@ -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:
index 93f11f43de9dc4007446cbf0a0f28a9b09c506f2..7b715c6f69dd027f5e0361d3aa3355622b57560d 100644 (file)
@@ -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);
+}
 \f
 /* rtx gen_rtx (code, mode, [element1, ..., elementn])
 **
@@ -650,6 +699,38 @@ get_first_label_num ()
   return first_label_num;
 }
 \f
+/* 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))));
 }
 \f
@@ -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;
 }
 \f
-/* 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 ();
 
index 7fdbdf5d2bf06ac57fda9462fe1cfbb7f227fca4..a7684508b5bcf730748362bea6016b72f9b049ad 100644 (file)
@@ -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
index c2661722cb3a27ed8787aa10da2cf8f6ccc88bee..7d78acd33ae16fdb6e9428c90a2451e9154fd250 100644 (file)
@@ -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;
index fef6641a3a63d194f04d5b4a38ab0d2d1e12d9e2..88519bd73bfa128a75faa3c6028df9ca3aa939cb 100644 (file)
@@ -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);
index d057bc5e264b4e8dc5f3ac0bdc05d9b8212712a6..388bd2a9d8a0535ea7541043ca5903a5512a6585 100644 (file)
@@ -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);
 
index 6eebf34f2847e1da81a2f3ad6f09e5ea2b7b8114..c31029bc5668d2eefb685ecbd5fb0dfca9f31dd4 100644 (file)
@@ -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,
index 21f46df1461a37f80f59af4383756ba3b58b70b1..d41e0d279751ce10fcb7c8f8ef0c30742317b394 100644 (file)
@@ -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);
 }
 
index 8aa172a5e36aa9504008c7119f6d9cddff4cdff0..2f757bd9ade77394e2ca378e94af03ffe9b2e1d9 100644 (file)
@@ -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;
index f0df3da0371e1efdc03d48b9304c5b38ae92d731..b642643f3aec048d52360bd00fcd38c14d12ee2b 100644 (file)
@@ -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));
index ed6540e4bfd779a44b0630ffe78f8738bae71f76..327e8fa5f2544da3ce94e01e202029156aa505cf 100644 (file)
@@ -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));
     }
 
index 2b111d4bd59b5327744091daaa69f00a6341cd86..5c5807394dc0838741c04ee6191ef626b2c9c487 100644 (file)
@@ -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;
 }
index c743ad63fe83c61a98fb373cf112efaf9a22f359..c83d4f145f58930a7ca5da38302e307e55666908 100644 (file)
@@ -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);
 
index 1596a019067ad9a7337b8313e03ccf5fa78a1714..e278f985529a0ce60c25bb2fa05d3c3e4e876e91 100644 (file)
@@ -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;
 }
 \f
@@ -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);
            }
 
index 54c3f086a48236a3447cb9104dc3c7516c8a878c..6c2044674236073a3f699571fc136a4d6350137c 100644 (file)
@@ -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;
index 26c4546fce364e8abe6b3993b789a514945a73cb..227c662c537196a0e046e284ba56303a32a78245 100644 (file)
@@ -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
index 0822966602155ab9c4b124e44b043913e8589000..61b9a49ac02d3b1b3cd504ad812865b022dbfb19 100644 (file)
@@ -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
index 9849aed299bb1288c3666cd6499bfd7ac5af6946..ea5bea62331a9d55f3954813817c8d5d8ac2b34f 100644 (file)
@@ -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)
     {
index 6194b875244f0b4e05ab17ca75496f0c83c25586..16cc3be5d605cbac692a59ea687b573883f850e8 100644 (file)
@@ -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);
     }
 
index 0b3a892ce2ca316c21d0241c4d5c672167b00df5..17f7d034d93dcff45044b39598dc25d36eb4c6eb 100644 (file)
@@ -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));
 
index dbadd70f9583505e839bbcd71e8b22e00a6a2ab6..e4f2ab037141a1e894009e29fa7f87e4b7e62107 100644 (file)
--- 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))
index cfae3a9b98734f717f1b736a003da85668314306..665a40766c7e1909dcc3f84a9a641e6c08efb404 100644 (file)
@@ -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
index db8e696801024908df3fc145b5abf66d2b326ca1..36c3c9ff42f2cf9d143c2b29f5227f4fac134f71 100644 (file)
@@ -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;
+
+}
index 4cd07790130aef6d88718e607d7e716454fb25ad..4aad9f931c1ee68ccd77afad603014f9f89b8f22 100644 (file)
@@ -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:
index 649bc0aa67d544869607dd5bdfb8eb3b59146115..dfccee06f796b8a38004368914839dc756535eef 100644 (file)
@@ -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
index 12f1562cbf6b85e4df51b12daf983b8d7a0b4169..e9c49dcffd41d931759673464f6b59a08f87e882 100644 (file)
@@ -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 ();
index e3dd5309b20b8c3e0ab818b42efebb70b00520c6..1956979f1bde80830c10df98cd62da0c73a19b5e 100644 (file)
@@ -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
This page took 0.310468 seconds and 5 git commands to generate.