This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: Current incarnation of subreg-byte


Perhaps its time we attempted to integrate the subreg-byte work into
the mainline gcc tree. The initial work was done a few years ago, then Jakub
maintained it for quite some time. I did some work on it last summer,
and rth created a branch off of gcc last fall (subreg-byte-branch) and
applied to patch to it.  The branch is woefully out of date now.

And thats as far as it progressed. Over the past few weeks I've been 
working with it again, building and running it on as many targets as
I can. I've also gone through all the changelogs and merged them together
into one sensible organized entry. 

- This patch bootstraps on
  alpha-linux, 
  x86-linux,
  sparc-solaris.

- This also runs with no extra failures on a number of other targets, including 
  ppc-elf
  sh-elf
and a couple of others I dont remember.

- I have also attempted to at least build the compiler on every target
  which the patch touches plus a few others. I think I built it on about 16 
  additional targets to the ones listed above. Some targets I couldnt 
  successfully build on, but the patched branch built to the same point 
  as the original did.

For those that aren't familiar with this, it changes the behaviour of a 
SUBREG. A SUBREG specifies the word offset that we take the subreg from. 
With all the odd combinations of bytes and words we now run across, and
64 bit targets, a word offset is no longer sufficient. (I beleive Jakub 
has been diligently maintaining this for a long time for sparc64 since it 
needs it to work correctly). This patch changes it such that a SUBREG now 
specifies a BYTE offset instead. Of course it touches most parts of the 
compiler, and I suspect the sheer breadth of its coverage is the main reason 
it hasnt been integrated yet... its just no fun dealing with it :-)

So here's the patch. I think I've done about as much with it as I can, 
and I'm rather sick of looking at it. I doubt I can get it much more ready
than it is.



What I'd like to propose is that I offer up the patch as it is now, and 
anyone who is concerned about a mainline breakage of their favorite target 
apply it, try it, and let me know if they encounter anything wrong.
I've caught a lot of things, but I suspect Ive still managed to miss a few. 
I will attempt to try PA again, I wasnt successful in building a compiler
at all when I tried last. 

If there hasn't been an outcry against it for whatever reason, then I'd like
to apply it to the source tree at the beginning of next week. That gives 
people a chance to fool around if they want to, yet hopefully 
it shouldnt get out of date enough to cause me more grief in checking it in.

Does this seem reasonable? Any other issues with it?

This patch is built from a gcc I extracted on monday, so its 2 days 
old already, but I have applied it to source that I just extracted this
(wednesday) afternoon, and it applied cleanly, so it should still be ok.

The vast majority of the patch has been reviewed by rth already, and his
comments integrated.
 
The patch is big........


-- MacLeod


2001-03-07  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.
	* 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.





Index: gcc/alias.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/alias.c,v
retrieving revision 1.115
diff -c -p -r1.115 alias.c
*** gcc/alias.c	2001/01/26 22:32:51	1.115
--- gcc/alias.c	2001/03/07 18:34:31
*************** nonlocal_mentioned_p (x)
*** 1847,1853 ****
  	{
  	  /* Global registers are not local.  */
  	  if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
! 	      && global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)])
  	    return 1;
  	  return 0;
  	}
--- 1847,1853 ----
  	{
  	  /* Global registers are not local.  */
  	  if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
! 	      && global_regs[subreg_regno (x)])
  	    return 1;
  	  return 0;
  	}
Index: gcc/caller-save.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/caller-save.c,v
retrieving revision 1.35
diff -c -p -r1.35 caller-save.c
*** gcc/caller-save.c	2001/02/28 21:32:54	1.35
--- gcc/caller-save.c	2001/03/07 18:34:37
*************** mark_set_regs (reg, setter, data)
*** 487,504 ****
  {
    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);
!     }
  
!   if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
      return;
  
-   regno = REGNO (reg) + word;
    endregno = regno + HARD_REGNO_NREGS (regno, mode);
  
    for (i = regno; i < endregno; i++)
--- 487,507 ----
  {
    register int regno, endregno, i;
    enum machine_mode mode = GET_MODE (reg);
  
    if (GET_CODE (reg) == SUBREG)
      {
!       rtx inner = SUBREG_REG (reg);
!       if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
! 	return;
  
!       regno = subreg_hard_regno (reg, 1);
!     }
!   else if (GET_CODE (reg) == REG
! 	   && REGNO (reg) < FIRST_PSEUDO_REGISTER)
!     regno = REGNO (reg);
!   else
      return;
  
    endregno = regno + HARD_REGNO_NREGS (regno, mode);
  
    for (i = regno; i < endregno; i++)
*************** add_stored_regs (reg, setter, data)
*** 517,537 ****
  {
    register int regno, endregno, i;
    enum machine_mode mode = GET_MODE (reg);
!   int word = 0;
  
    if (GET_CODE (setter) == CLOBBER)
      return;
  
!   while (GET_CODE (reg) == SUBREG)
      {
!       word += SUBREG_WORD (reg);
        reg = SUBREG_REG (reg);
      }
  
    if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
      return;
  
!   regno = REGNO (reg) + word;
    endregno = regno + HARD_REGNO_NREGS (regno, mode);
  
    for (i = regno; i < endregno; i++)
--- 520,543 ----
  {
    register int regno, endregno, i;
    enum machine_mode mode = GET_MODE (reg);
!   int offset = 0;
  
    if (GET_CODE (setter) == CLOBBER)
      return;
  
!   if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == 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) + offset;
    endregno = regno + HARD_REGNO_NREGS (regno, mode);
  
    for (i = regno; i < endregno; i++)
Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.175
diff -c -p -r1.175 calls.c
*** gcc/calls.c	2001/01/24 19:00:58	1.175
--- gcc/calls.c	2001/03/07 18:34:38
*************** precompute_arguments (flags, num_actuals
*** 1477,1482 ****
--- 1477,1484 ----
      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 ();
*************** precompute_arguments (flags, num_actuals
*** 1496,1506 ****
  	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)
  	  {
  	    args[i].value
! 	      = convert_modes (args[i].mode,
! 			       TYPE_MODE (TREE_TYPE (args[i].tree_value)),
  			       args[i].value, args[i].unsignedp);
  #ifdef PROMOTE_FOR_CALL_ONLY
  	    /* CSE will replace this only if it contains args[i].value
--- 1498,1508 ----
  	args[i].initial_value = args[i].value
  	  = protect_from_queue (args[i].value, 0);
  
! 	mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
! 	if (mode != args[i].mode)
  	  {
  	    args[i].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
*************** precompute_arguments (flags, num_actuals
*** 1510,1517 ****
  		&& 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);
  		SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
  		SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
  		  = args[i].unsignedp;
--- 1512,1518 ----
  		&& GET_MODE_CLASS (args[i].mode) == MODE_INT)
  	      {
  		args[i].initial_value
! 		  = 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;
*************** expand_call (exp, target, ignore)
*** 3286,3298 ****
  	{
  	  tree type = TREE_TYPE (exp);
  	  int unsignedp = TREE_UNSIGNED (type);
  
  	  /* 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);
  	  SUBREG_PROMOTED_VAR_P (target) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
  	}
--- 3287,3311 ----
  	{
  	  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 ();
  
! 	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: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.188
diff -c -p -r1.188 combine.c
*** gcc/combine.c	2001/03/03 04:19:50	1.188
--- gcc/combine.c	2001/03/07 18:34:42
*************** try_combine (i3, i2, i1, new_direct_jump
*** 2276,2282 ****
  	     be written as a ZERO_EXTEND.  */
  	  if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
  	    SUBST (*split, gen_rtx_combine (ZERO_EXTEND, split_mode,
! 					    XEXP (*split, 0)));
  #endif
  
  	  newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
--- 2276,2282 ----
  	     be written as a ZERO_EXTEND.  */
  	  if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
  	    SUBST (*split, gen_rtx_combine (ZERO_EXTEND, split_mode,
! 					    SUBREG_REG (*split)));
  #endif
  
  	  newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3797,3823 ****
  	      <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
  	{
  	  rtx inner = SUBREG_REG (x);
! 	  int endian_offset = 0;
  	  /* 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)));
  	  MEM_COPY_ATTRIBUTES (x, inner);
  	  return x;
  	}
--- 3797,3813 ----
  	      <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
  	{
  	  rtx inner = SUBREG_REG (x);
! 	  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);
  
  	  /* 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), offset));
  	  MEM_COPY_ATTRIBUTES (x, inner);
  	  return x;
  	}
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3830,3841 ****
  	 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));
  
! 	  SUBST_INT (SUBREG_WORD (x),
! 		     SUBREG_WORD (x) + SUBREG_WORD (SUBREG_REG (x)));
  	  SUBST (SUBREG_REG (x), SUBREG_REG (SUBREG_REG (x)));
  	}
  
--- 3820,3877 ----
  	 or not at all if changing back to starting mode.  */
        if (GET_CODE (SUBREG_REG (x)) == SUBREG)
  	{
! 	  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);
! 	    }
! 
! 	  /* 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)));
  	}
  
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3855,3864 ****
  #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));
  	  else
  	    return gen_rtx_CLOBBER (mode, const0_rtx);
  	}
--- 3891,3900 ----
  #endif
  	  && REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM)
  	{
! 	  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);
  	}
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3873,3879 ****
  	  && GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
  	  && GET_MODE_CLASS (mode) == MODE_INT)
  	{
! 	  temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x),
  				  0, op0_mode);
  	  if (temp)
  	    return temp;
--- 3909,3916 ----
  	  && GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
  	  && GET_MODE_CLASS (mode) == MODE_INT)
  	{
! 	  temp = operand_subword (SUBREG_REG (x),
! 				  (SUBREG_BYTE (x) / UNITS_PER_WORD),
  				  0, op0_mode);
  	  if (temp)
  	    return temp;
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3887,3897 ****
        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)))
  	  && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
  	  && (! WORDS_BIG_ENDIAN
  	      || GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
--- 3924,3932 ----
        if (CONSTANT_P (SUBREG_REG (x))
  	  && ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
  	      || ! WORDS_BIG_ENDIAN)
! 	      ? 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))
*************** combine_simplify_rtx (x, op0_mode, last,
*** 3903,3910 ****
  	  && 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);
  	  return SUBREG_REG (x);
  	}
  
--- 3938,3946 ----
  	  && 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_BYTE (x) != 0))
! 	    return constant_subword (SUBREG_REG (x), 
! 				     SUBREG_BYTE (x) / UNITS_PER_WORD, mode);
  	  return SUBREG_REG (x);
  	}
  
*************** simplify_set (x)
*** 5178,5191 ****
  
    if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
        && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL
!       && SUBREG_WORD (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_combine (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
! 			      GET_MODE (src), XEXP (src, 0)));
  
        src = SET_SRC (x);
      }
--- 5214,5227 ----
  
    if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
        && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL
!       && 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_combine (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
! 			      GET_MODE (src), SUBREG_REG (src)));
  
        src = SET_SRC (x);
      }
*************** expand_field_assignment (x)
*** 5772,5780 ****
        if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
  	  && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
  	{
  	  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)));
  	}
        else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
  	       && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
--- 5808,5818 ----
        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 * (byte_offset / UNITS_PER_WORD));
  	}
        else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
  	       && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
*************** make_extraction (mode, inner, pos, pos_r
*** 6012,6029 ****
  	  /* 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;
! 	}
        else
  	new = force_to_mode (inner, tmode,
  			     len >= HOST_BITS_PER_WIDE_INT
--- 6050,6075 ----
  	  /* 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)
! 	    {
! 	      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
*************** if_then_else_cond (x, ptrue, pfalse)
*** 7407,7417 ****
  	   || 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))
  	{
! 	  true0 = operand_subword (true0, SUBREG_WORD (x), 0,
  				   GET_MODE (SUBREG_REG (x)));
! 	  false0 = operand_subword (false0, SUBREG_WORD (x), 0,
  				    GET_MODE (SUBREG_REG (x)));
  	}
        *ptrue = force_to_mode (true0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
--- 7453,7463 ----
  	   || 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_BYTE (x) >= UNITS_PER_WORD))
  	{
! 	  true0 = operand_subword (true0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
  				   GET_MODE (SUBREG_REG (x)));
! 	  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);
*************** apply_distributive_law (x)
*** 7783,7789 ****
  
      case SUBREG:
        /* Non-paradoxical SUBREGs distributes over all operations, provided
! 	 the inner modes and word numbers 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
--- 7829,7835 ----
  
      case SUBREG:
        /* Non-paradoxical SUBREGs distributes over all operations, provided
! 	 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
*************** apply_distributive_law (x)
*** 7794,7800 ****
  	 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_lowpart_p (lhs)
  	  || (GET_MODE_CLASS (GET_MODE (lhs))
  	      != GET_MODE_CLASS (GET_MODE (SUBREG_REG (lhs))))
--- 7840,7846 ----
  	 We produce the result slightly differently in this case.  */
  
        if (GET_MODE (SUBREG_REG (lhs)) != GET_MODE (SUBREG_REG (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))))
*************** gen_lowpart_for_combine (mode, x)
*** 9865,9877 ****
       include an explicit SUBREG or we may simplify it further in combine.  */
    else
      {
!       int word = 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);
      }
  }
  
--- 9911,9929 ----
       include an explicit SUBREG or we may simplify it further in combine.  */
    else
      {
!       int offset = 0;
  
!       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);
      }
  }
  
*************** move_deaths (x, maybe_kill_insn, from_cu
*** 12030,12035 ****
--- 12082,12088 ----
  	 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: gcc/cse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cse.c,v
retrieving revision 1.177
diff -c -p -r1.177 cse.c
*** gcc/cse.c	2001/03/02 01:50:47	1.177
--- gcc/cse.c	2001/03/07 18:34:48
*************** mention_regs (x)
*** 1220,1230 ****
  	  /* 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.  */
  	  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));
  	}
  
        REG_IN_TABLE (i) = REG_TICK (i);
--- 1220,1230 ----
  	  /* 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 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_BYTE (x), GET_MODE (x));
  	}
  
        REG_IN_TABLE (i) = REG_TICK (i);
*************** remove_invalid_refs (regno)
*** 2004,2035 ****
        }
  }
  
! /* Likewise for a subreg with subreg_reg WORD and mode MODE.  */
  static void
! remove_invalid_subreg_refs (regno, word, mode)
       unsigned int regno;
!      unsigned int word;
       enum machine_mode mode;
  {
    unsigned int i;
    struct table_elt *p, *next;
!   unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
  
    for (i = 0; i < HASH_SIZE; i++)
      for (p = table[i]; p; p = next)
        {
! 	rtx exp;
  	next = p->next_same_hash;
  
! 	exp = p->exp;
! 	if (GET_CODE (p->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))
  	    && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
  	  remove_from_table (p, i);
        }
--- 2004,2034 ----
        }
  }
  
! /* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
!    and mode MODE.  */
  static void
! remove_invalid_subreg_refs (regno, offset, mode)
       unsigned int regno;
!      unsigned int offset;
       enum machine_mode mode;
  {
    unsigned int i;
    struct table_elt *p, *next;
!   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 = p->exp;
  	next = p->next_same_hash;
  
! 	if (GET_CODE (exp) != REG
  	    && (GET_CODE (exp) != SUBREG
  		|| GET_CODE (SUBREG_REG (exp)) != REG
  		|| REGNO (SUBREG_REG (exp)) != regno
! 		|| (((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);
        }
*************** canon_hash (x, mode)
*** 2302,2308 ****
  	if (GET_CODE (SUBREG_REG (x)) == REG)
  	  {
  	    hash += (((unsigned) SUBREG << 7)
! 		     + REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
  	    return hash;
  	  }
  	break;
--- 2301,2308 ----
  	if (GET_CODE (SUBREG_REG (x)) == REG)
  	  {
  	    hash += (((unsigned) SUBREG << 7)
! 		     + REGNO (SUBREG_REG (x))
! 		     + (SUBREG_BYTE (x) / UNITS_PER_WORD));
  	    return hash;
  	  }
  	break;
*************** fold_rtx (x, insn)
*** 3413,3419 ****
  	  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,
  				   GET_MODE (SUBREG_REG (x)));
  	  if (new == 0 && subreg_lowpart_p (x))
  	    new = gen_lowpart_if_possible (mode, folded_arg0);
--- 3413,3420 ----
  	  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_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);
*************** gen_lowpart_if_possible (mode, x)
*** 4392,4401 ****
  	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))));
        new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
        if (! memory_address_p (mode, XEXP (new, 0)))
  	return 0;
--- 4393,4404 ----
  	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))));
! 	}
        new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
        if (! memory_address_p (mode, XEXP (new, 0)))
  	return 0;
Index: gcc/dbxout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dbxout.c,v
retrieving revision 1.73
diff -c -p -r1.73 dbxout.c
*** gcc/dbxout.c	2001/02/21 14:42:18	1.73
--- gcc/dbxout.c	2001/03/07 18:34:49
*************** dbxout_symbol_location (decl, type, suff
*** 2016,2035 ****
    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);
! 	}
        if (GET_CODE (value) == REG)
  	{
! 	  regno = REGNO (value);
! 	  if (regno >= FIRST_PSEUDO_REGISTER)
  	    return 0;
- 	  regno += offset;
  	}
!       alter_subreg (home);
      }
  
    /* The kind-of-variable letter depends on where
--- 2016,2030 ----
    else if (GET_CODE (home) == SUBREG)
      {
        rtx value = home;
! 
        while (GET_CODE (value) == SUBREG)
! 	value = SUBREG_REG (value);
        if (GET_CODE (value) == REG)
  	{
! 	  if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
  	    return 0;
  	}
!       regno = REGNO (alter_subreg (home));
      }
  
    /* The kind-of-variable letter depends on where
Index: gcc/dwarf2out.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarf2out.c,v
retrieving revision 1.248
diff -c -p -r1.248 dwarf2out.c
*** gcc/dwarf2out.c	2001/03/03 10:08:14	1.248
--- gcc/dwarf2out.c	2001/03/07 18:34:51
*************** is_pseudo_reg (rtl)
*** 3417,3423 ****
  {
    return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
  	  || (GET_CODE (rtl) == SUBREG
! 	      && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
  }
  
  /* Return a reference to a type, with its const and volatile qualifiers
--- 3417,3423 ----
  {
    return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
  	  || (GET_CODE (rtl) == SUBREG
! 	      && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
  }
  
  /* Return a reference to a type, with its const and volatile qualifiers
*************** mem_loc_descriptor (rtl, mode)
*** 7064,7070 ****
           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);
  
        /* Fall through.  */
  
--- 7064,7070 ----
           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 = SUBREG_REG (rtl);
  
        /* Fall through.  */
  
*************** loc_descriptor (rtl)
*** 7208,7214 ****
           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);
  
        /* Fall through.  */
  
--- 7208,7214 ----
           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 = SUBREG_REG (rtl);
  
        /* Fall through.  */
  
Index: gcc/dwarfout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/dwarfout.c,v
retrieving revision 1.80
diff -c -p -r1.80 dwarfout.c
*** gcc/dwarfout.c	2001/02/21 14:42:18	1.80
--- gcc/dwarfout.c	2001/03/07 18:34:52
*************** is_pseudo_reg (rtl)
*** 817,823 ****
  {
    return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
            || ((GET_CODE (rtl) == SUBREG)
! 	      && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
  }
  
  inline static tree
--- 817,823 ----
  {
    return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
            || ((GET_CODE (rtl) == SUBREG)
! 	      && (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)));
  }
  
  inline static tree
*************** output_mem_loc_descriptor (rtl)
*** 1630,1636 ****
  	   legitimate to make the Dwarf info refer to the whole register
  	   which contains the given subreg.  */
  
! 	rtl = XEXP (rtl, 0);
  	/* Drop thru.  */
  
        case REG:
--- 1630,1636 ----
  	   legitimate to make the Dwarf info refer to the whole register
  	   which contains the given subreg.  */
  
! 	rtl = SUBREG_REG (rtl);
  	/* Drop thru.  */
  
        case REG:
*************** output_loc_descriptor (rtl)
*** 1714,1720 ****
  	   legitimate to make the Dwarf info refer to the whole register
  	   which contains the given subreg.  */
  
! 	rtl = XEXP (rtl, 0);
  	/* Drop thru.  */
  
      case REG:
--- 1714,1720 ----
  	   legitimate to make the Dwarf info refer to the whole register
  	   which contains the given subreg.  */
  
! 	rtl = SUBREG_REG (rtl);
  	/* Drop thru.  */
  
      case REG:
Index: gcc/emit-rtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/emit-rtl.c,v
retrieving revision 1.165
diff -c -p -r1.165 emit-rtl.c
*** gcc/emit-rtl.c	2001/03/02 21:41:36	1.165
--- gcc/emit-rtl.c	2001/03/07 18:34:52
*************** gen_rtx_MEM (mode, addr)
*** 348,353 ****
--- 348,402 ----
  
    return rt;
  }
+ 
+ rtx
+ gen_rtx_SUBREG (mode, reg, offset)
+      enum machine_mode mode;
+      rtx reg;
+      int offset;
+ {
+   /* This is the most common failure type.
+      Catch it early so we can see who does it.  */
+   if ((offset % GET_MODE_SIZE (mode)) != 0)
+     abort ();
+ 
+   /* This check isn't usable right now because combine will
+      throw arbitrary crap like a CALL into a SUBREG in
+      gen_lowpart_for_combine so we must just eat it.  */
+ #if 0
+   /* Check for this too.  */
+   if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
+     abort ();
+ #endif
+   return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
+ }
+ 
+ /* Generate a SUBREG representing the least-significant part
+  * of REG if MODE is smaller than mode of REG, otherwise
+  * paradoxical SUBREG. */
+ rtx
+ gen_lowpart_SUBREG (mode, reg)
+      enum machine_mode mode;
+      rtx reg;
+ {
+   enum machine_mode inmode;
+   int offset;
+ 
+   inmode = GET_MODE (reg);
+   if (inmode == VOIDmode)
+     inmode = mode;
+   offset = 0;
+   if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
+       && (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
+     {
+       offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
+       if (! BYTES_BIG_ENDIAN)
+ 	offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
+       else if (! WORDS_BIG_ENDIAN)
+ 	offset %= UNITS_PER_WORD;
+     }
+   return gen_rtx_SUBREG (mode, reg, offset);
+ }
  
  /* rtx gen_rtx (code, mode, [element1, ..., elementn])
  **
*************** get_first_label_num ()
*** 650,655 ****
--- 699,736 ----
    return first_label_num;
  }
  
+ /* Return the final regno of X, which is a SUBREG of a hard
+    register.  */
+ int
+ subreg_hard_regno (x, check_mode)
+      register rtx x;
+      int check_mode;
+ {
+   enum machine_mode mode = GET_MODE (x);
+   unsigned int byte_offset, base_regno, final_regno;
+   rtx reg = SUBREG_REG (x);
+ 
+   /* This is where we attempt to catch illegal subregs
+      created by the compiler.  */
+   if (GET_CODE (x) != SUBREG
+       || GET_CODE (reg) != REG)
+     abort ();
+   base_regno = REGNO (reg);
+   if (base_regno >= FIRST_PSEUDO_REGISTER)
+     abort ();
+   if (! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
+     abort ();
+ 
+   /* Catch non-congruent offsets too.  */
+   byte_offset = SUBREG_BYTE (x);
+   if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
+     abort ();
+ 
+   final_regno = subreg_regno (x);
+ 
+   return final_regno;
+ }
+ 
  /* Return a value representing some low-order bits of X, where the number
     of low-order bits is given by MODE.  Note that no conversion is done
     between floating-point and fixed-point values, rather, the bit 
*************** gen_lowpart_common (mode, x)
*** 666,687 ****
       enum machine_mode mode;
       register rtx x;
  {
!   int word = 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)))
      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 ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
        && (GET_MODE_CLASS (mode) == MODE_INT
--- 747,775 ----
       enum machine_mode mode;
       register rtx x;
  {
!   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
!       && ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
! 	  > ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
      return 0;
  
!   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
*************** gen_lowpart_common (mode, x)
*** 703,741 ****
  	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) == 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));
    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
  	       /* integrate.c can't handle parts of a return value register. */
! 	       && (! REG_FUNCTION_VALUE_P (x)
  		   || ! rtx_equal_function_value_matters)
  #ifdef CLASS_CANNOT_CHANGE_MODE
  	       && ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x))
--- 791,830 ----
  	return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
      }
    else if (GET_CODE (x) == SUBREG
! 	   && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
  	       || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
!     {
!       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)
      {
!       /* 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. */
! 	  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))
*************** gen_lowpart_common (mode, x)
*** 752,760 ****
  	       && 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);
      }
    /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
       from the low-order part of the constant.  */
--- 841,849 ----
  	       && x != arg_pointer_rtx
  #endif
  	       && x != stack_pointer_rtx)
! 	    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.  */
*************** gen_lowpart_common (mode, x)
*** 847,853 ****
  	   && 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));
  
    /* 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
--- 936,942 ----
  	   && GET_CODE (x) == CONST_DOUBLE
  	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
  	   && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
!     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
*************** gen_lowpart_common (mode, x)
*** 863,873 ****
  	   && 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));
  
        if (lowpart && GET_CODE (lowpart) == CONST_INT
  	  && highpart && GET_CODE (highpart) == CONST_INT)
  	return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
--- 952,965 ----
  	   && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
  	   && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
      {
!       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);
*************** gen_imagpart (mode, x)
*** 1021,1027 ****
      return XEXP (x, 1);
    else if (WORDS_BIG_ENDIAN)
      return gen_lowpart (mode, x);
!   else if (!WORDS_BIG_ENDIAN
  	   && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
  	   && REG_P (x)
  	   && REGNO (x) < FIRST_PSEUDO_REGISTER)
--- 1113,1119 ----
      return XEXP (x, 1);
    else if (WORDS_BIG_ENDIAN)
      return gen_lowpart (mode, x);
!   else if (! WORDS_BIG_ENDIAN
  	   && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
  	   && REG_P (x)
  	   && REGNO (x) < FIRST_PSEUDO_REGISTER)
*************** subreg_realpart_p (x)
*** 1043,1049 ****
    if (GET_CODE (x) != SUBREG)
      abort ();
  
!   return ((unsigned int) SUBREG_WORD (x) * UNITS_PER_WORD
  	  < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
  }
  
--- 1135,1141 ----
    if (GET_CODE (x) != SUBREG)
      abort ();
  
!   return ((unsigned int) SUBREG_BYTE (x)
  	  < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
  }
  
*************** gen_highpart (mode, x)
*** 1101,1110 ****
       enum machine_mode mode;
       register rtx 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)))
      abort ();
    if (GET_CODE (x) == CONST_DOUBLE
  #if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
--- 1193,1205 ----
       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 (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))
*************** gen_highpart (mode, x)
*** 1121,1135 ****
    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));
  
        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))));
  
        return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
      }
--- 1216,1229 ----
    else if (GET_CODE (x) == MEM)
      {
        register int offset = 0;
+ 
        if (! WORDS_BIG_ENDIAN)
! 	offset = (MAX (xsize, UNITS_PER_WORD)
! 		  - MAX (msize, UNITS_PER_WORD));
  
        if (! BYTES_BIG_ENDIAN
! 	  && msize < UNITS_PER_WORD)
! 	offset -= (msize - MIN (UNITS_PER_WORD, xsize));
  
        return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
      }
*************** gen_highpart (mode, x)
*** 1138,1183 ****
        /* 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)
  	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.  */
  
        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)
  	  /* 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
  #endif
! 	  && x != stack_pointer_rtx)
! 	return gen_rtx_REG (mode, REGNO (x) + word);
!       else
! 	return gen_rtx_SUBREG (mode, x, word);
      }
    else
      abort ();
--- 1232,1278 ----
        /* 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_BYTE (x) != 0)
  	abort ();
        return gen_highpart (mode, SUBREG_REG (x));
      }
    else if (GET_CODE (x) == REG)
      {
!       int offset = 0;
  
        if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
  	abort ();
! 
!       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
  #endif
! 	      && 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 ();
*************** int
*** 1191,1344 ****
  subreg_lowpart_p (x)
       rtx 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));
  
!   return SUBREG_WORD (x) == 0;
  }
  
- /* 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.  */
- 
  rtx
! operand_subword (op, i, validate_address, mode)
       rtx op;
!      unsigned int i;
!      int validate_address;
       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;
  
    /* 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
--- 1286,1329 ----
  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 (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_BYTE (x) == offset;
  }
  
  
! /* Helper routine for all the constant cases of operand_subword.
!    Some places invoke this directly.  */
  
  rtx
! constant_subword (op, offset, mode)
       rtx op;
!      int offset;
       enum machine_mode mode;
  {
    int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
!   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;
  
  #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
*************** operand_subword (op, i, validate_address
*** 1365,1376 ****
  	 So we explicitly mask and sign-extend as necessary.  */
        if (BITS_PER_WORD == 32)
  	{
! 	  val = k[i];
  	  val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
  	  return GEN_INT (val);
  	}
  #if HOST_BITS_PER_WIDE_INT >= 64
!       else if (BITS_PER_WORD >= 64 && i == 0)
  	{
  	  val = k[! WORDS_BIG_ENDIAN];
  	  val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
--- 1350,1361 ----
  	 So we explicitly mask and sign-extend as necessary.  */
        if (BITS_PER_WORD == 32)
  	{
! 	  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 && offset == 0)
  	{
  	  val = k[! WORDS_BIG_ENDIAN];
  	  val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
*************** operand_subword (op, i, validate_address
*** 1380,1387 ****
  #endif
        else if (BITS_PER_WORD == 16)
  	{
! 	  val = k[i >> 1];
! 	  if ((i & 1) == !WORDS_BIG_ENDIAN)
  	    val >>= 16;
  	  val &= 0xffff;
  	  return GEN_INT (val);
--- 1365,1372 ----
  #endif
        else if (BITS_PER_WORD == 16)
  	{
! 	  val = k[offset >> 1];
! 	  if ((offset & 1) == ! WORDS_BIG_ENDIAN)
  	    val >>= 16;
  	  val &= 0xffff;
  	  return GEN_INT (val);
*************** operand_subword (op, i, validate_address
*** 1402,1417 ****
  
        if (BITS_PER_WORD == 32)
  	{
! 	  val = k[i];
  	  val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
  	  return GEN_INT (val);
  	}
  #if HOST_BITS_PER_WIDE_INT >= 64
!       else if (BITS_PER_WORD >= 64 && i <= 1)
  	{
! 	  val = k[i*2 + ! WORDS_BIG_ENDIAN];
  	  val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
! 	  val |= (HOST_WIDE_INT) k[i*2 + WORDS_BIG_ENDIAN] & 0xffffffff;
  	  return GEN_INT (val);
  	}
  #endif
--- 1387,1402 ----
  
        if (BITS_PER_WORD == 32)
  	{
! 	  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 && offset <= 1)
  	{
! 	  val = k[offset * 2 + ! WORDS_BIG_ENDIAN];
  	  val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
! 	  val |= (HOST_WIDE_INT) k[offset * 2 + WORDS_BIG_ENDIAN] & 0xffffffff;
  	  return GEN_INT (val);
  	}
  #endif
*************** operand_subword (op, i, validate_address
*** 1431,1440 ****
  	 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
  		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
  #else
!       return GEN_INT (i != WORDS_BIG_ENDIAN
  		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
  #endif
      }
--- 1416,1425 ----
  	 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 (offset == WORDS_BIG_ENDIAN
  		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
  #else
!       return GEN_INT (offset != WORDS_BIG_ENDIAN
  		      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
  #endif
      }
*************** operand_subword (op, i, validate_address
*** 1460,1466 ****
  
        if (BITS_PER_WORD == 16)
  	{
! 	  if ((i & 1) == !WORDS_BIG_ENDIAN)
  	    val >>= 16;
  	  val &= 0xffff;
  	}
--- 1445,1451 ----
  
        if (BITS_PER_WORD == 16)
  	{
! 	  if ((offset & 1) == ! WORDS_BIG_ENDIAN)
  	    val >>= 16;
  	  val &= 0xffff;
  	}
*************** operand_subword (op, i, validate_address
*** 1504,1510 ****
        
    /* 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.  
  
       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
--- 1489,1495 ----
        
    /* The only remaining cases that we can handle are integers.
       Convert to proper endianness now since these cases need it.
!      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
*************** operand_subword (op, i, validate_address
*** 1519,1557 ****
      return 0;
  
    if (WORDS_BIG_ENDIAN)
!     i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
  
    /* Find out which word on the host machine this value is in and get
       it from the constant.  */
!   val = (i / 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 = trunc_int_for_mode (val, word_mode);
  
    return GEN_INT (val);
  }
  
  /* 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. 
  
     MODE is the mode of OP, in case it is CONST_INT.  */
  
  rtx
! operand_subword_force (op, i, mode)
       rtx op;
!      unsigned int i;
       enum machine_mode mode;
  {
!   rtx result = operand_subword (op, i, 1, mode);
  
    if (result)
      return result;
--- 1504,1687 ----
      return 0;
  
    if (WORDS_BIG_ENDIAN)
!     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 = (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 >> ((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.  
  
     MODE is the mode of OP, in case it is CONST_INT.  */
  
  rtx
! operand_subword_force (op, offset, mode)
       rtx op;
!      unsigned int offset;
       enum machine_mode mode;
  {
!   rtx result = operand_subword (op, offset, 1, mode);
  
    if (result)
      return result;
*************** operand_subword_force (op, i, mode)
*** 1566,1572 ****
  	op = force_reg (mode, op);
      }
  
!   result = operand_subword (op, i, 1, mode);
    if (result == 0)
      abort ();
  
--- 1696,1702 ----
  	op = force_reg (mode, op);
      }
  
!   result = operand_subword (op, offset, 1, mode);
    if (result == 0)
      abort ();
  
Index: gcc/expmed.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expmed.c,v
retrieving revision 1.76
diff -c -p -r1.76 expmed.c
*** gcc/expmed.c	2001/01/31 19:05:49	1.76
--- gcc/expmed.c	2001/03/07 18:34:54
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 263,269 ****
  	 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);
        /* We used to adjust BITPOS here, but now we do the whole adjustment
  	 right after the loop.  */
        op0 = SUBREG_REG (op0);
--- 263,269 ----
  	 meaningful at a much higher level; when structures are copied
  	 between memory and regs, the higher-numbered regs
  	 always get higher addresses.  */
!       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);
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 313,319 ****
  		abort ();
  	    }
  	  if (GET_CODE (op0) == REG)
! 	    op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
  	  else
  	    op0 = change_address (op0, fieldmode,
  				  plus_constant (XEXP (op0, 0), offset));
--- 313,321 ----
  		abort ();
  	    }
  	  if (GET_CODE (op0) == REG)
! 	    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));
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 375,381 ****
  	}
  
        emit_insn (GEN_FCN (icode)
! 		 (gen_rtx_SUBREG (fieldmode, op0, offset), value));
  
        return value;
      }
--- 377,386 ----
  	}
  
        emit_insn (GEN_FCN (icode)
! 		 (gen_rtx_SUBREG (fieldmode, op0,
! 				  (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
! 				  + (offset * UNITS_PER_WORD)),
! 				  value));
  
        return value;
      }
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 449,455 ****
  		abort ();
  	    }
  	  op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
! 		                op0, offset);
  	}
        offset = 0;
      }
--- 454,460 ----
  		abort ();
  	    }
  	  op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
! 		                op0, (offset * UNITS_PER_WORD));
  	}
        offset = 0;
      }
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 552,558 ****
        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));
        if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
  	xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
  
--- 557,563 ----
        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_BYTE (xop0));
        if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
  	xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
  
*************** store_split_bit_field (op0, bitsize, bit
*** 912,919 ****
  	 the current word starting from the base register.  */
        if (GET_CODE (op0) == SUBREG)
  	{
! 	  word = operand_subword_force (SUBREG_REG (op0),
! 					SUBREG_WORD (op0) + offset,
  					GET_MODE (SUBREG_REG (op0)));
  	  offset = 0;
  	}
--- 917,924 ----
  	 the current word starting from the base register.  */
        if (GET_CODE (op0) == SUBREG)
  	{
! 	  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;
  	}
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1010,1016 ****
        int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
        int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
  
!       offset += SUBREG_WORD (op0);
  
        inner_size = MIN (inner_size, BITS_PER_WORD);
  
--- 1015,1021 ----
        int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
        int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
  
!       offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
  
        inner_size = MIN (inner_size, BITS_PER_WORD);
  
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1106,1112 ****
  		abort ();
  	    }
  	  if (GET_CODE (op0) == REG)
! 	    op0 = gen_rtx_SUBREG (mode1, op0, offset);
  	  else
  	    op0 = change_address (op0, mode1,
  				  plus_constant (XEXP (op0, 0), offset));
--- 1111,1119 ----
  		abort ();
  	    }
  	  if (GET_CODE (op0) == REG)
! 	    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));
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1215,1221 ****
  	  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);
  	}
        offset = 0;
      }
--- 1222,1228 ----
  	  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 * UNITS_PER_WORD));
  	}
        offset = 0;
      }
*************** extract_split_bit_field (op0, bitsize, b
*** 1810,1817 ****
  	 the current word starting from the base register.  */
        if (GET_CODE (op0) == SUBREG)
  	{
! 	  word = operand_subword_force (SUBREG_REG (op0),
! 					SUBREG_WORD (op0) + offset,
  					GET_MODE (SUBREG_REG (op0)));
  	  offset = 0;
  	}
--- 1817,1824 ----
  	 the current word starting from the base register.  */
        if (GET_CODE (op0) == SUBREG)
  	{
! 	  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;
  	}
*************** expand_shift (code, mode, shifted, amoun
*** 1930,1936 ****
          op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
  		       % GET_MODE_BITSIZE (mode));
        else if (GET_CODE (op1) == SUBREG
! 	       && SUBREG_WORD (op1) == 0)
  	op1 = SUBREG_REG (op1);
      }
  #endif
--- 1937,1943 ----
          op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
  		       % GET_MODE_BITSIZE (mode));
        else if (GET_CODE (op1) == SUBREG
! 	       && SUBREG_BYTE (op1) == 0)
  	op1 = SUBREG_REG (op1);
      }
  #endif
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.297
diff -c -p -r1.297 expr.c
*** gcc/expr.c	2001/03/02 21:41:35	1.297
--- gcc/expr.c	2001/03/07 18:34:56
*************** store_expr (exp, target, want_value)
*** 4033,4039 ****
        if (want_value && GET_MODE (temp) != GET_MODE (target)
  	  && GET_MODE (temp) != VOIDmode)
  	{
! 	  temp = gen_rtx_SUBREG (GET_MODE (target), temp, 0);
  	  SUBREG_PROMOTED_VAR_P (temp) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (temp)
  	    = SUBREG_PROMOTED_UNSIGNED_P (target);
--- 4033,4039 ----
        if (want_value && GET_MODE (temp) != GET_MODE (target)
  	  && GET_MODE (temp) != VOIDmode)
  	{
! 	  temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
  	  SUBREG_PROMOTED_VAR_P (temp) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (temp)
  	    = SUBREG_PROMOTED_UNSIGNED_P (target);
*************** expand_expr (exp, target, tmode, modifie
*** 6244,6250 ****
  	      != promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
  	    abort ();
  
! 	  temp = gen_rtx_SUBREG (mode, DECL_RTL (exp), 0);
  	  SUBREG_PROMOTED_VAR_P (temp) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
  	  return temp;
--- 6244,6250 ----
  	      != promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
  	    abort ();
  
! 	  temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
  	  SUBREG_PROMOTED_VAR_P (temp) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
  	  return temp;
*************** expand_expr (exp, target, tmode, modifie
*** 6364,6370 ****
  
  	  if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
  	    {
! 	      temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
  	      SUBREG_PROMOTED_VAR_P (temp) = 1;
  	      SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
  	    }
--- 6364,6370 ----
  
  	  if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
  	    {
! 	      temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
  	      SUBREG_PROMOTED_VAR_P (temp) = 1;
  	      SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
  	    }
*************** expand_expr (exp, target, tmode, modifie
*** 6387,6393 ****
  	{
  	  /* Compute the signedness and make the proper SUBREG.  */
  	  promote_mode (type, mode, &unsignedp, 0);
! 	  temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
  	  SUBREG_PROMOTED_VAR_P (temp) = 1;
  	  SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
  	  return temp;
--- 6387,6393 ----
  	{
  	  /* Compute the signedness and make the proper SUBREG.  */
  	  promote_mode (type, mode, &unsignedp, 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: gcc/final.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/final.c,v
retrieving revision 1.161
diff -c -p -r1.161 final.c
*** gcc/final.c	2001/02/28 17:53:35	1.161
--- gcc/final.c	2001/03/07 18:34:59
*************** alter_subreg (x)
*** 3154,3173 ****
  
    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
        PUT_CODE (x, REG);
        REGNO (x) = regno;
        ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
--- 3154,3161 ----
  
    if (GET_CODE (y) == REG)
      {
!       int regno = subreg_hard_regno (x, 1);
  
        PUT_CODE (x, REG);
        REGNO (x) = regno;
        ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
*************** alter_subreg (x)
*** 3177,3187 ****
      }
    else if (GET_CODE (y) == MEM)
      {
!       register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  
!       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);
--- 3165,3176 ----
      }
    else if (GET_CODE (y) == MEM)
      {
!       register int offset = SUBREG_BYTE (x);
  
!       /* Catch these instead of generating incorrect code.  */
!       if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
! 	abort ();
! 
        PUT_CODE (x, MEM);
        MEM_COPY_ATTRIBUTES (x, y);
        XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
Index: gcc/flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.381
diff -c -p -r1.381 flow.c
*** gcc/flow.c	2001/02/24 02:32:33	1.381
--- gcc/flow.c	2001/03/07 18:35:00
*************** set_noop_p (set)
*** 3313,3319 ****
  
    if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
      {
!       if (SUBREG_WORD (src) != SUBREG_WORD (dst))
  	return 0;
        src = SUBREG_REG (src);
        dst = SUBREG_REG (dst);
--- 3313,3319 ----
  
    if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
      {
!       if (SUBREG_BYTE (src) != SUBREG_BYTE (dst))
  	return 0;
        src = SUBREG_REG (src);
        dst = SUBREG_REG (dst);
*************** mark_set_1 (pbi, code, reg, cond, insn, 
*** 4842,4853 ****
  	  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_last = (regno_first
  			    + HARD_REGNO_NREGS (regno_first, outer_mode) - 1);
  
--- 4842,4850 ----
  	  regno_last = regno_first = REGNO (SUBREG_REG (reg));
  	  if (regno_first < FIRST_PSEUDO_REGISTER)
  	    {
! 	      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: gcc/function.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.c,v
retrieving revision 1.254
diff -c -p -r1.254 function.c
*** gcc/function.c	2001/03/02 01:50:49	1.254
--- gcc/function.c	2001/03/07 18:35:03
*************** fixup_var_refs_1 (var, promoted_mode, lo
*** 2230,2236 ****
  	  dest = XEXP (dest, 0);
  
  	if (GET_CODE (src) == SUBREG)
! 	  src = XEXP (src, 0);
  
  	/* If VAR does not appear at the top level of the SET
  	   just scan the lower levels of the tree.  */
--- 2230,2236 ----
  	  dest = XEXP (dest, 0);
  
  	if (GET_CODE (src) == SUBREG)
! 	  src = SUBREG_REG (src);
  
  	/* If VAR does not appear at the top level of the SET
  	   just scan the lower levels of the tree.  */
*************** fixup_memory_subreg (x, insn, uncritical
*** 2514,2520 ****
       rtx insn;
       int uncritical;
  {
!   int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
    rtx addr = XEXP (SUBREG_REG (x), 0);
    enum machine_mode mode = GET_MODE (x);
    rtx result;
--- 2514,2520 ----
       rtx insn;
       int uncritical;
  {
!   int offset = SUBREG_BYTE (x);
    rtx addr = XEXP (SUBREG_REG (x), 0);
    enum machine_mode mode = GET_MODE (x);
    rtx result;
*************** fixup_memory_subreg (x, insn, uncritical
*** 2524,2532 ****
        && ! 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.  */
--- 2524,2529 ----
*************** optimize_bit_field (body, insn, equiv_me
*** 2720,2726 ****
  	  offset /= BITS_PER_UNIT;
  	  if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
  	    {
! 	      offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
  	      if (BYTES_BIG_ENDIAN)
  		offset -= (MIN (UNITS_PER_WORD,
  				GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
--- 2717,2724 ----
  	  offset /= BITS_PER_UNIT;
  	  if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
  	    {
! 	      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))))
*************** optimize_bit_field (body, insn, equiv_me
*** 2745,2751 ****
  		{
  		  rtx src = SET_SRC (body);
  		  while (GET_CODE (src) == SUBREG
! 			 && SUBREG_WORD (src) == 0)
  		    src = SUBREG_REG (src);
  		  if (GET_MODE (src) != GET_MODE (memref))
  		    src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
--- 2743,2749 ----
  		{
  		  rtx src = SET_SRC (body);
  		  while (GET_CODE (src) == SUBREG
! 			 && SUBREG_BYTE (src) == 0)
  		    src = SUBREG_REG (src);
  		  if (GET_MODE (src) != GET_MODE (memref))
  		    src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
*************** optimize_bit_field (body, insn, equiv_me
*** 2766,2772 ****
  	      rtx dest = SET_DEST (body);
  
  	      while (GET_CODE (dest) == SUBREG
! 		     && SUBREG_WORD (dest) == 0
  		     && (GET_MODE_CLASS (GET_MODE (dest))
  			 == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
  		     && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
--- 2764,2770 ----
  	      rtx dest = SET_DEST (body);
  
  	      while (GET_CODE (dest) == SUBREG
! 		     && 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)))
*************** purge_addressof_1 (loc, insn, force, sto
*** 3076,3082 ****
  		       code did.  This is especially true of
  		       REG_RETVAL.  */
  
! 		    if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
  		      z = SUBREG_REG (z);
  
  		    if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
--- 3074,3080 ----
  		       code did.  This is especially true of
  		       REG_RETVAL.  */
  
! 		    if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
  		      z = SUBREG_REG (z);
  
  		    if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
*************** purge_single_hard_subreg_set (pattern)
*** 3452,3468 ****
  {
    rtx reg = SET_DEST (pattern);
    enum machine_mode mode = GET_MODE (SET_DEST (pattern));
!   int word = 0;
! 		  
!   while (GET_CODE (reg) == SUBREG)
      {
!       word += SUBREG_WORD (reg);
        reg = SUBREG_REG (reg);
      }
! 	      
    if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
      {
!       reg = gen_rtx_REG (mode, REGNO (reg) + word);
        SET_DEST (pattern) = reg;
      }
  }
--- 3450,3471 ----
  {
    rtx reg = SET_DEST (pattern);
    enum machine_mode mode = GET_MODE (SET_DEST (pattern));
!   int offset = 0;
! 
!   if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG
!       && REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER)
      {
!       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) + offset);
        SET_DEST (pattern) = reg;
      }
  }
*************** assign_parms (fndecl)
*** 4741,4746 ****
--- 4744,4763 ----
  
  	      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);
Index: gcc/gengenrtl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gengenrtl.c,v
retrieving revision 1.39
diff -c -p -r1.39 gengenrtl.c
*** gcc/gengenrtl.c	2000/10/13 06:26:26	1.39
--- gcc/gengenrtl.c	2001/03/07 18:35:12
*************** special_rtx (idx)
*** 208,213 ****
--- 208,214 ----
    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: gcc/global.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/global.c,v
retrieving revision 1.65
diff -c -p -r1.65 global.c
*** gcc/global.c	2000/12/05 19:12:19	1.65
--- gcc/global.c	2001/03/07 18:35:13
*************** mark_reg_store (reg, setter, data)
*** 1422,1438 ****
  {
    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);
!     }
  
    if (GET_CODE (reg) != REG)
      return;
--- 1422,1429 ----
  {
    register int regno;
  
    if (GET_CODE (reg) == SUBREG)
!     reg = SUBREG_REG (reg);
  
    if (GET_CODE (reg) != REG)
      return;
*************** mark_reg_store (reg, setter, data)
*** 1456,1462 ****
      }
  
    if (reg_renumber[regno] >= 0)
!     regno = reg_renumber[regno] /* + word */;
  
    /* Handle hardware regs (and pseudos allocated to hard regs).  */
    if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
--- 1447,1453 ----
      }
  
    if (reg_renumber[regno] >= 0)
!     regno = reg_renumber[regno];
  
    /* Handle hardware regs (and pseudos allocated to hard regs).  */
    if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
*************** set_preference (dest, src)
*** 1606,1612 ****
    else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
      {
        src_regno = REGNO (SUBREG_REG (src));
!       offset += SUBREG_WORD (src);
      }
    else
      return;
--- 1597,1611 ----
    else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
      {
        src_regno = REGNO (SUBREG_REG (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;
*************** set_preference (dest, src)
*** 1616,1622 ****
    else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
      {
        dest_regno = REGNO (SUBREG_REG (dest));
!       offset -= SUBREG_WORD (dest);
      }
    else
      return;
--- 1615,1629 ----
    else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
      {
        dest_regno = REGNO (SUBREG_REG (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: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/integrate.c,v
retrieving revision 1.130
diff -c -p -r1.130 integrate.c
*** gcc/integrate.c	2001/02/24 13:15:55	1.130
--- gcc/integrate.c	2001/03/07 18:35:16
*************** copy_rtx_and_substitute (orig, map, for_
*** 1899,1921 ****
        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));
        else if (GET_CODE (copy) == CONCAT)
  	{
  	  rtx retval = subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1);
  
  	  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)));
  	}
        else
  	return gen_rtx_SUBREG (GET_MODE (orig), copy,
! 			       SUBREG_WORD (orig));
  
      case ADDRESSOF:
        copy = gen_rtx_ADDRESSOF (mode,
--- 1899,1931 ----
        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)
! 	{
! 	  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;
! 	  
! 	  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_BYTE (orig));
  
      case ADDRESSOF:
        copy = gen_rtx_ADDRESSOF (mode,
*************** subst_constants (loc, insn, map, memonly
*** 2407,2414 ****
  	  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)));
  
  	  cancel_changes (num_changes);
  	  if (new == 0 && subreg_lowpart_p (x))
--- 2417,2424 ----
  	  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_BYTE (x) / UNITS_PER_WORD,
! 				   0, GET_MODE (SUBREG_REG (x)));
  
  	  cancel_changes (num_changes);
  	  if (new == 0 && subreg_lowpart_p (x))
*************** mark_stores (dest, x, data)
*** 2685,2691 ****
      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);
        mode = GET_MODE (SUBREG_REG (dest));
      }
  
--- 2695,2706 ----
      regno = REGNO (dest), mode = GET_MODE (dest);
    else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
      {
!       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: gcc/jump.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/jump.c,v
retrieving revision 1.157
diff -c -p -r1.157 jump.c
*** gcc/jump.c	2001/02/28 17:49:36	1.157
--- gcc/jump.c	2001/03/07 18:35:18
*************** rtx_renumbered_equal_p (x, y)
*** 3572,3578 ****
  				  && GET_CODE (SUBREG_REG (y)) == REG)))
      {
        int reg_x = -1, reg_y = -1;
!       int word_x = 0, word_y = 0;
  
        if (GET_MODE (x) != GET_MODE (y))
  	return 0;
--- 3572,3578 ----
  				  && GET_CODE (SUBREG_REG (y)) == REG)))
      {
        int reg_x = -1, reg_y = -1;
!       int byte_x = 0, byte_y = 0;
  
        if (GET_MODE (x) != GET_MODE (y))
  	return 0;
*************** rtx_renumbered_equal_p (x, y)
*** 3585,3599 ****
        if (code == SUBREG)
  	{
  	  reg_x = REGNO (SUBREG_REG (x));
! 	  word_x = SUBREG_WORD (x);
  
  	  if (reg_renumber[reg_x] >= 0)
  	    {
! 	      reg_x = reg_renumber[reg_x] + word_x;
! 	      word_x = 0;
  	    }
  	}
- 
        else
  	{
  	  reg_x = REGNO (x);
--- 3585,3601 ----
        if (code == SUBREG)
  	{
  	  reg_x = REGNO (SUBREG_REG (x));
! 	  byte_x = SUBREG_BYTE (x);
  
  	  if (reg_renumber[reg_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);
*************** rtx_renumbered_equal_p (x, y)
*** 3604,3618 ****
        if (GET_CODE (y) == SUBREG)
  	{
  	  reg_y = REGNO (SUBREG_REG (y));
! 	  word_y = SUBREG_WORD (y);
  
  	  if (reg_renumber[reg_y] >= 0)
  	    {
! 	      reg_y = reg_renumber[reg_y];
! 	      word_y = 0;
  	    }
  	}
- 
        else
  	{
  	  reg_y = REGNO (y);
--- 3606,3622 ----
        if (GET_CODE (y) == SUBREG)
  	{
  	  reg_y = REGNO (SUBREG_REG (y));
! 	  byte_y = SUBREG_BYTE (y);
  
  	  if (reg_renumber[reg_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);
*************** rtx_renumbered_equal_p (x, y)
*** 3620,3626 ****
  	    reg_y = reg_renumber[reg_y];
  	}
  
!       return reg_x >= 0 && reg_x == reg_y && word_x == word_y;
      }
  
    /* Now we have disposed of all the cases
--- 3624,3630 ----
  	    reg_y = reg_renumber[reg_y];
  	}
  
!       return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
      }
  
    /* Now we have disposed of all the cases
*************** true_regnum (x)
*** 3751,3757 ****
      {
        int base = true_regnum (SUBREG_REG (x));
        if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
! 	return SUBREG_WORD (x) + base;
      }
    return -1;
  }
--- 3755,3763 ----
      {
        int base = true_regnum (SUBREG_REG (x));
        if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
! 	return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
! 					   GET_MODE (SUBREG_REG (x)),
! 					   SUBREG_BYTE (x), GET_MODE (x));
      }
    return -1;
  }
Index: gcc/local-alloc.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/local-alloc.c,v
retrieving revision 1.78
diff -c -p -r1.78 local-alloc.c
*** gcc/local-alloc.c	2001/02/02 01:03:47	1.78
--- gcc/local-alloc.c	2001/03/07 18:35:19
*************** combine_regs (usedreg, setreg, may_save_
*** 1813,1837 ****
      {
        if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
  	may_save_copy = 0;
!       offset += SUBREG_WORD (usedreg);
        usedreg = SUBREG_REG (usedreg);
      }
    if (GET_CODE (usedreg) != REG)
      return 0;
    ureg = REGNO (usedreg);
!   usize = REG_SIZE (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);
        setreg = SUBREG_REG (setreg);
      }
    if (GET_CODE (setreg) != REG)
      return 0;
    sreg = REGNO (setreg);
!   ssize = REG_SIZE (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
--- 1813,1861 ----
      {
        if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
  	may_save_copy = 0;
!       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);
!   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;
!       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);
!   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
*************** reg_is_born (reg, birth)
*** 2032,2038 ****
    register int regno;
  
    if (GET_CODE (reg) == SUBREG)
!     regno = REGNO (SUBREG_REG (reg)) + SUBREG_WORD (reg);
    else
      regno = REGNO (reg);
  
--- 2056,2066 ----
    register int regno;
  
    if (GET_CODE (reg) == SUBREG)
!     {
!       regno = REGNO (SUBREG_REG (reg));
!       if (regno < FIRST_PSEUDO_REGISTER)
! 	regno = subreg_hard_regno (reg, 1);
!     }
    else
      regno = REGNO (reg);
  
Index: gcc/recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.90
diff -c -p -r1.90 recog.c
*** gcc/recog.c	2001/02/18 23:56:34	1.90
--- gcc/recog.c	2001/03/07 18:35:26
*************** validate_replace_rtx_1 (loc, from, to, o
*** 519,531 ****
  	  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)),
  				      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;
  		  HOST_WIDE_INT valh;
  		  unsigned HOST_WIDE_INT vall;
  
--- 519,533 ----
  	  if (GET_CODE (XEXP (x, 0)) == SUBREG)
  	    {
  	      if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD)
! 		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_BYTE (XEXP (x, 0)) * BITS_PER_UNIT;
  		  HOST_WIDE_INT valh;
  		  unsigned HOST_WIDE_INT vall;
  
*************** validate_replace_rtx_1 (loc, from, to, o
*** 571,596 ****
        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.  */
        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))
  	    {
! 	      rtx new =  gen_lowpart_if_possible (GET_MODE (x), to);
  	      if (new)
  		{
  		  validate_change (object, loc, new, 1);
--- 573,593 ----
        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.  */
        if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
          {
! 	  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);
  	      if (new)
  		{
  		  validate_change (object, loc, new, 1);
*************** validate_replace_rtx_1 (loc, from, to, o
*** 598,610 ****
  		}
  	    }
  
! 	  /* 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)))
  	    {
! 	      validate_change (object, loc, to, 1);
! 	      return;
  	    }
          }
  
--- 595,661 ----
  		}
  	    }
  
! 	  offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
! 	  switch (GET_CODE (to))
  	    {
! 	    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;
  	    }
          }
  
*************** validate_replace_rtx_1 (loc, from, to, o
*** 614,628 ****
  	  && rtx_equal_p (SUBREG_REG (x), from))
  	{
  	  if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
! 	      && SUBREG_WORD (x) == 0 && SUBREG_WORD (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);
  	  return;
  	}
  
--- 665,690 ----
  	  && rtx_equal_p (SUBREG_REG (x), from))
  	{
  	  if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
! 	      && SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0)
  	    {
  	      validate_change (object, loc, SUBREG_REG (to), 1);
  	      return;
  	    }
  
! 	  /* 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;
  	}
  
*************** validate_replace_rtx_1 (loc, from, to, o
*** 638,652 ****
  	  && ! MEM_VOLATILE_P (to)
  	  && GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
  	{
! 	  int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  	  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);
--- 700,709 ----
  	  && ! MEM_VOLATILE_P (to)
  	  && GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
  	{
! 	  int offset = SUBREG_BYTE (x);
  	  enum machine_mode mode = GET_MODE (x);
  	  rtx new;
  
  	  new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
  	  MEM_COPY_ATTRIBUTES (new, to);
  	  validate_change (object, loc, new, 1);
*************** validate_replace_rtx_1 (loc, from, to, o
*** 696,703 ****
  	      int offset = pos / BITS_PER_UNIT;
  	      rtx newmem;
  
! 		  /* 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);
--- 753,760 ----
  	      int offset = pos / BITS_PER_UNIT;
  	      rtx newmem;
  
! 	      /* 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);
*************** general_operand (op, mode)
*** 1042,1048 ****
       enum machine_mode mode;
  {
    register enum rtx_code code = GET_CODE (op);
-   int mode_altering_drug = 0;
  
    if (mode == VOIDmode)
      mode = GET_MODE (op);
--- 1099,1104 ----
*************** general_operand (op, mode)
*** 1080,1090 ****
  
        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)
--- 1136,1141 ----
*************** general_operand (op, mode)
*** 1115,1122 ****
    return 0;
  
   win:
-   if (mode_altering_drug)
-     return ! mode_dependent_address_p (XEXP (op, 0));
    return 1;
  }
  
--- 1166,1171 ----
*************** indirect_operand (op, mode)
*** 1446,1458 ****
    if (! reload_completed
        && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
      {
!       register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
        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;
  
--- 1495,1503 ----
    if (! reload_completed
        && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
      {
!       register int offset = SUBREG_BYTE (op);
        rtx inner = SUBREG_REG (op);
  
        if (mode != VOIDmode && GET_MODE (op) != mode)
  	return 0;
  
*************** constrain_operands (strict)
*** 2461,2467 ****
  	    {
  	      if (GET_CODE (SUBREG_REG (op)) == REG
  		  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
! 		offset = SUBREG_WORD (op);
  	      op = SUBREG_REG (op);
  	    }
  
--- 2506,2515 ----
  	    {
  	      if (GET_CODE (SUBREG_REG (op)) == REG
  		  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
! 		offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
! 					      GET_MODE (SUBREG_REG (op)),
! 					      SUBREG_BYTE (op),
! 					      GET_MODE (op));
  	      op = SUBREG_REG (op);
  	    }
  
Index: gcc/reg-stack.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reg-stack.c,v
retrieving revision 1.65
diff -c -p -r1.65 reg-stack.c
*** gcc/reg-stack.c	2001/02/19 14:59:42	1.65
--- gcc/reg-stack.c	2001/03/07 18:35:28
*************** get_true_reg (pat)
*** 558,564 ****
  	  rtx subreg;
  	  if (FP_REG_P (subreg = SUBREG_REG (*pat)))
  	    {
! 	      *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
  				  GET_MODE (subreg));
  	    default:
  	      return pat;
--- 558,568 ----
  	  rtx subreg;
  	  if (FP_REG_P (subreg = SUBREG_REG (*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: gcc/regmove.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/regmove.c,v
retrieving revision 1.96
diff -c -p -r1.96 regmove.c
*** gcc/regmove.c	2001/01/31 00:20:44	1.96
--- gcc/regmove.c	2001/03/07 18:35:28
*************** optimize_reg_copy_3 (insn, dest, src)
*** 718,724 ****
  
    /* 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);
    while (p = NEXT_INSN (p), p != insn)
      {
        if (! INSN_P (p))
--- 718,724 ----
  
    /* Now walk forward making additional replacements.  We want to be able
       to undo all the changes if a later substitution fails.  */
!   subreg = gen_lowpart_SUBREG (old_mode, src_reg);
    while (p = NEXT_INSN (p), p != insn)
      {
        if (! INSN_P (p))
*************** regmove_optimize (f, nregs, regmove_dump
*** 1164,1170 ****
  		{
  		  src_subreg
  		    = gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
! 				      src, SUBREG_WORD (dst));
  		  dst = SUBREG_REG (dst);
  		}
  	      if (GET_CODE (dst) != REG
--- 1164,1170 ----
  		{
  		  src_subreg
  		    = gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
! 				      src, SUBREG_BYTE (dst));
  		  dst = SUBREG_REG (dst);
  		}
  	      if (GET_CODE (dst) != REG
Index: gcc/regs.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/regs.h,v
retrieving revision 1.20
diff -c -p -r1.20 regs.h
*** gcc/regs.h	2001/02/28 16:23:59	1.20
--- gcc/regs.h	2001/03/07 18:35:28
*************** Boston, MA 02111-1307, USA.  */
*** 24,35 ****
  
  #define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
  
! /* Get the number of consecutive hard regs required to hold the REG 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.  */
  
  #define REG_SIZE(R) \
    ((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
  #ifndef SMALL_REGISTER_CLASSES
  #define SMALL_REGISTER_CLASSES 0
--- 24,51 ----
  
  #define REG_BYTES(R) mode_size[(int) GET_MODE (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.
  
+    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: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.142
diff -c -p -r1.142 reload.c
*** gcc/reload.c	2001/01/24 23:50:56	1.142
--- gcc/reload.c	2001/03/07 18:35:30
*************** reload_inner_reg_of_subreg (x, mode)
*** 792,798 ****
      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))
      return 1;
  
    /* If the outer part is a word or smaller, INNER larger than a
--- 792,798 ----
      return 0;
  
    /* If INNER is not ok for MODE, then INNER will need reloading.  */
!   if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
      return 1;
  
    /* If the outer part is a word or smaller, INNER larger than a
*************** push_reload (in, out, inloc, outloc, cla
*** 939,951 ****
  
       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
       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))
--- 939,950 ----
  
       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_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
  #ifdef CLASS_CANNOT_CHANGE_MODE
        && (class != CLASS_CANNOT_CHANGE_MODE
  	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
*************** push_reload (in, out, inloc, outloc, cla
*** 979,985 ****
  	      && 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)
  	      && ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
  		   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
  		       > UNITS_PER_WORD)
--- 978,984 ----
  	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
  	      /* The case where out is nonzero
  		 is handled differently in the following statement.  */
! 	      && (out == 0 || SUBREG_BYTE (in) == 0)
  	      && ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
  		   && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
  		       > UNITS_PER_WORD)
*************** push_reload (in, out, inloc, outloc, cla
*** 987,995 ****
  			/ 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)))
  #ifdef SECONDARY_INPUT_RELOAD_CLASS
  	  || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
  	      && (SECONDARY_INPUT_RELOAD_CLASS (class,
--- 986,992 ----
  			/ UNITS_PER_WORD)
  		       != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
  					    GET_MODE (SUBREG_REG (in)))))
! 		  || ! 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,
*************** push_reload (in, out, inloc, outloc, cla
*** 1029,1035 ****
       that case.  */
  
    /* Similar issue for (SUBREG constant ...) if it was not handled by the
!      code above.  This can happen if SUBREG_WORD != 0.  */
  
    if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
      {
--- 1026,1032 ----
       that case.  */
  
    /* Similar issue for (SUBREG constant ...) if it was not handled by the
!      code above.  This can happen if SUBREG_BYTE != 0.  */
  
    if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
      {
*************** push_reload (in, out, inloc, outloc, cla
*** 1039,1045 ****
  	 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)),
  		   VOIDmode, VOIDmode, 0, 0, opnum, type);
        dont_remove_subreg = 1;
      }
--- 1036,1046 ----
  	 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_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;
      }
*************** push_reload (in, out, inloc, outloc, cla
*** 1051,1057 ****
       (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)
  #ifdef CLASS_CANNOT_CHANGE_MODE
        && (class != CLASS_CANNOT_CHANGE_MODE
  	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
--- 1052,1058 ----
       (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_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)),
*************** push_reload (in, out, inloc, outloc, cla
*** 1081,1089 ****
  			/ 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)))
  #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
  	  || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
  	      && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
--- 1082,1088 ----
  			/ UNITS_PER_WORD)
  		       != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
  					    GET_MODE (SUBREG_REG (out)))))
! 		  || ! 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,
*************** push_reload (in, out, inloc, outloc, cla
*** 1130,1136 ****
        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)),
  		   VOIDmode, VOIDmode, 0, 0,
  		   opnum, RELOAD_OTHER);
      }
--- 1129,1139 ----
        dont_remove_subreg = 1;
        push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
  		   &SUBREG_REG (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);
      }
*************** push_reload (in, out, inloc, outloc, cla
*** 1147,1162 ****
    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));
  
    /* 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));
  
    /* Narrow down the class of register wanted if that is
       desirable on this machine for efficiency.  */
--- 1150,1163 ----
    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), 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), subreg_regno (out));
  
    /* Narrow down the class of register wanted if that is
       desirable on this machine for efficiency.  */
*************** find_dummy_reload (real_in, real_out, in
*** 1811,1825 ****
  	  || GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
      return 0;
  
    /* Find the inside of any subregs.  */
    while (GET_CODE (out) == SUBREG)
      {
!       out_offset = SUBREG_WORD (out);
        out = SUBREG_REG (out);
      }
    while (GET_CODE (in) == SUBREG)
      {
!       in_offset = SUBREG_WORD (in);
        in = SUBREG_REG (in);
      }
  
--- 1812,1839 ----
  	  || 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)
      {
!       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)
      {
!       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);
      }
  
*************** operands_match_p (x, y)
*** 2036,2042 ****
  	  i = REGNO (SUBREG_REG (x));
  	  if (i >= FIRST_PSEUDO_REGISTER)
  	    goto slow;
! 	  i += SUBREG_WORD (x);
  	}
        else
  	i = REGNO (x);
--- 2050,2059 ----
  	  i = REGNO (SUBREG_REG (x));
  	  if (i >= FIRST_PSEUDO_REGISTER)
  	    goto slow;
! 	  i += subreg_regno_offset (REGNO (SUBREG_REG (x)),
! 				    GET_MODE (SUBREG_REG (x)),
! 				    SUBREG_BYTE (x),
! 				    GET_MODE (x));
  	}
        else
  	i = REGNO (x);
*************** operands_match_p (x, y)
*** 2046,2052 ****
  	  j = REGNO (SUBREG_REG (y));
  	  if (j >= FIRST_PSEUDO_REGISTER)
  	    goto slow;
! 	  j += SUBREG_WORD (y);
  	}
        else
  	j = REGNO (y);
--- 2063,2072 ----
  	  j = REGNO (SUBREG_REG (y));
  	  if (j >= FIRST_PSEUDO_REGISTER)
  	    goto slow;
! 	  j += subreg_regno_offset (REGNO (SUBREG_REG (y)),
! 				    GET_MODE (SUBREG_REG (y)),
! 				    SUBREG_BYTE (y),
! 				    GET_MODE (y));
  	}
        else
  	j = REGNO (y);
*************** find_reloads (insn, replace, ind_levels,
*** 2778,2784 ****
  
  	  while (GET_CODE (operand) == SUBREG)
  	    {
! 	      offset += SUBREG_WORD (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.  */
--- 2798,2815 ----
  
  	  while (GET_CODE (operand) == SUBREG)
  	    {
! 	      /* 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.  */
*************** find_reloads (insn, replace, ind_levels,
*** 2829,2834 ****
--- 2860,2870 ----
  			  )
  #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.  */
*************** find_reloads (insn, replace, ind_levels,
*** 2842,2848 ****
  			       != HARD_REGNO_NREGS (REGNO (operand),
  						    GET_MODE (operand))))
  			  || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
! 						   operand_mode[i]))))
  		force_reload = 1;
  	    }
  
--- 2878,2886 ----
  			       != HARD_REGNO_NREGS (REGNO (operand),
  						    GET_MODE (operand))))
  			  || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
! 						   operand_mode[i])))
! #endif
! 		  )
  		force_reload = 1;
  	    }
  
*************** find_reloads (insn, replace, ind_levels,
*** 3717,3723 ****
  	rtx operand = recog_data.operand[i];
  
  	while (GET_CODE (operand) == SUBREG)
! 	  operand = XEXP (operand, 0);
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
--- 3755,3761 ----
  	rtx operand = recog_data.operand[i];
  
  	while (GET_CODE (operand) == SUBREG)
! 	  operand = SUBREG_REG (operand);
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
*************** find_reloads (insn, replace, ind_levels,
*** 3767,3773 ****
  	    operand = *recog_data.operand_loc[i];
  
  	    while (GET_CODE (operand) == SUBREG)
! 	      operand = XEXP (operand, 0);
  	    if (GET_CODE (operand) == REG)
  	      {
  		if (modified[i] != RELOAD_WRITE)
--- 3805,3811 ----
  	    operand = *recog_data.operand_loc[i];
  
  	    while (GET_CODE (operand) == SUBREG)
! 	      operand = SUBREG_REG (operand);
  	    if (GET_CODE (operand) == REG)
  	      {
  		if (modified[i] != RELOAD_WRITE)
*************** find_reloads (insn, replace, ind_levels,
*** 3790,3796 ****
  	rtx operand = recog_data.operand[i];
  
  	while (GET_CODE (operand) == SUBREG)
! 	  operand = XEXP (operand, 0);
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
--- 3828,3834 ----
  	rtx operand = recog_data.operand[i];
  
  	while (GET_CODE (operand) == SUBREG)
! 	  operand = SUBREG_REG (operand);
  	if ((GET_CODE (operand) == MEM
  	     || (GET_CODE (operand) == REG
  		 && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
*************** find_reloads_toplev (x, opnum, type, ind
*** 4304,4310 ****
  	  && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
  	  && reg_equiv_constant[regno] != 0
  	  && (tem = operand_subword (reg_equiv_constant[regno],
! 				     SUBREG_WORD (x), 0,
  				     GET_MODE (SUBREG_REG (x)))) != 0)
  	{
  	  /* TEM is now a word sized constant for the bits from X that
--- 4342,4348 ----
  	  && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
  	  && reg_equiv_constant[regno] != 0
  	  && (tem = operand_subword (reg_equiv_constant[regno],
! 				     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
*************** find_reloads_toplev (x, opnum, type, ind
*** 4330,4336 ****
  	  && (GET_MODE_SIZE (GET_MODE (x))
  	      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
  	{
! 	  int shift = SUBREG_WORD (x) * BITS_PER_WORD;
  	  if (WORDS_BIG_ENDIAN)
  	    shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
  		     - GET_MODE_BITSIZE (GET_MODE (x))
--- 4368,4374 ----
  	  && (GET_MODE_SIZE (GET_MODE (x))
  	      < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
  	{
! 	  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))
*************** find_reloads_toplev (x, opnum, type, ind
*** 4384,4396 ****
  	 the meaning of the memory access.  */
        enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
  
        if (is_set_dest)
  	push_reload (NULL_RTX, SUBREG_REG (x), NULL_PTR, &SUBREG_REG (x),
! 		     find_valid_class (subreg_mode, SUBREG_WORD (x)),
  		     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)),
  		     subreg_mode, VOIDmode, 0, 0, opnum, type);
      }
  
--- 4422,4439 ----
  	 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_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_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
  		     subreg_mode, VOIDmode, 0, 0, opnum, type);
      }
  
*************** find_reloads_address_1 (mode, x, context
*** 5076,5082 ****
  	    code0 = GET_CODE (op0);
  	    if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
  	      op0 = gen_rtx_REG (word_mode,
! 				 REGNO (op0) + SUBREG_WORD (orig_op0));
  	  }
  
  	if (GET_CODE (op1) == SUBREG)
--- 5119,5129 ----
  	    code0 = GET_CODE (op0);
  	    if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
  	      op0 = gen_rtx_REG (word_mode,
! 				 (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)
*************** find_reloads_address_1 (mode, x, context
*** 5084,5091 ****
  	    op1 = SUBREG_REG (op1);
  	    code1 = GET_CODE (op1);
  	    if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
  	      op1 = gen_rtx_REG (GET_MODE (op1),
! 				 REGNO (op1) + SUBREG_WORD (orig_op1));
  	  }
  
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
--- 5131,5144 ----
  	    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_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
*************** find_reloads_address_1 (mode, x, context
*** 5493,5499 ****
  	     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);
  
  	      if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
  		     : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
--- 5546,5552 ----
  	     needless copies if SUBREG_REG is multi-word.  */
  	  if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
  	    {
! 	      int regno = subreg_regno (x);
  
  	      if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
  		     : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
*************** find_reloads_subreg_address (x, force_re
*** 5647,5661 ****
  	  if (force_replace
  	      || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
  	    {
! 	      int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  	      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));
  
--- 5700,5709 ----
  	  if (force_replace
  	      || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
  	    {
! 	      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)));
  
  	      XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
  	      PUT_MODE (tem, GET_MODE (x));
  
*************** subst_reloads (insn)
*** 5742,5749 ****
  		*r->subreg_loc = SUBREG_REG (reloadreg);
  	      else
  		{
  		  *r->where = SUBREG_REG (reloadreg);
! 		  SUBREG_WORD (*r->subreg_loc) += SUBREG_WORD (reloadreg);
  		}
  	    }
  	  else
--- 5790,5807 ----
  		*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_BYTE (*r->subreg_loc) = final_offset;
  		}
  	    }
  	  else
*************** find_replacement (loc)
*** 5844,5855 ****
  
  	  if (GET_CODE (reloadreg) == REG)
  	    return gen_rtx_REG (GET_MODE (*loc),
! 				REGNO (reloadreg) + SUBREG_WORD (*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));
  	}
      }
  
--- 5902,5925 ----
  
  	  if (GET_CODE (reloadreg) == REG)
  	    return gen_rtx_REG (GET_MODE (*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
! 	    {
! 	      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);
! 	    }
  	}
      }
  
*************** refers_to_regno_for_reload_p (regno, end
*** 5926,5932 ****
        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_endregno
  	    = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
  			     ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
--- 5996,6002 ----
        if (GET_CODE (SUBREG_REG (x)) == REG
  	  && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
  	{
! 	  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);
*************** reg_overlap_mentioned_for_reload_p (x, i
*** 6021,6027 ****
      {
        regno = REGNO (SUBREG_REG (x));
        if (regno < FIRST_PSEUDO_REGISTER)
! 	regno += SUBREG_WORD (x);
      }
    else if (GET_CODE (x) == REG)
      {
--- 6091,6100 ----
      {
        regno = REGNO (SUBREG_REG (x));
        if (regno < FIRST_PSEUDO_REGISTER)
! 	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: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.258
diff -c -p -r1.258 reload1.c
*** gcc/reload1.c	2001/03/01 13:35:13	1.258
--- gcc/reload1.c	2001/03/07 18:35:31
*************** eliminate_regs (x, mem_mode, insn)
*** 2511,2517 ****
        return x;
  
      case SUBREG:
!       /* Similar to above processing, but preserve SUBREG_WORD.
  	 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
--- 2511,2517 ----
        return x;
  
      case SUBREG:
!       /* 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
*************** eliminate_regs (x, mem_mode, insn)
*** 2528,2534 ****
        else
  	new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
  
!       if (new != XEXP (x, 0))
  	{
  	  int x_size = GET_MODE_SIZE (GET_MODE (x));
  	  int new_size = GET_MODE_SIZE (GET_MODE (new));
--- 2528,2534 ----
        else
  	new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
  
!       if (new != SUBREG_REG (x))
  	{
  	  int x_size = GET_MODE_SIZE (GET_MODE (x));
  	  int new_size = GET_MODE_SIZE (GET_MODE (new));
*************** eliminate_regs (x, mem_mode, insn)
*** 2549,2568 ****
  		  || (x_size == new_size))
  	      )
  	    {
! 	      int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  	      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 x;
--- 2549,2563 ----
  		  || (x_size == new_size))
  	      )
  	    {
! 	      int offset = SUBREG_BYTE (x);
  	      enum machine_mode mode = GET_MODE (x);
  
  	      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_BYTE (x));
  	}
  
        return x;
*************** forget_old_reloads_1 (x, ignored, data)
*** 4084,4093 ****
    unsigned int nr;
    int offset = 0;
  
!   /* note_stores does give us subregs of hard regs.  */
    while (GET_CODE (x) == SUBREG)
      {
!       offset += SUBREG_WORD (x);
        x = SUBREG_REG (x);
      }
  
--- 4079,4092 ----
    unsigned int nr;
    int offset = 0;
  
!   /* 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_regno_offset (REGNO (SUBREG_REG (x)),
! 				     GET_MODE (SUBREG_REG (x)),
! 				     SUBREG_BYTE (x),
! 				     GET_MODE (x));
        x = SUBREG_REG (x);
      }
  
*************** choose_reload_regs (chain)
*** 5397,5403 ****
  
  	  if (inheritance)
  	    {
! 	      int word = 0;
  	      register int regno = -1;
  	      enum machine_mode mode = VOIDmode;
  
--- 5396,5402 ----
  
  	  if (inheritance)
  	    {
! 	      int byte = 0;
  	      register int regno = -1;
  	      enum machine_mode mode = VOIDmode;
  
*************** choose_reload_regs (chain)
*** 5416,5425 ****
  	      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);
  		  regno = REGNO (SUBREG_REG (rld[r].in_reg));
  		  if (regno < FIRST_PSEUDO_REGISTER)
! 		    regno += word;
  		  mode = GET_MODE (rld[r].in_reg);
  		}
  #ifdef AUTO_INC_DEC
--- 5415,5424 ----
  	      else if (GET_CODE (rld[r].in_reg) == SUBREG
  		       && GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
  		{
! 		  byte = SUBREG_BYTE (rld[r].in_reg);
  		  regno = REGNO (SUBREG_REG (rld[r].in_reg));
  		  if (regno < FIRST_PSEUDO_REGISTER)
! 		    regno = subreg_regno (rld[r].in_reg);
  		  mode = GET_MODE (rld[r].in_reg);
  		}
  #ifdef AUTO_INC_DEC
*************** choose_reload_regs (chain)
*** 5440,5446 ****
  		 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);
  #endif
  
  	      if (regno >= 0 && reg_last_reload_reg[regno] != 0)
--- 5439,5445 ----
  		 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 = subreg_regno (rld[r].in);
  #endif
  
  	      if (regno >= 0 && reg_last_reload_reg[regno] != 0)
*************** choose_reload_regs (chain)
*** 5449,5463 ****
  		  rtx last_reg = reg_last_reload_reg[regno];
  		  enum machine_mode need_mode;
  
! 		  i = REGNO (last_reg) + word;
  		  last_class = REGNO_REG_CLASS (i);
  
! 		  if (word == 0)
  		    need_mode = mode;
  		  else
  		    need_mode
! 		      = smallest_mode_for_size (GET_MODE_SIZE (mode)
! 						+ word * UNITS_PER_WORD,
  						GET_MODE_CLASS (mode));
  
  		  if (
--- 5448,5462 ----
  		  rtx last_reg = reg_last_reload_reg[regno];
  		  enum machine_mode need_mode;
  
! 		  i = REGNO (last_reg);
! 		  i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
  		  last_class = REGNO_REG_CLASS (i);
  
! 		  if (byte == 0)
  		    need_mode = mode;
  		  else
  		    need_mode
! 		      = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
  						GET_MODE_CLASS (mode));
  
  		  if (
*************** choose_reload_regs (chain)
*** 5627,5633 ****
  			 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);
  		      equiv = gen_rtx_REG (rld[r].mode, regno);
  		    }
  		  else
--- 5626,5632 ----
  			 Make a new REG since this might be used in an
  			 address and not all machines support SUBREGs
  			 there.  */
! 		      regno = subreg_regno (equiv);
  		      equiv = gen_rtx_REG (rld[r].mode, regno);
  		    }
  		  else
*************** emit_input_reload_insns (chain, rl, old,
*** 6257,6263 ****
      oldequiv = SUBREG_REG (oldequiv);
    if (GET_MODE (oldequiv) != VOIDmode
        && mode != GET_MODE (oldequiv))
!     oldequiv = gen_rtx_SUBREG (mode, oldequiv, 0);
  
    /* Switch to the right place to emit the reload insns.  */
    switch (rl->when_needed)
--- 6256,6262 ----
      oldequiv = SUBREG_REG (oldequiv);
    if (GET_MODE (oldequiv) != VOIDmode
        && mode != GET_MODE (oldequiv))
!     oldequiv = gen_lowpart_SUBREG (mode, oldequiv);
  
    /* Switch to the right place to emit the reload insns.  */
    switch (rl->when_needed)
*************** reload_combine_note_store (dst, set, dat
*** 8872,8878 ****
  
    if (GET_CODE (dst) == SUBREG)
      {
!       regno = SUBREG_WORD (dst);
        dst = SUBREG_REG (dst);
      }
    if (GET_CODE (dst) != REG)
--- 8871,8880 ----
  
    if (GET_CODE (dst) == SUBREG)
      {
!       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)
*************** move2add_note_store (dst, set, data)
*** 9263,9269 ****
  
    if (GET_CODE (dst) == SUBREG)
      {
!       regno = SUBREG_WORD (dst);
        dst = SUBREG_REG (dst);
      }
  
--- 9265,9274 ----
  
    if (GET_CODE (dst) == SUBREG)
      {
!       regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
! 				   GET_MODE (SUBREG_REG (dst)),
! 				   SUBREG_BYTE (dst),
! 				   GET_MODE (dst));
        dst = SUBREG_REG (dst);
      }
  
Index: gcc/resource.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/resource.c,v
retrieving revision 1.40
diff -c -p -r1.40 resource.c
*** gcc/resource.c	2001/02/23 17:47:52	1.40
--- gcc/resource.c	2001/03/07 18:35:32
*************** update_live_status (dest, x, data)
*** 100,106 ****
      return;
  
    if (GET_CODE (dest) == SUBREG)
!     first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
    else
      first_regno = REGNO (dest);
  
--- 100,106 ----
      return;
  
    if (GET_CODE (dest) == SUBREG)
!     first_regno = subreg_regno (dest);
    else
      first_regno = REGNO (dest);
  
*************** mark_referenced_resources (x, res, inclu
*** 222,228 ****
  	mark_referenced_resources (SUBREG_REG (x), res, 0);
        else
  	{
! 	  unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
  	  unsigned int last_regno
  	    = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
  
--- 222,228 ----
  	mark_referenced_resources (SUBREG_REG (x), res, 0);
        else
  	{
! 	  unsigned int regno = subreg_regno (x);
  	  unsigned int last_regno
  	    = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
  
*************** mark_set_resources (x, res, in_dest, mar
*** 780,786 ****
  	    mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
  	  else
  	    {
! 	      unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
  	      unsigned int last_regno
  		= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
  
--- 780,786 ----
  	    mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
  	  else
  	    {
! 	      unsigned int regno = subreg_regno (x);
  	      unsigned int last_regno
  		= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
  
Index: gcc/rtl.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.h,v
retrieving revision 1.245
diff -c -p -r1.245 rtl.h
*** gcc/rtl.h	2001/03/02 21:41:36	1.245
--- gcc/rtl.h	2001/03/07 18:35:33
*************** extern const char * const note_insn_name
*** 789,799 ****
  #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.  */
  
  #define SUBREG_REG(RTX) XCEXP(RTX, 0, SUBREG)
! #define SUBREG_WORD(RTX) XCUINT(RTX, 1, SUBREG)
  
  /* 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
     the reg.  SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
--- 789,806 ----
  #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_BYTE extracts the byte-number.  */
  
  #define SUBREG_REG(RTX) XCEXP(RTX, 0, 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
     the reg.  SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
*************** extern int rtx_equal_p                  
*** 1183,1188 ****
--- 1190,1196 ----
  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));
  
*************** extern rtx gen_realpart			PARAMS ((enum 
*** 1195,1200 ****
--- 1203,1210 ----
  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,
*************** extern rtx gen_rtx_CONST_DOUBLE PARAMS (
*** 1573,1579 ****
--- 1583,1592 ----
  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.  */
Index: gcc/rtl.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtl.texi,v
retrieving revision 1.35
diff -c -p -r1.35 rtl.texi
*** gcc/rtl.texi	2001/02/02 06:11:26	1.35
--- gcc/rtl.texi	2001/03/07 18:35:34
*************** This virtual register is replaced by the
*** 1166,1181 ****
  @end table
  
  @findex subreg
! @item (subreg:@var{m} @var{reg} @var{wordnum})
  @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.
  
  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.
  
  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
--- 1166,1181 ----
  @end table
  
  @findex subreg
! @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-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{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
*************** a multi-register value.  Machine modes s
*** 1192,1198 ****
  @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.
  
  Storing in a non-paradoxical @code{subreg} has undefined results for
  bits belonging to the same word as the @code{subreg}.  This laxity makes
--- 1192,1198 ----
  @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{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
*************** the @code{subreg}, use @code{strict_low_
*** 1202,1210 ****
  
  @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.
  
  @cindex @code{FLOAT_WORDS_BIG_ENDIAN}, (lack of) effect on @code{subreg}
  On a few targets, @code{FLOAT_WORDS_BIG_ENDIAN} disagrees with
  @code{WORDS_BIG_ENDIAN}.
--- 1202,1215 ----
  
  @cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
  The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
! 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
  @code{WORDS_BIG_ENDIAN}.
*************** a single machine register.  The reload p
*** 1239,1248 ****
  expressions such as these from being formed.
  
  @findex SUBREG_REG
! @findex SUBREG_WORD
  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.
  
  @findex scratch
  @cindex scratch operands
--- 1244,1253 ----
  expressions such as these from being formed.
  
  @findex SUBREG_REG
! @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_BYTE} macro.
  
  @findex scratch
  @cindex scratch operands
Index: gcc/rtlanal.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/rtlanal.c,v
retrieving revision 1.89
diff -c -p -r1.89 rtlanal.c
*** gcc/rtlanal.c	2001/02/25 19:34:06	1.89
--- gcc/rtlanal.c	2001/03/07 18:35:35
*************** refers_to_regno_p (regno, endregno, x, l
*** 1067,1073 ****
        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_endregno
  	    = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
  			     ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
--- 1067,1073 ----
        if (GET_CODE (SUBREG_REG (x)) == REG
  	  && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
  	{
! 	  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);
*************** reg_overlap_mentioned_p (x, in)
*** 1154,1160 ****
      case SUBREG:
        regno = REGNO (SUBREG_REG (x));
        if (regno < FIRST_PSEUDO_REGISTER)
! 	regno += SUBREG_WORD (x);
        goto do_reg;
  
      case REG:
--- 1154,1160 ----
      case SUBREG:
        regno = REGNO (SUBREG_REG (x));
        if (regno < FIRST_PSEUDO_REGISTER)
! 	regno = subreg_regno (x);
        goto do_reg;
  
      case REG:
*************** replace_regs (x, reg_map, nregs, replace
*** 2213,2230 ****
  	    return map_inner;
  	  else
  	    {
  	      /* 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);
  	      return x;
  #if 0
  	      rtx new = rtx_alloc (SUBREG);
  	      PUT_MODE (new, GET_MODE (x));
  	      SUBREG_REG (new) = map_inner;
! 	      SUBREG_WORD (new) = SUBREG_WORD (x) + SUBREG_WORD (map_val);
  #endif
  	    }
  	}
--- 2213,2244 ----
  	    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_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_BYTE (new) = final_offset;
  #endif
  	    }
  	}
*************** loc_mentioned_in_p (loc, in)
*** 2596,2599 ****
--- 2610,2675 ----
  	    return 1;
      }
    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: gcc/sched-vis.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/sched-vis.c,v
retrieving revision 1.5
diff -c -p -r1.5 sched-vis.c
*** gcc/sched-vis.c	2000/12/22 12:27:36	1.5
--- gcc/sched-vis.c	2001/03/07 18:35:36
*************** print_value (buf, x, verbose)
*** 591,597 ****
      case SUBREG:
        print_value (t, SUBREG_REG (x), verbose);
        cur = safe_concat (buf, cur, t);
!       sprintf (t, "#%d", SUBREG_WORD (x));
        cur = safe_concat (buf, cur, t);
        break;
      case SCRATCH:
--- 591,597 ----
      case SUBREG:
        print_value (t, SUBREG_REG (x), verbose);
        cur = safe_concat (buf, cur, t);
!       sprintf (t, "#%d", SUBREG_BYTE (x));
        cur = safe_concat (buf, cur, t);
        break;
      case SCRATCH:
Index: gcc/sdbout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/sdbout.c,v
retrieving revision 1.39
diff -c -p -r1.39 sdbout.c
*** gcc/sdbout.c	2001/01/30 01:26:25	1.39
--- gcc/sdbout.c	2001/03/07 18:35:37
*************** sdbout_symbol (decl, local)
*** 796,814 ****
        else if (GET_CODE (value) == SUBREG)
  	{
  	  int offset = 0;
  	  while (GET_CODE (value) == SUBREG)
! 	    {
! 	      offset += SUBREG_WORD (value);
! 	      value = SUBREG_REG (value);
! 	    }
  	  if (GET_CODE (value) == REG)
  	    {
! 	      regno = REGNO (value);
! 	      if (regno >= FIRST_PSEUDO_REGISTER)
  		return;
- 	      regno += offset;
  	    }
! 	  alter_subreg (DECL_RTL (decl));
  	  value = DECL_RTL (decl);
  	}
        /* Don't output anything if an auto variable
--- 796,810 ----
        else if (GET_CODE (value) == SUBREG)
  	{
  	  int offset = 0;
+ 
  	  while (GET_CODE (value) == SUBREG)
! 	    value = SUBREG_REG (value);
  	  if (GET_CODE (value) == REG)
  	    {
! 	      if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
  		return;
  	    }
! 	  regno = REGNO (alter_subreg (DECL_RTL (decl)));
  	  value = DECL_RTL (decl);
  	}
        /* Don't output anything if an auto variable
Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stmt.c,v
retrieving revision 1.185
diff -c -p -r1.185 stmt.c
*** gcc/stmt.c	2001/02/20 18:22:27	1.185
--- gcc/stmt.c	2001/03/07 18:35:39
*************** expand_anon_union_decl (decl, cleanup, d
*** 4274,4280 ****
  	  if (mode == GET_MODE (x))
  	    DECL_RTL (decl_elt) = x;
  	  else
! 	    DECL_RTL (decl_elt) = gen_rtx_SUBREG (mode, x, 0);
  	}
        else
  	abort ();
--- 4274,4280 ----
  	  if (mode == GET_MODE (x))
  	    DECL_RTL (decl_elt) = x;
  	  else
! 	    DECL_RTL (decl_elt) = gen_lowpart_SUBREG (mode, x);
  	}
        else
  	abort ();
Index: gcc/tm.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tm.texi,v
retrieving revision 1.175
diff -c -p -r1.175 tm.texi
*** gcc/tm.texi	2001/03/03 03:53:43	1.175
--- gcc/tm.texi	2001/03/07 18:35:44
*************** definition of this macro is
*** 1697,1713 ****
      / 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
--- 1697,1702 ----
*************** allocation.
*** 1790,1795 ****
--- 1779,1797 ----
  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
Index: gcc/config/a29k/a29k.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/a29k/a29k.c,v
retrieving revision 1.12
diff -c -p -r1.12 a29k.c
*** gcc/config/a29k/a29k.c	2000/11/09 07:45:14	1.12
--- gcc/config/a29k/a29k.c	2001/03/07 18:36:00
*************** gpc_reg_operand (op, mode)
*** 263,271 ****
      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);
      }
    else
      return 0;
--- 263,272 ----
      regno = REGNO (op);
    else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
      {
!       if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
! 	regno = subreg_regno (op);
!       else
! 	regno = REGNO (SUBREG_REG (op));
      }
    else
      return 0;
*************** a29k_get_reloaded_address (op)
*** 468,474 ****
  {
    if (GET_CODE (op) == SUBREG)
      {
!       if (SUBREG_WORD (op) != 0)
  	abort ();
  
        op = SUBREG_REG (op);
--- 469,475 ----
  {
    if (GET_CODE (op) == SUBREG)
      {
!       if (SUBREG_BYTE (op) != 0)
  	abort ();
  
        op = SUBREG_REG (op);
*************** print_operand (file, x, code)
*** 1185,1191 ****
        if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
  	fprintf (file, "$float");
        else
! 	fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0)));
        memcpy ((char *) &u,
  	      (char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), sizeof u);
        fprintf (file, "(%.20e)", u.d);
--- 1189,1196 ----
        if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
  	fprintf (file, "$float");
        else
! 	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: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.155
diff -c -p -r1.155 alpha.c
*** gcc/config/alpha/alpha.c	2001/01/16 14:29:08	1.155
--- gcc/config/alpha/alpha.c	2001/03/07 18:36:01
*************** print_operand_address (file, addr)
*** 4100,4106 ****
      basereg = REGNO (addr);
    else if (GET_CODE (addr) == SUBREG
  	   && GET_CODE (SUBREG_REG (addr)) == REG)
!     basereg = REGNO (SUBREG_REG (addr)) + SUBREG_WORD (addr);
    else if (GET_CODE (addr) == CONST_INT)
      offset = INTVAL (addr);
    else
--- 4100,4107 ----
      basereg = REGNO (addr);
    else if (GET_CODE (addr) == SUBREG
  	   && GET_CODE (SUBREG_REG (addr)) == REG)
!     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: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/arm/arm.c,v
retrieving revision 1.142
diff -c -p -r1.142 arm.c
*** gcc/config/arm/arm.c	2001/02/09 02:00:44	1.142
--- gcc/config/arm/arm.c	2001/03/07 18:36:05
*************** arm_reload_in_hi (operands)
*** 4749,4759 ****
  
    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)))));
        ref = SUBREG_REG (ref);
      }
  
--- 4749,4755 ----
  
    if (GET_CODE (ref) == SUBREG)
      {
!       offset = SUBREG_BYTE (ref);
        ref = SUBREG_REG (ref);
      }
  
*************** arm_reload_out_hi (operands)
*** 4866,4876 ****
  
    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)))));
        ref = SUBREG_REG (ref);
      }
  
--- 4862,4868 ----
  
    if (GET_CODE (ref) == SUBREG)
      {
!       offset = SUBREG_BYTE (ref);
        ref = SUBREG_REG (ref);
      }
  
Index: gcc/config/d30v/d30v.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/d30v/d30v.c,v
retrieving revision 1.5
diff -c -p -r1.5 d30v.c
*** gcc/config/d30v/d30v.c	2001/01/11 01:47:23	1.5
--- gcc/config/d30v/d30v.c	2001/03/07 18:36:13
*************** d30v_split_double (value, p_high, p_low)
*** 2668,2677 ****
    switch (GET_CODE (value))
      {
      case SUBREG:
!       offset = SUBREG_WORD (value);
!       value = SUBREG_REG (value);
!       if (GET_CODE (value) != REG)
  	abort ();
  
        /* fall through */
  
--- 2668,2680 ----
    switch (GET_CODE (value))
      {
      case SUBREG:
!       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 */
  
*************** d30v_print_operand_memory_reference (str
*** 2796,2802 ****
  
        if (GET_CODE (x0) == SUBREG)
  	{
! 	  offset0 = SUBREG_WORD (x0);
  	  x0 = SUBREG_REG (x0);
  	}
  
--- 2799,2808 ----
  
        if (GET_CODE (x0) == SUBREG)
  	{
! 	  offset0 = subreg_regno_offset (REGNO (SUBREG_REG (x0)),
! 					 GET_MODE (SUBREG_REG (x0)),
! 					 SUBREG_BYTE (x0),
! 					 GET_MODE (x0));
  	  x0 = SUBREG_REG (x0);
  	}
  
*************** d30v_print_operand_memory_reference (str
*** 2829,2835 ****
        switch (GET_CODE (x1))
  	{
  	case SUBREG:
! 	  offset1 = SUBREG_WORD (x1);
  	  x1 = SUBREG_REG (x1);
  	  if (GET_CODE (x1) != REG)
  	    fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x);
--- 2835,2844 ----
        switch (GET_CODE (x1))
  	{
  	case SUBREG:
! 	  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: gcc/config/dsp16xx/dsp16xx.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/dsp16xx/dsp16xx.md,v
retrieving revision 1.8
diff -c -p -r1.8 dsp16xx.md
*** gcc/config/dsp16xx/dsp16xx.md	2001/02/04 22:44:11	1.8
--- gcc/config/dsp16xx/dsp16xx.md	2001/03/07 18:36:16
***************
*** 1258,1264 ****
    "
  {
  	operands[2] = gen_reg_rtx (HImode);
! 	operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
  }")
  
  ;;(define_insn "extendqihi2"
--- 1258,1264 ----
    "
  {
  	operands[2] = gen_reg_rtx (HImode);
! 	operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
  }")
  
  ;;(define_insn "extendqihi2"
***************
*** 1308,1314 ****
    "
  {
  	operands[2] = gen_reg_rtx (HImode);
! 	operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
  }")
  
  
--- 1308,1314 ----
    "
  {
  	operands[2] = gen_reg_rtx (HImode);
! 	operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
  }")
  
  
Index: gcc/config/h8300/h8300.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/h8300/h8300.md,v
retrieving revision 1.26
diff -c -p -r1.26 h8300.md
*** gcc/config/h8300/h8300.md	2001/02/21 18:09:48	1.26
--- gcc/config/h8300/h8300.md	2001/03/07 18:36:17
***************
*** 1925,1931 ****
  	(subreg:HI (zero_extract:SI
  		     (match_operand:HI 1 "register_operand" "r")
  		     (const_int 1)
! 		     (match_operand:HI 2 "immediate_operand" "n")) 1))]
    ""
    "sub.w	%0,%0\;bld	%Z2,%Y1\;bst	#0,%X0"
    [(set_attr "cc" "clobber")
--- 1925,1931 ----
  	(subreg:HI (zero_extract:SI
  		     (match_operand:HI 1 "register_operand" "r")
  		     (const_int 1)
! 		     (match_operand:HI 2 "immediate_operand" "n")) 2))]
    ""
    "sub.w	%0,%0\;bld	%Z2,%Y1\;bst	#0,%X0"
    [(set_attr "cc" "clobber")
***************
*** 1966,1972 ****
  		  (subreg:HI
  		    (lshiftrt:SI
  		      (match_operand:SI 1 "register_operand" "Ur")
! 		      (match_operand:SI 2 "const_int_operand" "n")) 1))
  		(const_int 1)))]
    "INTVAL (operands[2]) < 16"
    "sub.w	%0,%0\;bild	%Z2,%Y1\;bst	#0,%X0"
--- 1966,1972 ----
  		  (subreg:HI
  		    (lshiftrt:SI
  		      (match_operand:SI 1 "register_operand" "Ur")
! 		      (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: gcc/config/i370/i370.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i370/i370.md,v
retrieving revision 1.15
diff -c -p -r1.15 i370.md
*** gcc/config/i370/i370.md	2000/10/18 02:06:38	1.15
--- gcc/config/i370/i370.md	2001/03/07 18:36:18
*************** check_label_emit ();
*** 537,548 ****
          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_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);
  
          /* Compare! */
          emit_insn (gen_cmpstrsi_1 (result, reg1, reg2));
--- 537,548 ----
          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, 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, GET_MODE_SIZE (SImode)), len);
  
          /* Compare! */
          emit_insn (gen_cmpstrsi_1 (result, reg1, reg2));
*************** check_label_emit ();
*** 1409,1419 ****
          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_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);
  
          /* Copy! */
          emit_insn (gen_movstrsi_1 (reg1, reg2));
--- 1409,1419 ----
          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, 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, GET_MODE_SIZE (SImode)), zippo);
  
          /* Copy! */
          emit_insn (gen_movstrsi_1 (reg1, reg2));
*************** check_label_emit ();
*** 1476,1487 ****
          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_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);
  
          /* Copy! */
          emit_insn (gen_movstrsi_1 (reg1, reg2));
--- 1476,1487 ----
          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, 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, GET_MODE_SIZE (SImode)), len);
  
          /* Copy! */
          emit_insn (gen_movstrsi_1 (reg1, reg2));
*************** check_label_emit ();
*** 2425,2435 ****
         * 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]));
        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)));
      }
    DONE;
  }")
--- 2425,2436 ----
         * Dunno how to untwist it elegantly; but it seems to work for now.
         */
        emit_insn (gen_rtx_SET (VOIDmode,
! 			  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, GET_MODE_SIZE (SImode))));
      }
    DONE;
  }")
*************** check_label_emit ();
*** 2534,2540 ****
    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)));
    DONE;
  }")
  
--- 2535,2541 ----
    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, GET_MODE_SIZE (SImode))));
    DONE;
  }")
  
*************** check_label_emit ();
*** 2552,2558 ****
  {
    rtx dr = gen_reg_rtx (DImode);
    rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0);
!   rtx dr_1 = gen_rtx_SUBREG (SImode, dr, 1);
  
  
    if (GET_CODE (operands[2]) == CONST_INT)
--- 2553,2559 ----
  {
    rtx dr = gen_reg_rtx (DImode);
    rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0);
!   rtx dr_1 = gen_rtx_SUBREG (SImode, dr, GET_MODE_SIZE (SImode));
  
  
    if (GET_CODE (operands[2]) == CONST_INT)
Index: gcc/config/i860/i860.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i860/i860.c,v
retrieving revision 1.16
diff -c -p -r1.16 i860.c
*** gcc/config/i860/i860.c	2000/08/08 22:22:32	1.16
--- gcc/config/i860/i860.c	2001/03/07 18:36:23
*************** single_insn_src_p (op, mode)
*** 341,347 ****
        return 1;
  
      case SUBREG:
!       if (SUBREG_WORD (op) != 0)
  	return 0;
        return single_insn_src_p (SUBREG_REG (op), mode);
  
--- 341,347 ----
        return 1;
  
      case SUBREG:
!       if (SUBREG_BYTE (op) != 0)
  	return 0;
        return single_insn_src_p (SUBREG_REG (op), mode);
  
Index: gcc/config/i860/i860.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i860/i860.md,v
retrieving revision 1.8
diff -c -p -r1.8 i860.md
*** gcc/config/i860/i860.md	2000/07/23 19:51:43	1.8
--- gcc/config/i860/i860.md	2001/03/07 18:36:24
***************
*** 1730,1741 ****
  }")
  
  (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" ""))
     (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))]
    "WORDS_BIG_ENDIAN"
    "
  {
--- 1730,1741 ----
  }")
  
  (define_expand "mulsi3_big"
!   [(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) 4)
! 	(mult:SI (subreg:SI (match_dup 4) 4) (subreg:SI (match_dup 5) 4)))
!    (set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 4))]
    "WORDS_BIG_ENDIAN"
    "
  {
***************
*** 1752,1760 ****
    "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)))]
    "WORDS_BIG_ENDIAN"
    "fmlow.dd %2,%1,%0")
  
--- 1752,1760 ----
    "fmlow.dd %2,%1,%0")
  
  (define_insn ""
!   [(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")
  
Index: gcc/config/i960/i960.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i960/i960.md,v
retrieving revision 1.18
diff -c -p -r1.18 i960.md
*** gcc/config/i960/i960.md	2001/01/10 21:12:28	1.18
--- gcc/config/i960/i960.md	2001/03/07 18:36:25
***************
*** 1211,1225 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_16 = GEN_INT (16);
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
--- 1211,1227 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_16 = GEN_INT (16);
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  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_byte);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
***************
*** 1246,1260 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
--- 1248,1264 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  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_byte);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
***************
*** 1282,1305 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op0_subreg_word = 0;
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        if (GET_CODE (operand0) == SUBREG)
  	{
! 	  op0_subreg_word = SUBREG_WORD (operand0);
  	  operand0 = SUBREG_REG (operand0);
  	}
        if (GET_MODE (operand0) != SImode)
! 	operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
--- 1286,1313 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op0_subreg_byte = 0;
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  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_byte);
  
        if (GET_CODE (operand0) == SUBREG)
  	{
! 	  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_byte);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
***************
*** 1327,1341 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_16 = GEN_INT (16);
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
        emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
--- 1335,1351 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_16 = GEN_INT (16);
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  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_byte);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
        emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
***************
*** 1367,1381 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
! 	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
--- 1377,1393 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
!           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_byte);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
***************
*** 1403,1426 ****
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op0_subreg_word = 0;
!       int op1_subreg_word = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_word = SUBREG_WORD (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
  
        if (GET_CODE (operand0) == SUBREG)
  	{
! 	  op0_subreg_word = SUBREG_WORD (operand0);
  	  operand0 = SUBREG_REG (operand0);
  	}
        if (GET_MODE (operand0) != SImode)
! 	operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
  
        emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
        emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
--- 1415,1438 ----
      {
        rtx temp = gen_reg_rtx (SImode);
        rtx shift_24 = GEN_INT (24);
!       int op0_subreg_byte = 0;
!       int op1_subreg_byte = 0;
  
        if (GET_CODE (operand1) == SUBREG)
  	{
! 	  op1_subreg_byte = SUBREG_BYTE (operand1);
  	  operand1 = SUBREG_REG (operand1);
  	}
        if (GET_MODE (operand1) != SImode)
! 	operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
  
        if (GET_CODE (operand0) == SUBREG)
  	{
! 	  op0_subreg_byte = SUBREG_BYTE (operand0);
  	  operand0 = SUBREG_REG (operand0);
  	}
        if (GET_MODE (operand0) != SImode)
! 	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: gcc/config/m68hc11/m68hc11.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m68hc11/m68hc11.c,v
retrieving revision 1.2
diff -c -p -r1.2 m68hc11.c
*** gcc/config/m68hc11/m68hc11.c	2001/02/04 22:44:11	1.2
--- gcc/config/m68hc11/m68hc11.c	2001/03/07 18:36:31
*************** m68hc11_gen_lowpart (mode, x)
*** 1757,1768 ****
      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 (mode == SImode)
! 	return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 2);
        else if (mode == HImode)
! 	return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 1);
        else
  	abort ();
      }
--- 1757,1768 ----
      return gen_rtx (REG, mode, HARD_B_REGNUM);
  
    /* gen_lowpart crashes when it is called with a SUBREG.  */
!   if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
      {
        if (mode == SImode)
! 	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_BYTE (x) + 1);
        else
  	abort ();
      }
*************** m68hc11_gen_highpart (mode, x)
*** 1862,1868 ****
      }
  
    /* gen_highpart crashes when it is called with a SUBREG.  */
!   if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
      {
        return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));
      }
--- 1862,1868 ----
      }
  
    /* gen_highpart crashes when it is called with a SUBREG.  */
!   if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
      {
        return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));
      }
Index: gcc/config/m68k/m68k.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m68k/m68k.md,v
retrieving revision 1.36
diff -c -p -r1.36 m68k.md
*** gcc/config/m68k/m68k.md	2000/11/28 21:31:43	1.36
--- gcc/config/m68k/m68k.md	2001/03/07 18:36:35
***************
*** 1554,1560 ****
    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]));
    else
      operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
  }")
--- 1554,1560 ----
    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_BYTE (operands[0]));
    else
      operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
  }")
***************
*** 1570,1576 ****
    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]));
    else
      operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
  }")
--- 1570,1576 ----
    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_BYTE (operands[0]));
    else
      operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
  }")
***************
*** 1586,1592 ****
    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]));
    else
      operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
  }")
--- 1586,1592 ----
    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_BYTE (operands[0]));
    else
      operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
  }")
***************
*** 3096,3102 ****
  ;; 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)
  	  (mult:SI (match_operand:SI 1 "register_operand" "")
  		   (match_operand:SI 2 "nonimmediate_operand" "")))
       (set (subreg:SI (match_dup 0) 0)
--- 3096,3102 ----
  ;; 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" "") 4)
  	  (mult:SI (match_operand:SI 1 "register_operand" "")
  		   (match_operand:SI 2 "nonimmediate_operand" "")))
       (set (subreg:SI (match_dup 0) 0)
***************
*** 3135,3141 ****
  
  (define_expand "mulsidi3"
    [(parallel
!     [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
  	  (mult:SI (match_operand:SI 1 "register_operand" "")
  		   (match_operand:SI 2 "nonimmediate_operand" "")))
       (set (subreg:SI (match_dup 0) 0)
--- 3135,3141 ----
  
  (define_expand "mulsidi3"
    [(parallel
!     [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
  	  (mult:SI (match_operand:SI 1 "register_operand" "")
  		   (match_operand:SI 2 "nonimmediate_operand" "")))
       (set (subreg:SI (match_dup 0) 0)
***************
*** 4731,4737 ****
  (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))]
    ""
    "*
  {
--- 4731,4737 ----
  (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)) 4))]
    ""
    "*
  {
***************
*** 4743,4749 ****
  (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))]
    ""
    "*
  {
--- 4743,4749 ----
  (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)) 4))]
    ""
    "*
  {
***************
*** 4894,4903 ****
  ;;(define_insn ""
  ;;        [(set (cc0)
  ;;            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
! ;;                    (const_int 32)) 1))
  ;;        (set (match_operand:SI 1 "general_operand" "=dm")
  ;;            (subreg:SI (lshiftrt:DI (match_dup 0)
! ;;                    (const_int 32)) 1))]
  ;;  ""
  ;;  "*
  ;;{
--- 4894,4903 ----
  ;;(define_insn ""
  ;;        [(set (cc0)
  ;;            (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
! ;;                    (const_int 32)) 4))
  ;;        (set (match_operand:SI 1 "general_operand" "=dm")
  ;;            (subreg:SI (lshiftrt:DI (match_dup 0)
! ;;                    (const_int 32)) 4))]
  ;;  ""
  ;;  "*
  ;;{
***************
*** 4924,4930 ****
  (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))]
    ""
    "*
  {
--- 4924,4930 ----
  (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)) 4))]
    ""
    "*
  {
Index: gcc/config/m88k/m88k.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/m88k/m88k.md,v
retrieving revision 1.11
diff -c -p -r1.11 m88k.md
*** gcc/config/m88k/m88k.md	2000/11/10 16:01:22	1.11
--- gcc/config/m88k/m88k.md	2001/03/07 18:36:38
***************
*** 2295,2304 ****
  ;;- sign extension instructions
  
  (define_expand "extendsidi2"
!   [(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1)
          (match_operand:SI 1 "general_operand" "g"))
     (set (subreg:SI (match_dup 0) 0)
!         (ashiftrt:SI (subreg:SI (match_dup 0) 1)
                       (const_int 31)))]
    ""
    "")
--- 2295,2304 ----
  ;;- sign extension instructions
  
  (define_expand "extendsidi2"
!   [(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) 4)
                       (const_int 31)))]
    ""
    "")
Index: gcc/config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/mips/mips.c,v
retrieving revision 1.111
diff -c -p -r1.111 mips.c
*** gcc/config/mips/mips.c	2001/02/27 01:26:26	1.111
--- gcc/config/mips/mips.c	2001/03/07 18:36:44
*************** mips_move_1word (operands, insn, unsigne
*** 1835,1854 ****
    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;
    enum delay_type delay = DELAY_NONE;
  
    while (code0 == SUBREG)
      {
!       subreg_word0 += SUBREG_WORD (op0);
        op0 = SUBREG_REG (op0);
        code0 = GET_CODE (op0);
      }
  
    while (code1 == SUBREG)
      {
!       subreg_word1 += SUBREG_WORD (op1);
        op1 = SUBREG_REG (op1);
        code1 = GET_CODE (op1);
      }
--- 1835,1860 ----
    enum rtx_code code0 = GET_CODE (op0);
    enum rtx_code code1 = GET_CODE (op1);
    enum machine_mode mode = GET_MODE (op0);
!   int subreg_offset0 = 0;
!   int subreg_offset1 = 0;
    enum delay_type delay = DELAY_NONE;
  
    while (code0 == SUBREG)
      {
!       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_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);
      }
*************** mips_move_1word (operands, insn, unsigne
*** 1859,1869 ****
  
    if (code0 == REG)
      {
!       int regno0 = REGNO (op0) + subreg_word0;
  
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_word1;
  
  	  /* Just in case, don't do anything for assigning a register
  	     to itself, unless we are filling a delay slot.  */
--- 1865,1875 ----
  
    if (code0 == REG)
      {
!       int regno0 = REGNO (op0) + subreg_offset0;
  
        if (code1 == REG)
  	{
! 	  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.  */
*************** mips_move_1word (operands, insn, unsigne
*** 2148,2154 ****
  
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_word1;
  
  	  if (GP_REG_P (regno1))
  	    {
--- 2154,2160 ----
  
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_offset1;
  
  	  if (GP_REG_P (regno1))
  	    {
*************** mips_move_2words (operands, insn)
*** 2227,2239 ****
    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;
    enum delay_type delay = DELAY_NONE;
  
    while (code0 == SUBREG)
      {
!       subreg_word0 += SUBREG_WORD (op0);
        op0 = SUBREG_REG (op0);
        code0 = GET_CODE (op0);
      }
--- 2233,2248 ----
    rtx op1 = operands[1];
    enum rtx_code code0 = GET_CODE (operands[0]);
    enum rtx_code code1 = GET_CODE (operands[1]);
!   int subreg_offset0 = 0;
!   int subreg_offset1 = 0;
    enum delay_type delay = DELAY_NONE;
  
    while (code0 == SUBREG)
      {
!       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);
      }
*************** mips_move_2words (operands, insn)
*** 2246,2252 ****
  
    while (code1 == SUBREG)
      {
!       subreg_word1 += SUBREG_WORD (op1);
        op1 = SUBREG_REG (op1);
        code1 = GET_CODE (op1);
      }
--- 2255,2264 ----
  
    while (code1 == SUBREG)
      {
!       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);
      }
*************** mips_move_2words (operands, insn)
*** 2264,2274 ****
  
    if (code0 == REG)
      {
!       int regno0 = REGNO (op0) + subreg_word0;
  
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_word1;
  
  	  /* Just in case, don't do anything for assigning a register
  	     to itself, unless we are filling a delay slot.  */
--- 2276,2286 ----
  
    if (code0 == REG)
      {
!       int regno0 = REGNO (op0) + subreg_offset0;
  
        if (code1 == REG)
  	{
! 	  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.  */
*************** mips_move_2words (operands, insn)
*** 2605,2611 ****
      {
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_word1;
  
  	  if (FP_REG_P (regno1))
  	    ret = "s.d\t%1,%0";
--- 2617,2623 ----
      {
        if (code1 == REG)
  	{
! 	  int regno1 = REGNO (op1) + subreg_offset1;
  
  	  if (FP_REG_P (regno1))
  	    ret = "s.d\t%1,%0";
*************** mips_secondary_reload_class (class, mode
*** 7887,7893 ****
  	{
  	  while (GET_CODE (x) == SUBREG)
  	    {
! 	      off += SUBREG_WORD (x);
  	      x = SUBREG_REG (x);
  	    }
  
--- 7899,7908 ----
  	{
  	  while (GET_CODE (x) == SUBREG)
  	    {
! 	      off += subreg_regno_offset (REGNO (SUBREG_REG (x)),
! 					  GET_MODE (SUBREG_REG (x)),
! 					  SUBREG_BYTE (x),
! 					  GET_MODE (x));
  	      x = SUBREG_REG (x);
  	    }
  
Index: gcc/config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/mips/mips.md,v
retrieving revision 1.87
diff -c -p -r1.87 mips.md
*** gcc/config/mips/mips.md	2000/11/28 21:31:44	1.87
--- gcc/config/mips/mips.md	2001/03/07 18:36:46
***************
*** 790,801 ****
  	(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) 1)
! 	(plus:SI (subreg:SI (match_dup 0) 1)
  		 (match_dup 3)))]
    "")
  
--- 790,801 ----
  	(ltu:SI (subreg:SI (match_dup 0) 0)
  		(subreg:SI (match_dup 2) 0)))
  
!    (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) 4)
! 	(plus:SI (subreg:SI (match_dup 0) 4)
  		 (match_dup 3)))]
    "")
  
***************
*** 812,824 ****
     && (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 (match_dup 3)
! 	(ltu:SI (subreg:SI (match_dup 0) 1)
! 		(subreg:SI (match_dup 2) 1)))
  
     (set (subreg:SI (match_dup 0) 0)
  	(plus:SI (subreg:SI (match_dup 1) 0)
--- 812,824 ----
     && (REGNO (operands[0]) != REGNO (operands[1])
         || REGNO (operands[0]) != REGNO (operands[2]))"
  
!   [(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) 4)
! 		(subreg:SI (match_dup 2) 4)))
  
     (set (subreg:SI (match_dup 0) 0)
  	(plus:SI (subreg:SI (match_dup 1) 0)
***************
*** 865,872 ****
  	(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)
  		 (match_dup 3)))]
    "")
  
--- 865,872 ----
  	(ltu:SI (subreg:SI (match_dup 0) 0)
  		(match_dup 2)))
  
!    (set (subreg:SI (match_dup 0) 4)
! 	(plus:SI (subreg:SI (match_dup 1) 4)
  		 (match_dup 3)))]
    "")
  
***************
*** 881,892 ****
     && 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)
  		 (match_dup 2)))
  
     (set (match_dup 3)
! 	(ltu:SI (subreg:SI (match_dup 0) 1)
  		(match_dup 2)))
  
     (set (subreg:SI (match_dup 0) 0)
--- 881,892 ----
     && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
     && INTVAL (operands[2]) > 0"
  
!   [(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) 4)
  		(match_dup 2)))
  
     (set (subreg:SI (match_dup 0) 0)
***************
*** 1307,1318 ****
  	(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) 1)
! 	(minus:SI (subreg:SI (match_dup 0) 1)
  		  (match_dup 3)))]
    "")
  
--- 1307,1318 ----
  	(minus:SI (subreg:SI (match_dup 1) 0)
  		  (subreg:SI (match_dup 2) 0)))
  
!    (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) 4)
! 	(minus:SI (subreg:SI (match_dup 0) 4)
  		  (match_dup 3)))]
    "")
  
***************
*** 1328,1339 ****
     && 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)))
  
!    (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) 0)
  	(minus:SI (subreg:SI (match_dup 1) 0)
--- 1328,1339 ----
     && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
  
    [(set (match_dup 3)
! 	(ltu:SI (subreg:SI (match_dup 1) 4)
! 	        (subreg:SI (match_dup 2) 4)))
  
!    (set (subreg:SI (match_dup 0) 4)
! 	(minus:SI (subreg:SI (match_dup 1) 4)
! 		  (subreg:SI (match_dup 2) 4)))
  
     (set (subreg:SI (match_dup 0) 0)
  	(minus:SI (subreg:SI (match_dup 1) 0)
***************
*** 1378,1385 ****
  	(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)
  		  (match_dup 3)))]
    "")
  
--- 1378,1385 ----
  	(minus:SI (subreg:SI (match_dup 1) 0)
  		  (match_dup 2)))
  
!    (set (subreg:SI (match_dup 0) 4)
! 	(minus:SI (subreg:SI (match_dup 1) 4)
  		  (match_dup 3)))]
    "")
  
***************
*** 1395,1405 ****
     && INTVAL (operands[2]) > 0"
  
    [(set (match_dup 3)
! 	(ltu:SI (subreg:SI (match_dup 1) 1)
  		(match_dup 2)))
  
!    (set (subreg:SI (match_dup 0) 1)
! 	(minus:SI (subreg:SI (match_dup 1) 1)
  		  (match_dup 2)))
  
     (set (subreg:SI (match_dup 0) 0)
--- 1395,1405 ----
     && INTVAL (operands[2]) > 0"
  
    [(set (match_dup 3)
! 	(ltu:SI (subreg:SI (match_dup 1) 4)
  		(match_dup 2)))
  
!    (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)
*************** move\\t%0,%z4\\n\\
*** 3121,3127 ****
     && 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)))]
    "")
  
  
--- 3121,3127 ----
     && 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) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
    "")
  
  
*************** move\\t%0,%z4\\n\\
*** 3224,3230 ****
     && 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)))]
    "")
  
  (define_insn "anddi3_internal1"
--- 3224,3230 ----
     && 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) 4) (and:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
    "")
  
  (define_insn "anddi3_internal1"
*************** move\\t%0,%z4\\n\\
*** 3325,3331 ****
     && 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)))]
    "")
  
  (define_expand "xorsi3"
--- 3325,3331 ----
     && 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) 4) (ior:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
    "")
  
  (define_expand "xorsi3"
*************** move\\t%0,%z4\\n\\
*** 3429,3435 ****
     && 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)))]
    "")
  
  (define_insn "xordi3_immed"
--- 3429,3435 ----
     && 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) 4) (xor:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
    "")
  
  (define_insn "xordi3_immed"
*************** move\\t%0,%z4\\n\\
*** 3478,3484 ****
     && 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))))]
    "")
  
  ;;
--- 3478,3484 ----
     && 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) 4) (and:SI (not:SI (subreg:SI (match_dup 1) 4)) (not:SI (subreg:SI (match_dup 2) 4))))]
    "")
  
  ;;
*************** move\\t%0,%z4\\n\\
*** 4917,4923 ****
     && 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))]
    "")
  
  (define_insn "movdi_internal2"
--- 4917,4923 ----
     && 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) 4) (subreg:SI (match_dup 1) 4))]
    "")
  
  (define_insn "movdi_internal2"
*************** move\\t%0,%z4\\n\\
*** 6147,6153 ****
     && 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))]
    "")
  
  ;; Instructions to load the global pointer register.
--- 6147,6153 ----
     && 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) 4) (subreg:SI (match_dup 1) 4))]
    "")
  
  ;; Instructions to load the global pointer register.
*************** move\\t%0,%z4\\n\\
*** 6516,6522 ****
     && 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) 0) (const_int 0))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
--- 6516,6522 ----
     && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
     && (INTVAL (operands[2]) & 32) != 0"
  
!   [(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);")
*************** move\\t%0,%z4\\n\\
*** 6533,6540 ****
     && 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))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
  
--- 6533,6540 ----
     && 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) 4) (match_dup 2)))
!    (set (subreg:SI (match_dup 0) 4) (const_int 0))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
  
*************** move\\t%0,%z4\\n\\
*** 6574,6589 ****
     && (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)
  		   (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)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
--- 6574,6589 ----
     && (INTVAL (operands[2]) & 63) < 32
     && (INTVAL (operands[2]) & 63) != 0"
  
!   [(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) 4)
! 	(ior:SI (subreg:SI (match_dup 0) 4)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
*************** move\\t%0,%z4\\n\\
*** 6614,6628 ****
  		   (match_dup 2)))
  
     (set (match_dup 3)
! 	(lshiftrt:SI (subreg:SI (match_dup 1) 1)
  		     (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)
  		   (match_dup 2)))]
    "
  {
--- 6614,6628 ----
  		   (match_dup 2)))
  
     (set (match_dup 3)
! 	(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) 4)
! 	(ashift:SI (subreg:SI (match_dup 1) 4)
  		   (match_dup 2)))]
    "
  {
*************** move\\t%0,%z4\\n\\
*** 6871,6878 ****
     && 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)))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
  
--- 6871,6878 ----
     && 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) 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);")
  
*************** move\\t%0,%z4\\n\\
*** 6887,6893 ****
     && 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) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
--- 6887,6893 ----
     && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
     && (INTVAL (operands[2]) & 32) != 0"
  
!   [(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);")
*************** move\\t%0,%z4\\n\\
*** 6932,6946 ****
  		     (match_dup 2)))
  
     (set (match_dup 3)
! 	(ashift:SI (subreg:SI (match_dup 1) 1)
  		   (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)
  		     (match_dup 2)))]
    "
  {
--- 6932,6946 ----
  		     (match_dup 2)))
  
     (set (match_dup 3)
! 	(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) 4)
! 	(ashiftrt:SI (subreg:SI (match_dup 1) 4)
  		     (match_dup 2)))]
    "
  {
*************** move\\t%0,%z4\\n\\
*** 6962,6977 ****
     && (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)
  		     (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)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
--- 6962,6977 ----
     && (INTVAL (operands[2]) & 63) < 32
     && (INTVAL (operands[2]) & 63) != 0"
  
!   [(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) 4)
! 	(ior:SI (subreg:SI (match_dup 0) 4)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
*************** move\\t%0,%z4\\n\\
*** 7255,7262 ****
     && 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))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
  
--- 7255,7262 ----
     && 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) 4) (match_dup 2)))
!    (set (subreg:SI (match_dup 0) 4) (const_int 0))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
  
*************** move\\t%0,%z4\\n\\
*** 7272,7278 ****
     && 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) 0) (const_int 0))]
  
    "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
--- 7272,7278 ----
     && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
     && (INTVAL (operands[2]) & 32) != 0"
  
!   [(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);")
*************** move\\t%0,%z4\\n\\
*** 7317,7331 ****
  		     (match_dup 2)))
  
     (set (match_dup 3)
! 	(ashift:SI (subreg:SI (match_dup 1) 1)
  		   (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)
  		     (match_dup 2)))]
    "
  {
--- 7317,7331 ----
  		     (match_dup 2)))
  
     (set (match_dup 3)
! 	(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) 4)
! 	(lshiftrt:SI (subreg:SI (match_dup 1) 4)
  		     (match_dup 2)))]
    "
  {
*************** move\\t%0,%z4\\n\\
*** 7347,7362 ****
     && (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)
  		     (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)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
--- 7347,7362 ----
     && (INTVAL (operands[2]) & 63) < 32
     && (INTVAL (operands[2]) & 63) != 0"
  
!   [(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) 4)
! 	(ior:SI (subreg:SI (match_dup 0) 4)
  		(match_dup 3)))
  
     (set (subreg:SI (match_dup 0) 0)
Index: gcc/config/mn10200/mn10200.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/mn10200/mn10200.c,v
retrieving revision 1.15
diff -c -p -r1.15 mn10200.c
*** gcc/config/mn10200/mn10200.c	2000/01/14 23:00:20	1.15
--- gcc/config/mn10200/mn10200.c	2001/03/07 18:36:47
*************** print_operand (file, x, code)
*** 163,170 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
  	    break;
  
  	  case CONST_DOUBLE:
--- 163,169 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x)]);
  	    break;
  
  	  case CONST_DOUBLE:
*************** print_operand (file, x, code)
*** 223,230 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
  	    break;
  
  	  case CONST_DOUBLE:
--- 222,228 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
  	    break;
  
  	  case CONST_DOUBLE:
*************** print_operand (file, x, code)
*** 323,330 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
  	    break;
  
  	  case CONST_INT:
--- 321,327 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x)]);
  	    break;
  
  	  case CONST_INT:
Index: gcc/config/mn10300/mn10300.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/mn10300/mn10300.c,v
retrieving revision 1.32
diff -c -p -r1.32 mn10300.c
*** gcc/config/mn10300/mn10300.c	2000/12/06 03:56:43	1.32
--- gcc/config/mn10300/mn10300.c	2001/03/07 18:36:48
*************** print_operand (file, x, code)
*** 144,151 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
  	    break;
  
  	  case CONST_DOUBLE:
--- 144,150 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x)]);
  	    break;
  
  	  case CONST_DOUBLE:
*************** print_operand (file, x, code)
*** 205,212 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
  	    break;
  
  	  case CONST_DOUBLE:
--- 204,210 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
  	    break;
  
  	  case CONST_DOUBLE:
*************** print_operand (file, x, code)
*** 290,297 ****
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s",
! 		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
  	    break;
  
  	  /* This will only be single precision....  */
--- 288,294 ----
  	    break;
  
  	  case SUBREG:
! 	    fprintf (file, "%s", reg_names[subreg_regno (x)]);
  	    break;
  
  	  /* This will only be single precision....  */
Index: gcc/config/ns32k/ns32k.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ns32k/ns32k.md,v
retrieving revision 1.16
diff -c -p -r1.16 ns32k.md
*** gcc/config/ns32k/ns32k.md	2000/09/12 14:58:47	1.16
--- gcc/config/ns32k/ns32k.md	2001/03/07 18:36:49
***************
*** 1275,1281 ****
  ;; 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)
  	(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)
--- 1275,1281 ----
  ;; 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") 4)
  	(truncate:SI (udiv:DI (match_operand:DI 1 "nonimmediate_operand" "0")
  		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))))
     (set (subreg:SI (match_operand:DI 3 "nonimmediate_operand" "=0") 0)
***************
*** 1338,1344 ****
    "deiw %2,%0")
  
  (define_insn "udivmoddihi4"
!   [(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 1)
  	(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)
--- 1338,1344 ----
    "deiw %2,%0")
  
  (define_insn "udivmoddihi4"
!   [(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: gcc/config/pa/pa.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pa/pa.c,v
retrieving revision 1.99
diff -c -p -r1.99 pa.c
*** gcc/config/pa/pa.c	2001/03/01 16:48:44	1.99
--- gcc/config/pa/pa.c	2001/03/07 18:36:50
*************** emit_move_sequence (operands, mode, scra
*** 1201,1211 ****
  	   && GET_CODE (SUBREG_REG (operand0)) == REG
  	   && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
      {
!      /* We must not alter SUBREG_WORD (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));
        operand0 = alter_subreg (temp);
      }
  
--- 1201,1211 ----
  	   && GET_CODE (SUBREG_REG (operand0)) == REG
  	   && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
      {
!      /* 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_BYTE (operand0));
        operand0 = alter_subreg (temp);
      }
  
*************** emit_move_sequence (operands, mode, scra
*** 1218,1228 ****
  	   && GET_CODE (SUBREG_REG (operand1)) == REG
  	   && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
      {
!      /* We must not alter SUBREG_WORD (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));
        operand1 = alter_subreg (temp);
      }
  
--- 1218,1228 ----
  	   && GET_CODE (SUBREG_REG (operand1)) == REG
  	   && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
      {
!      /* 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_BYTE (operand1));
        operand1 = alter_subreg (temp);
      }
  
Index: gcc/config/pa/pa.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pa/pa.md,v
retrieving revision 1.83
diff -c -p -r1.83 pa.md
*** gcc/config/pa/pa.md	2001/02/27 23:48:38	1.83
--- gcc/config/pa/pa.md	2001/03/07 18:36:51
***************
*** 3505,3513 ****
     (set_attr "length" "4")])
  
  (define_expand "floatunssisf2"
!   [(set (subreg:SI (match_dup 2) 1)
  	(match_operand:SI 1 "register_operand" ""))
!    (set (subreg:SI (match_dup 2) 0)
  	(const_int 0))
     (set (match_operand:SF 0 "register_operand" "")
  	(float:SF (match_dup 2)))]
--- 3505,3513 ----
     (set_attr "length" "4")])
  
  (define_expand "floatunssisf2"
!   [(set (subreg:SI (match_dup 2) 4)
  	(match_operand:SI 1 "register_operand" ""))
!    (set (subreg:SI (match_dup 2) 4)
  	(const_int 0))
     (set (match_operand:SF 0 "register_operand" "")
  	(float:SF (match_dup 2)))]
***************
*** 3523,3529 ****
  }")
  
  (define_expand "floatunssidf2"
!   [(set (subreg:SI (match_dup 2) 1)
  	(match_operand:SI 1 "register_operand" ""))
     (set (subreg:SI (match_dup 2) 0)
  	(const_int 0))
--- 3523,3529 ----
  }")
  
  (define_expand "floatunssidf2"
!   [(set (subreg:SI (match_dup 2) 4)
  	(match_operand:SI 1 "register_operand" ""))
     (set (subreg:SI (match_dup 2) 0)
  	(const_int 0))
***************
*** 3891,3897 ****
  	  
  	}
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
! 			      gen_rtx_SUBREG (SImode, scratch, 1)));
        DONE;
      }
    operands[3] = gen_reg_rtx (SImode);
--- 3891,3897 ----
  	  
  	}
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
! 			      gen_rtx_SUBREG (SImode, scratch, GET_MODE_SIZE (SImode))));
        DONE;
      }
    operands[3] = gen_reg_rtx (SImode);
Index: gcc/config/pdp11/pdp11.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/pdp11/pdp11.md,v
retrieving revision 1.13
diff -c -p -r1.13 pdp11.md
*** gcc/config/pdp11/pdp11.md	2000/05/01 17:31:30	1.13
--- gcc/config/pdp11/pdp11.md	2001/03/07 18:36:52
***************
*** 766,772 ****
  (define_expand "zero_extendhisi2"
    [(set (subreg:HI 
            (match_dup 0)
!           1)
          (match_operand:HI 1 "register_operand" "r"))
     (set (subreg:HI 
            (match_operand:SI 0 "register_operand" "=r")
--- 766,772 ----
  (define_expand "zero_extendhisi2"
    [(set (subreg:HI 
            (match_dup 0)
!           2)
          (match_operand:HI 1 "register_operand" "r"))
     (set (subreg:HI 
            (match_operand:SI 0 "register_operand" "=r")
***************
*** 1782,1797 ****
    [(set_attr "length" "2")])
  
  (define_expand "modhi3"
!   [(set (subreg:HI (match_dup 1) 1)
  	(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))]
    "TARGET_45"
    "")
  
  (define_insn ""
!   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 1)
  	(mod:HI (match_operand:SI 1 "general_operand" "0")
  		(match_operand:HI 2 "general_operand" "g")))]
    "TARGET_45"
--- 1782,1797 ----
    [(set_attr "length" "2")])
  
  (define_expand "modhi3"
!   [(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) 2))]
    "TARGET_45"
    "")
  
  (define_insn ""
!   [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 4)
  	(mod:HI (match_operand:SI 1 "general_operand" "0")
  		(match_operand:HI 2 "general_operand" "g")))]
    "TARGET_45"
***************
*** 1802,1812 ****
  ;  [(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)
  ;	           (mod:HI (match_dup 1)
  ;		           (match_dup 2)))])
  ;   (set (match_operand:HI 3 "general_operand" "=r")
! ;        (subreg:HI (match_dup 1) 1))
  ;   (set (match_operand:HI 0 "general_operand" "=r")
  ;        (subreg:HI (match_dup 1) 0))]
  ;  "TARGET_45"
--- 1802,1812 ----
  ;  [(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) 2)
  ;	           (mod:HI (match_dup 1)
  ;		           (match_dup 2)))])
  ;   (set (match_operand:HI 3 "general_operand" "=r")
! ;        (subreg:HI (match_dup 1) 2))
  ;   (set (match_operand:HI 0 "general_operand" "=r")
  ;        (subreg:HI (match_dup 1) 0))]
  ;  "TARGET_45"
***************
*** 1816,1822 ****
  ;  [(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)
  ;	           (mod:HI (match_dup 1)
  ;		           (match_dup 2)))]
  ;  "TARGET_45"
--- 1816,1822 ----
  ;  [(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) 2)
  ;	           (mod:HI (match_dup 1)
  ;		           (match_dup 2)))]
  ;  "TARGET_45"
Index: gcc/config/romp/romp.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/romp/romp.c,v
retrieving revision 1.11
diff -c -p -r1.11 romp.c
*** gcc/config/romp/romp.c	2000/11/10 16:01:26	1.11
--- gcc/config/romp/romp.c	2001/03/07 18:36:53
*************** memory_offset_in_range_p (op, mode, low,
*** 270,281 ****
  
    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
        op = SUBREG_REG (op);
      }
  
--- 270,276 ----
  
    while (GET_CODE (op) == SUBREG)
      {
!       offset += SUBREG_BYTE (op);
        op = SUBREG_REG (op);
      }
  
Index: gcc/config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.c,v
retrieving revision 1.89
diff -c -p -r1.89 sh.c
*** gcc/config/sh/sh.c	2001/02/02 18:20:29	1.89
--- gcc/config/sh/sh.c	2001/03/07 18:36:59
*************** output_movedouble (insn, operands, mode)
*** 667,673 ****
        if (GET_CODE (inside) == REG)
  	ptrreg = REGNO (inside);
        else if (GET_CODE (inside) == SUBREG)
! 	ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
        else if (GET_CODE (inside) == PLUS)
  	{
  	  ptrreg = REGNO (XEXP (inside, 0));
--- 667,673 ----
        if (GET_CODE (inside) == REG)
  	ptrreg = REGNO (inside);
        else if (GET_CODE (inside) == SUBREG)
! 	ptrreg = subreg_regno (inside);
        else if (GET_CODE (inside) == PLUS)
  	{
  	  ptrreg = REGNO (XEXP (inside, 0));
*************** gen_ashift_hi (type, n, reg)
*** 1144,1156 ****
  	 gen_ashift_hi is only called in contexts where we know that the
  	 sign extension works out correctly.  */
        {
! 	int word = 0;
  	if (GET_CODE (reg) == SUBREG)
  	  {
! 	    word = SUBREG_WORD (reg);
  	    reg = SUBREG_REG (reg);
  	  }
! 	gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, word));
  	break;
        }
      case ASHIFT:
--- 1144,1156 ----
  	 gen_ashift_hi is only called in contexts where we know that the
  	 sign extension works out correctly.  */
        {
! 	int offset = 0;
  	if (GET_CODE (reg) == SUBREG)
  	  {
! 	    offset = SUBREG_BYTE (reg);
  	    reg = SUBREG_REG (reg);
  	  }
! 	gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));
  	break;
        }
      case ASHIFT:
*************** regs_used (x, is_dest)
*** 2517,2523 ****
  	  break;
  	if (REGNO (y) < 16)
  	  return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
! 		  << (REGNO (y) + SUBREG_WORD (x) + is_dest));
  	return 0;
        }
      case SET:
--- 2517,2527 ----
  	  break;
  	if (REGNO (y) < 16)
  	  return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
! 		  << (REGNO (y) +
! 		      subreg_regno_offset (REGNO (y),
! 					   GET_MODE (y),
! 					   SUBREG_BYTE (x),
! 					   GET_MODE (x)) + is_dest));
  	return 0;
        }
      case SET:
*************** machine_dependent_reorg (first)
*** 3261,3267 ****
  		      mode = HImode;
  		      while (GET_CODE (dst) == SUBREG)
  			{
! 			  offset += SUBREG_WORD (dst);
  			  dst = SUBREG_REG (dst);
  			}
  		      dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
--- 3265,3274 ----
  		      mode = HImode;
  		      while (GET_CODE (dst) == SUBREG)
  			{
! 			  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: gcc/config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.h,v
retrieving revision 1.97
diff -c -p -r1.97 sh.h
*** gcc/config/sh/sh.h	2001/02/15 17:17:09	1.97
--- gcc/config/sh/sh.h	2001/03/07 18:37:00
*************** extern int current_function_anonymous_ar
*** 1400,1406 ****
    ((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))))
  
  /* 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
--- 1400,1406 ----
    ((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_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: gcc/config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.md,v
retrieving revision 1.78
diff -c -p -r1.78 sh.md
*** gcc/config/sh/sh.md	2001/02/09 19:41:48	1.78
--- gcc/config/sh/sh.md	2001/03/07 18:37:00
***************
*** 2590,2596 ****
    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]);
    else if (GET_CODE (operands[0]) == MEM)
      regno = -1;
  
--- 2590,2596 ----
    if (GET_CODE (operands[0]) == REG)
      regno = REGNO (operands[0]);
    else if (GET_CODE (operands[0]) == SUBREG)
!     regno = subreg_regno (operands[0]);
    else if (GET_CODE (operands[0]) == MEM)
      regno = -1;
  
***************
*** 2728,2734 ****
        mem = operands[1];
        store_p = 0;
      }
!   if (GET_CODE (mem) == SUBREG && SUBREG_WORD (mem) == 0)
      mem = SUBREG_REG (mem);
    if (GET_CODE (mem) == MEM)
      {
--- 2728,2734 ----
        mem = operands[1];
        store_p = 0;
      }
!   if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
      mem = SUBREG_REG (mem);
    if (GET_CODE (mem) == MEM)
      {
***************
*** 2750,2756 ****
  	  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));
  	  if (store_p || ! refers_to_regno_p (REGNO (word0),
  					      REGNO (word0) + 1, addr, 0))
  	    {
--- 2750,2756 ----
  	  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, 4));
  	  if (store_p || ! refers_to_regno_p (REGNO (word0),
  					      REGNO (word0) + 1, addr, 0))
  	    {
***************
*** 2962,2968 ****
    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]);
    else if (GET_CODE (operands[0]) == MEM)
      regno = -1;
  
--- 2962,2968 ----
    if (GET_CODE (operands[0]) == REG)
      regno = REGNO (operands[0]);
    else if (GET_CODE (operands[0]) == SUBREG)
!     regno = subreg_regno (operands[0]);
    else if (GET_CODE (operands[0]) == MEM)
      regno = -1;
  
Index: gcc/config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sparc/sparc.c,v
retrieving revision 1.137
diff -c -p -r1.137 sparc.c
*** gcc/config/sparc/sparc.c	2001/02/18 23:39:28	1.137
--- gcc/config/sparc/sparc.c	2001/03/07 18:37:02
*************** ultra_find_type (type_mask, list, start)
*** 7479,7486 ****
  				  && 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)))))
  		      || (check_fpmode_conflict == 1
  			  && GET_CODE (slot_insn) == INSN
  			  && GET_CODE (slot_pat) == SET
--- 7479,7486 ----
  				  && GET_CODE (SET_SRC (pat)) == SUBREG
  				  && REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
  				       REGNO (SUBREG_REG (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: gcc/config/sparc/sparc.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sparc/sparc.h,v
retrieving revision 1.131
diff -c -p -r1.131 sparc.h
*** gcc/config/sparc/sparc.h	2001/01/04 18:54:14	1.131
--- gcc/config/sparc/sparc.h	2001/03/07 18:37:02
*************** while (0)
*** 1146,1170 ****
         : (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)))
  
  /* 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[];
  #define HARD_REGNO_MODE_OK(REGNO, MODE) \
    ((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0)
  
--- 1146,1179 ----
         : (GET_MODE_SIZE (MODE) + 3) / 4)				\
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_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: gcc/config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sparc/sparc.md,v
retrieving revision 1.121
diff -c -p -r1.121 sparc.md
*** gcc/config/sparc/sparc.md	2001/02/13 08:46:52	1.121
--- gcc/config/sparc/sparc.md	2001/03/07 18:37:04
***************
*** 4546,4560 ****
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_16 = GEN_INT (16);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
  			  shift_16));
    emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
    DONE;
--- 4546,4562 ----
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_16 = GEN_INT (16);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_16));
    emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
    DONE;
***************
*** 4624,4638 ****
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_48 = GEN_INT (48);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
  			  shift_48));
    emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
    DONE;
--- 4626,4642 ----
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_48 = GEN_INT (48);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_48));
    emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
    DONE;
***************
*** 4794,4800 ****
  
  (define_insn "*cmp_siqi_trunc"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
  		    (const_int 0)))]
    ""
    "andcc\\t%0, 0xff, %%g0"
--- 4798,4804 ----
  
  (define_insn "*cmp_siqi_trunc"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
  		    (const_int 0)))]
    ""
    "andcc\\t%0, 0xff, %%g0"
***************
*** 4803,4812 ****
  
  (define_insn "*cmp_siqi_trunc_set"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
  		    (const_int 0)))
     (set (match_operand:QI 0 "register_operand" "=r")
! 	(subreg:QI (match_dup 1) 0))]
    ""
    "andcc\\t%1, 0xff, %0"
    [(set_attr "type" "compare")
--- 4807,4816 ----
  
  (define_insn "*cmp_siqi_trunc_set"
    [(set (reg:CC 100)
! 	(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) 3))]
    ""
    "andcc\\t%1, 0xff, %0"
    [(set_attr "type" "compare")
***************
*** 4814,4820 ****
  
  (define_insn "*cmp_diqi_trunc"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
  		    (const_int 0)))]
    "TARGET_ARCH64"
    "andcc\\t%0, 0xff, %%g0"
--- 4818,4824 ----
  
  (define_insn "*cmp_diqi_trunc"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
  		    (const_int 0)))]
    "TARGET_ARCH64"
    "andcc\\t%0, 0xff, %%g0"
***************
*** 4823,4832 ****
  
  (define_insn "*cmp_diqi_trunc_set"
    [(set (reg:CC 100)
! 	(compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
  		    (const_int 0)))
     (set (match_operand:QI 0 "register_operand" "=r")
! 	(subreg:QI (match_dup 1) 0))]
    "TARGET_ARCH64"
    "andcc\\t%1, 0xff, %0"
    [(set_attr "type" "compare")
--- 4827,4836 ----
  
  (define_insn "*cmp_diqi_trunc_set"
    [(set (reg:CC 100)
! 	(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) 7))]
    "TARGET_ARCH64"
    "andcc\\t%1, 0xff, %0"
    [(set_attr "type" "compare")
***************
*** 4846,4860 ****
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_16 = GEN_INT (16);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
  			  shift_16));
    emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
    DONE;
--- 4850,4866 ----
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_16 = GEN_INT (16);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_16));
    emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
    DONE;
***************
*** 4876,4898 ****
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_24 = GEN_INT (24);
!   int op1_subword = 0;
!   int op0_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
    if (GET_CODE (operand0) == SUBREG)
      {
!       op0_subword = SUBREG_WORD (operand0);
        operand0 = XEXP (operand0, 0);
      }
!   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
  			  shift_24));
    if (GET_MODE (operand0) != SImode)
!     operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword);
    emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
    DONE;
  }")
--- 4882,4908 ----
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_24 = GEN_INT (24);
!   int op1_subbyte = 0;
!   int op0_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_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_subbyte),
  			  shift_24));
    if (GET_MODE (operand0) != SImode)
!     operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
    emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
    DONE;
  }")
***************
*** 4913,4927 ****
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_24 = GEN_INT (24);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
  			  shift_24));
    emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
    DONE;
--- 4923,4939 ----
  {
    rtx temp = gen_reg_rtx (SImode);
    rtx shift_24 = GEN_INT (24);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_24));
    emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
    DONE;
***************
*** 4943,4957 ****
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_56 = GEN_INT (56);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
  			  shift_56));
    emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
    DONE;
--- 4955,4971 ----
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_56 = GEN_INT (56);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_56));
    emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
    DONE;
***************
*** 4973,4987 ****
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_48 = GEN_INT (48);
!   int op1_subword = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       op1_subword = SUBREG_WORD (operand1);
        operand1 = XEXP (operand1, 0);
      }
  
!   emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
  			  shift_48));
    emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
    DONE;
--- 4987,5003 ----
  {
    rtx temp = gen_reg_rtx (DImode);
    rtx shift_48 = GEN_INT (48);
!   int op1_subbyte = 0;
  
    if (GET_CODE (operand1) == SUBREG)
      {
!       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_subbyte),
  			  shift_48));
    emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
    DONE;
***************
*** 6275,6281 ****
  	  (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))
     (clobber (match_scratch:SI 4 "=X,&h"))]
    "TARGET_V8PLUS"
    "@
--- 6291,6297 ----
  	  (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"))
! 	 4))
     (clobber (match_scratch:SI 4 "=X,&h"))]
    "TARGET_V8PLUS"
    "@
***************
*** 8346,8352 ****
  (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)
  		     (match_operand:SI 2 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && ((GET_CODE (operands[2]) == CONST_INT
--- 8362,8368 ----
  (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)) 4)
  		     (match_operand:SI 2 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && ((GET_CODE (operands[2]) == CONST_INT
***************
*** 8366,8372 ****
  (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)
  		     (match_operand:SI 2 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && ((GET_CODE (operands[2]) == CONST_INT
--- 8382,8388 ----
  (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)) 4)
  		     (match_operand:SI 2 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && ((GET_CODE (operands[2]) == CONST_INT
***************
*** 8386,8392 ****
  (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 3 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
--- 8402,8408 ----
  (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")) 4)
  		     (match_operand:SI 3 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
***************
*** 8405,8411 ****
  (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 3 "small_int_or_double" "n")))]
    "TARGET_ARCH64
     && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
--- 8421,8427 ----
  (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")) 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: gcc/config/v850/v850.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/v850/v850.c,v
retrieving revision 1.37
diff -c -p -r1.37 v850.c
*** gcc/config/v850/v850.c	2001/01/09 03:10:12	1.37
--- gcc/config/v850/v850.c	2001/03/07 18:37:04
*************** print_operand (file, x, code)
*** 542,548 ****
  	  fputs (reg_names[REGNO (x)], file);
  	  break;
  	case SUBREG:
! 	  fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
  	  break;
  	case CONST_INT:
  	case SYMBOL_REF:
--- 542,548 ----
  	  fputs (reg_names[REGNO (x)], file);
  	  break;
  	case SUBREG:
! 	  fputs (reg_names[subreg_regno (x)], file);
  	  break;
  	case CONST_INT:
  	case SYMBOL_REF:
*************** output_move_double (operands)
*** 824,830 ****
        if (GET_CODE (inside) == REG)
   	ptrreg = REGNO (inside);
        else if (GET_CODE (inside) == SUBREG)
! 	ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
        else if (GET_CODE (inside) == PLUS)
  	ptrreg = REGNO (XEXP (inside, 0));
        else if (GET_CODE (inside) == LO_SUM)
--- 824,830 ----
        if (GET_CODE (inside) == REG)
   	ptrreg = REGNO (inside);
        else if (GET_CODE (inside) == SUBREG)
! 	ptrreg = subreg_regno (inside);
        else if (GET_CODE (inside) == PLUS)
  	ptrreg = REGNO (XEXP (inside, 0));
        else if (GET_CODE (inside) == LO_SUM)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]