Use byte offsets in SUBREGs instead of words.

2001-04-03  Jakub Jelinek  <jakub@redhat.com>
	    David S. Miller  <davem@pierdol.cobaltmicro.com>
            Andrew MacLeod  <amacleod@redhat.com>

	Use byte offsets in SUBREGs instead of words.

	* alias.c (nonlocal_mentioned_p): Use subreg_regno function.
	* caller-save.c (mark_set_regs): Change callers of subreg_hard_regno
	to pass new argument.
	(add_stored_regs): Use subreg_regno_offset function.
	* calls.c (expand_call): For non-paradoxical SUBREG take endianess
	into account.
	(precompute_arguments): Use gen_lowpart_SUBREG.
	* combine.c (try_combine): Replace explicit XEXP with SUBREG_REG.
	(combine_simplify_rtx): Rework to use SUBREG_BYTE.
	(simplify_set): Rework to use SUBREG_BYTE.
	(expand_field_assignment): Use SUBREG_BYTE.
	(make_extraction): Use SUBREG_BYTE.
	(if_then_else_cond): Use SUBREG_BYTE.
	(apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments.
	(gen_lowpart_for_combine): Compute full byte offset.
	* cse.c (mention_regs): Use SUBREG_BYTE.
	(remove_invalid_subreg_refs): Rework to use SUBREG_BYTE.
	(canon_hash): Use SUBREG_BYTE.
	(fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword.
	(gen_lowpart_if_possible): Formatting.
	* dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos
	correctly.
	* dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
	(mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
	(loc_descriptor): Fixup explicit XEXP into SUBREG_REG
	* dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
	(output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
	(output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
	* emit-rtl.c (gen_rtx_SUBREG): New function, used to verify
	certain invariants about SUBREGs the compiler creates.
	(gen_lowpart_SUBREG): New function.
	(subreg_hard_regno): New function to get the final register number.
	(gen_lowpart_common): Use SUBREG_BYTE.
	(gen_imagpart): Spacing nits.
	(subreg_realpart_p): Use SUBREG_BYTE.
	(gen_highpart): Use SUBREG_BYTE.
	(subreg_lowpart_p): Always compute endian corrected goal offset,
	even at the byte level, then compare against that.
	(constant_subword): New function, pulled out all constant cases
	from operand_subword and changed second argument name to offset.
	(operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early
	and call constant_subword to do the work.  Return const0_rtx if
	looking for a word outside of OP.
	(operand_subword_force): Change second arg name to offset.
	* expmed.c (store_bit_field): Use SUBREG_BYTE.
	(store_split_bit_field): Use SUBREG_BYTE.
	(extract_bit_field): Use SUBREG_BYTE.
	(extract_split_bit_field): Use SUBREG_BYTE.
	(expand_shift): Use SUBREG_BYTE.
	* expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG.
	* final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE.
	* flow.c (set_noop_p): Use SUBREG_BYTE.
	(mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead.
	* function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG.
	(fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian
	correction code.
	(optimize_bit_field): Use SUBREG_BYTE.
	(purge_addressof_1): Use SUBREG_BYTE.
	(purge_single_hard_subreg_set): Use subreg_regno_offset function.
	(assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are
	actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true.
	* gengenrtl.c (special_rtx): Add SUBREG.
	* global.c (mark_reg_store): Use SUBREG_BYTE.
	(set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE.
	* ifcvt (noce_emit_move_insn): Use SUBREG_BYTE.
	* integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure
	final byte offset is congruent to subreg's mode size.
	(subst_constants): Use SUBREG_BYTE.
	(mark_stores): Use subreg_regno_offset function.
	* jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset
	function and SUBREG_BYTE.
	* local-alloc.c (combine_regs): Use subreg_regno_offset function.
	(reg_is_born): Use subreg_hard_regno.
	* recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte
	endian correction code.  Don't combine subregs unless resulting
	offset aligns with type.  Fix subreg constant extraction for DImode.
	Simplify SUBREG of VOIDmode CONST_DOUBLE.
	(general_operand): Remove dead mode_altering_drug code.
	(indirect_operand): Use SUBREG_BYTE.
	(constrain_operands): Use subreg_regno_offset function.
	* reg-stack.c (get_true_reg): Use subreg_regno_offset function.
	* regmove.c (regmove_optimize): Use SUBREG_BYTE.
	(optimize_reg_copy_3): Use gen_lowpart_SUBREG.
	* regs.h (REG_SIZE): Allow target to override.
	(REGMODE_NATURAL_SIZE): New macro which target can override.
	* reload.c (reload_inner_reg_of_subreg): subreg_regno should be used
	on the entire subreg rtx.
	(push_reload): Use SUBREG_BYTE in comments and code.
	(find_dummy_reload): Use subreg_regno_offset.  Only adjust offsets
	for hard registers inside subregs.
	(operands_match_p): Use subreg_regno_offset.
	(find_reloads): Use SUBREG_BYTE and only advance offset for subregs
	containing hard regs.
	(find_reload_toplev): Use SUBREG_BYTE.  Remove byte endian
	corrections when fixing up MEM subregs.
	(find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and
	subreg_regno_offset where appropriate.
	(find_reloads_subreg_address): Use SUBREG_BYTE.  Remove
	byte endian corrections when fixing up MEM subregs.
	(subst_reloads): When combining two subregs, make sure final
	offset is congruent to subreg's mode size.
	(find_replacement): Use SUBREG_BYTE and subreg_regno_offset.
	(refers_to_regno_for_reload_p): Use subreg_regno.
	(reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset.
	* reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian
	correction code for memory subreg fixups.
	(forget_old_reload_1): Use subreg_regno_offset.
	(choose_reload_regs): Use subreg_regno.
	(emit_input_reload_insns): Use SUBREG_BYTE.
	(reload_combine_note_store): Use subreg_regno_offset.
	(move2add_note_store): Use subreg_regno_offset.
	* resource.c (update_live_status, mark_referenced_resources): Use
	subreg_regno function.
	(mark_set_resources): Use subreg_regno function.
	* rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE.
	(subreg_regno_offset, subreg_regno): Define prototypes.
	(subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions.
	(gen_lowpart_SUBREG): Add prototype.
	* rtl.texi (subreg): Update to reflect new byte offset representation.
	Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now.
	* rtlanal.c (refers_to_regno_p): Use subreg_regno.
	(reg_overlap_mentioned_p): Use subreg_regno.
	(replace_regs); Make sure final offset of combined subreg is
	congruent to size of subreg's mode.
	(subreg_regno_offset): New function.
	(subreg_regno): New function.
	* sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE.
	* sdbout.c (sdbout_symbol): Compute offset using alter_subreg.
	* stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG.
	* tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead.
	(SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides.
	* config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno.
	(a29k_get_reloaded_address): Use SUBREG_BYTE.
	(print_operand): Use SUBREG_BYTE.
	* config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE.
	* config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE.
	(arm_reload_out_hi): Use SUBREG_BYTE.
	* config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset
	instead of SUBREG_WORD.
	(d30v_print_operand_memory_reference): Use subreg_regno_offset.
	* config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix
	SUBREG creation to use byte offset.
	* config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit
	inverted load insns): Fix explicit rtl subregs to use byte
	offsets.
	* config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3,
	udivsi3, umodsi3): Generate SUBREGs with byte offsets.
	* config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE.
	* config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl
	to use byte offsets.
	(unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets.
	* config/i960/i960.md (extendhisi2): Generate SUBREGs with byte
	offsets, also make sure it is congruent to SUBREG's mode size.
	(extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2,
	unnamed ldob insn): Generate SUBREGs with byte offset.
	(zero_extendqihi2): SUBREG's are byte offsets.
	* config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE.
	(m68hc11_gen_highpart): Use SUBREG_BYTE.
	* config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2,
	zero-extendqisi2): Generate SUBREGs with byte offset.
	(umulsidi3, mulsidi3, subreghi1ashrdi_const32,
	subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit
	subregs in rtl to use byte offsets.
	* config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset.
	* config/mips/mips.c (mips_move_1word): Use subreg_regno_offset.
	(mips_move_2words): Use subreg_regno_offset.
	(mips_secondary_reload_class): Use subreg_regno_offset.
	* config/mips/mips.md (DImode plus, minus, move, and logical op
	splits): Fixup explicit subregs in rtl to use byte offsets.
	* config/mn10200/mn10200.c (print_operand): Use subreg_regno function.
	* config/mn10300/mn10300.c (print_operand): Use subreg_regno function.
	* config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in
	rtl to use byte offsets.
	* config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE.
	* config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit
	subregs to use byte offsets.
	* config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1):
	Fixup explicit subregs in rtl to use byte offsets.
	* config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE
	and remove byte endian correction code.
	* config/sh/sh.c (output_movedouble): Use subreg_regno.
	(gen_ashift_hi): Use SUBREG_BYTE.
	(regs_used): Use subreg_regno_offset.
	(machine_dependent_reorg): Use subreg_regno_offset.
	* config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE.
	* config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno.
	(movdf_i4): Subregs are byte offsets now.
	* config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE.
	* config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed.
	(REGMODE_NATURAL_SIZE): Override.
	(REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode.
	* config/sparc/sparc.md (TFmode move splits): Generate SUBREGs
	with byte offsets.
	(zero_extendhisi2, zero_extendqidi2_insn, extendhisi2,
	extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn,
	extendqidi2): Generate SUBREGs with byte offsets, also make sure
	it is congruent to SUBREG's mode size.
	(smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte
	offsets.
	(cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc,
	cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2,
	lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper
	SUBREG_BYTE offset for non-paradoxical subregs in patterns.
	* config/v850/v850.c (print_operand, output_move_double): Use
	subreg_regno function.

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

From-SVN: r41058
This commit is contained in:
Jakub Jelinek 2001-04-03 17:06:12 +02:00 committed by Andrew Macleod
parent 924c96ebc4
commit ddef6bc7a3
64 changed files with 1634 additions and 867 deletions

View File

@ -1,3 +1,215 @@
2001-04-03 Jakub Jelinek <jakub@redhat.com>
David S. Miller <davem@pierdol.cobaltmicro.com>
Andrew MacLeod <amacleod@redhat.com>
Use byte offsets in SUBREGs instead of words.
* alias.c (nonlocal_mentioned_p): Use subreg_regno function.
* caller-save.c (mark_set_regs): Change callers of subreg_hard_regno
to pass new argument.
(add_stored_regs): Use subreg_regno_offset function.
* calls.c (expand_call): For non-paradoxical SUBREG take endianess
into account.
(precompute_arguments): Use gen_lowpart_SUBREG.
* combine.c (try_combine): Replace explicit XEXP with SUBREG_REG.
(combine_simplify_rtx): Rework to use SUBREG_BYTE.
(simplify_set): Rework to use SUBREG_BYTE.
(expand_field_assignment): Use SUBREG_BYTE.
(make_extraction): Use SUBREG_BYTE.
(if_then_else_cond): Use SUBREG_BYTE.
(apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments.
(gen_lowpart_for_combine): Compute full byte offset.
* cse.c (mention_regs): Use SUBREG_BYTE.
(remove_invalid_subreg_refs): Rework to use SUBREG_BYTE.
(canon_hash): Use SUBREG_BYTE.
(fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword.
(gen_lowpart_if_possible): Formatting.
* dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos
correctly.
* dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
(mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
(loc_descriptor): Fixup explicit XEXP into SUBREG_REG
* dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
(output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
(output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
* emit-rtl.c (gen_rtx_SUBREG): New function, used to verify
certain invariants about SUBREGs the compiler creates.
(gen_lowpart_SUBREG): New function.
(subreg_hard_regno): New function to get the final register number.
(gen_lowpart_common): Use SUBREG_BYTE.
(gen_imagpart): Spacing nits.
(subreg_realpart_p): Use SUBREG_BYTE.
(gen_highpart): Use SUBREG_BYTE.
(subreg_lowpart_p): Always compute endian corrected goal offset,
even at the byte level, then compare against that.
(constant_subword): New function, pulled out all constant cases
from operand_subword and changed second argument name to offset.
(operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early
and call constant_subword to do the work. Return const0_rtx if
looking for a word outside of OP.
(operand_subword_force): Change second arg name to offset.
* expmed.c (store_bit_field): Use SUBREG_BYTE.
(store_split_bit_field): Use SUBREG_BYTE.
(extract_bit_field): Use SUBREG_BYTE.
(extract_split_bit_field): Use SUBREG_BYTE.
(expand_shift): Use SUBREG_BYTE.
* expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG.
* final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE.
* flow.c (set_noop_p): Use SUBREG_BYTE.
(mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead.
* function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG.
(fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian
correction code.
(optimize_bit_field): Use SUBREG_BYTE.
(purge_addressof_1): Use SUBREG_BYTE.
(purge_single_hard_subreg_set): Use subreg_regno_offset function.
(assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are
actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true.
* gengenrtl.c (special_rtx): Add SUBREG.
* global.c (mark_reg_store): Use SUBREG_BYTE.
(set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE.
* ifcvt (noce_emit_move_insn): Use SUBREG_BYTE.
* integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure
final byte offset is congruent to subreg's mode size.
(subst_constants): Use SUBREG_BYTE.
(mark_stores): Use subreg_regno_offset function.
* jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset
function and SUBREG_BYTE.
* local-alloc.c (combine_regs): Use subreg_regno_offset function.
(reg_is_born): Use subreg_hard_regno.
* recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte
endian correction code. Don't combine subregs unless resulting
offset aligns with type. Fix subreg constant extraction for DImode.
Simplify SUBREG of VOIDmode CONST_DOUBLE.
(general_operand): Remove dead mode_altering_drug code.
(indirect_operand): Use SUBREG_BYTE.
(constrain_operands): Use subreg_regno_offset function.
* reg-stack.c (get_true_reg): Use subreg_regno_offset function.
* regmove.c (regmove_optimize): Use SUBREG_BYTE.
(optimize_reg_copy_3): Use gen_lowpart_SUBREG.
* regs.h (REG_SIZE): Allow target to override.
(REGMODE_NATURAL_SIZE): New macro which target can override.
* reload.c (reload_inner_reg_of_subreg): subreg_regno should be used
on the entire subreg rtx.
(push_reload): Use SUBREG_BYTE in comments and code.
(find_dummy_reload): Use subreg_regno_offset. Only adjust offsets
for hard registers inside subregs.
(operands_match_p): Use subreg_regno_offset.
(find_reloads): Use SUBREG_BYTE and only advance offset for subregs
containing hard regs.
(find_reload_toplev): Use SUBREG_BYTE. Remove byte endian
corrections when fixing up MEM subregs.
(find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and
subreg_regno_offset where appropriate.
(find_reloads_subreg_address): Use SUBREG_BYTE. Remove
byte endian corrections when fixing up MEM subregs.
(subst_reloads): When combining two subregs, make sure final
offset is congruent to subreg's mode size.
(find_replacement): Use SUBREG_BYTE and subreg_regno_offset.
(refers_to_regno_for_reload_p): Use subreg_regno.
(reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset.
* reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian
correction code for memory subreg fixups.
(forget_old_reload_1): Use subreg_regno_offset.
(choose_reload_regs): Use subreg_regno.
(emit_input_reload_insns): Use SUBREG_BYTE.
(reload_combine_note_store): Use subreg_regno_offset.
(move2add_note_store): Use subreg_regno_offset.
* resource.c (update_live_status, mark_referenced_resources): Use
subreg_regno function.
(mark_set_resources): Use subreg_regno function.
* rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE.
(subreg_regno_offset, subreg_regno): Define prototypes.
(subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions.
(gen_lowpart_SUBREG): Add prototype.
* rtl.texi (subreg): Update to reflect new byte offset representation.
Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now.
* rtlanal.c (refers_to_regno_p): Use subreg_regno.
(reg_overlap_mentioned_p): Use subreg_regno.
(replace_regs); Make sure final offset of combined subreg is
congruent to size of subreg's mode.
(subreg_regno_offset): New function.
(subreg_regno): New function.
* sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE.
* sdbout.c (sdbout_symbol): Compute offset using alter_subreg.
* stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG.
* tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead.
(SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides.
* config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno.
(a29k_get_reloaded_address): Use SUBREG_BYTE.
(print_operand): Use SUBREG_BYTE.
* config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE.
* config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE.
(arm_reload_out_hi): Use SUBREG_BYTE.
* config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset
instead of SUBREG_WORD.
(d30v_print_operand_memory_reference): Use subreg_regno_offset.
* config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix
SUBREG creation to use byte offset.
* config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit
inverted load insns): Fix explicit rtl subregs to use byte
offsets.
* config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3,
udivsi3, umodsi3): Generate SUBREGs with byte offsets.
* config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE.
* config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl
to use byte offsets.
(unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets.
* config/i960/i960.md (extendhisi2): Generate SUBREGs with byte
offsets, also make sure it is congruent to SUBREG's mode size.
(extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2,
unnamed ldob insn): Generate SUBREGs with byte offset.
(zero_extendqihi2): SUBREG's are byte offsets.
* config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE.
(m68hc11_gen_highpart): Use SUBREG_BYTE.
* config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2,
zero-extendqisi2): Generate SUBREGs with byte offset.
(umulsidi3, mulsidi3, subreghi1ashrdi_const32,
subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit
subregs in rtl to use byte offsets.
* config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset.
* config/mips/mips.c (mips_move_1word): Use subreg_regno_offset.
(mips_move_2words): Use subreg_regno_offset.
(mips_secondary_reload_class): Use subreg_regno_offset.
* config/mips/mips.md (DImode plus, minus, move, and logical op
splits): Fixup explicit subregs in rtl to use byte offsets.
* config/mn10200/mn10200.c (print_operand): Use subreg_regno function.
* config/mn10300/mn10300.c (print_operand): Use subreg_regno function.
* config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in
rtl to use byte offsets.
* config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE.
* config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit
subregs to use byte offsets.
* config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1):
Fixup explicit subregs in rtl to use byte offsets.
* config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE
and remove byte endian correction code.
* config/sh/sh.c (output_movedouble): Use subreg_regno.
(gen_ashift_hi): Use SUBREG_BYTE.
(regs_used): Use subreg_regno_offset.
(machine_dependent_reorg): Use subreg_regno_offset.
* config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE.
* config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno.
(movdf_i4): Subregs are byte offsets now.
* config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE.
* config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed.
(REGMODE_NATURAL_SIZE): Override.
(REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode.
* config/sparc/sparc.md (TFmode move splits): Generate SUBREGs
with byte offsets.
(zero_extendhisi2, zero_extendqidi2_insn, extendhisi2,
extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn,
extendqidi2): Generate SUBREGs with byte offsets, also make sure
it is congruent to SUBREG's mode size.
(smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte
offsets.
(cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc,
cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2,
lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper
SUBREG_BYTE offset for non-paradoxical subregs in patterns.
* config/v850/v850.c (print_operand, output_move_double): Use
subreg_regno function.
2001-04-03 Alexandre Oliva <aoliva@redhat.com>
* configure.in (target_subdir): Use target_alias, not target.

View File

@ -1880,7 +1880,7 @@ nonlocal_mentioned_p (x)
{
/* Global registers are not local. */
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
&& global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)])
&& global_regs[subreg_regno (x)])
return 1;
return 0;
}

View File

@ -487,18 +487,21 @@ mark_set_regs (reg, setter, data)
{
register int regno, endregno, i;
enum machine_mode mode = GET_MODE (reg);
int word = 0;
if (GET_CODE (reg) == SUBREG)
{
word = SUBREG_WORD (reg);
reg = SUBREG_REG (reg);
}
rtx inner = SUBREG_REG (reg);
if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
return;
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
regno = subreg_hard_regno (reg, 1);
}
else if (GET_CODE (reg) == REG
&& REGNO (reg) < FIRST_PSEUDO_REGISTER)
regno = REGNO (reg);
else
return;
regno = REGNO (reg) + word;
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)
@ -517,21 +520,24 @@ add_stored_regs (reg, setter, data)
{
register int regno, endregno, i;
enum machine_mode mode = GET_MODE (reg);
int word = 0;
int offset = 0;
if (GET_CODE (setter) == CLOBBER)
return;
while (GET_CODE (reg) == SUBREG)
if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
{
word += SUBREG_WORD (reg);
offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
GET_MODE (SUBREG_REG (reg)),
SUBREG_BYTE (reg),
GET_MODE (reg));
reg = SUBREG_REG (reg);
}
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
return;
regno = REGNO (reg) + word;
regno = REGNO (reg) + offset;
endregno = regno + HARD_REGNO_NREGS (regno, mode);
for (i = regno; i < endregno; i++)

View File

@ -1462,6 +1462,8 @@ precompute_arguments (flags, num_actuals, args)
if ((flags & (ECF_CONST | ECF_PURE))
|| calls_function (args[i].tree_value, !ACCUMULATE_OUTGOING_ARGS))
{
enum machine_mode mode;
/* If this is an addressable type, we cannot pre-evaluate it. */
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
abort ();
@ -1481,11 +1483,11 @@ precompute_arguments (flags, num_actuals, args)
args[i].initial_value = args[i].value
= protect_from_queue (args[i].value, 0);
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
if (mode != args[i].mode)
{
args[i].value
= convert_modes (args[i].mode,
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
= convert_modes (args[i].mode, mode,
args[i].value, args[i].unsignedp);
#ifdef PROMOTE_FOR_CALL_ONLY
/* CSE will replace this only if it contains args[i].value
@ -1495,8 +1497,7 @@ precompute_arguments (flags, num_actuals, args)
&& GET_MODE_CLASS (args[i].mode) == MODE_INT)
{
args[i].initial_value
= gen_rtx_SUBREG (TYPE_MODE (TREE_TYPE (args[i].tree_value)),
args[i].value, 0);
= gen_lowpart_SUBREG (mode, args[i].value);
SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
= args[i].unsignedp;
@ -3272,13 +3273,25 @@ expand_call (exp, target, ignore)
{
tree type = TREE_TYPE (exp);
int unsignedp = TREE_UNSIGNED (type);
int offset = 0;
/* If we don't promote as expected, something is wrong. */
if (GET_MODE (target)
!= promote_mode (type, TYPE_MODE (type), &unsignedp, 1))
abort ();
target = gen_rtx_SUBREG (TYPE_MODE (type), target, 0);
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
&& GET_MODE_SIZE (GET_MODE (target))
> GET_MODE_SIZE (TYPE_MODE (type)))
{
offset = GET_MODE_SIZE (GET_MODE (target))
- GET_MODE_SIZE (TYPE_MODE (type));
if (! BYTES_BIG_ENDIAN)
offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
else if (! WORDS_BIG_ENDIAN)
offset %= UNITS_PER_WORD;
}
target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
SUBREG_PROMOTED_VAR_P (target) = 1;
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
}

View File

@ -2249,7 +2249,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
be written as a ZERO_EXTEND. */
if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
XEXP (*split, 0)));
SUBREG_REG (*split)));
#endif
newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
@ -3773,27 +3773,17 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
rtx inner = SUBREG_REG (x);
int endian_offset = 0;
int offset = SUBREG_BYTE (x);
/* Don't change the mode of the MEM
if that would change the meaning of the address. */
if (MEM_VOLATILE_P (SUBREG_REG (x))
|| mode_dependent_address_p (XEXP (inner, 0)))
return gen_rtx_CLOBBER (mode, const0_rtx);
if (BYTES_BIG_ENDIAN)
{
if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (mode);
if (GET_MODE_SIZE (GET_MODE (inner)) < UNITS_PER_WORD)
endian_offset -= (UNITS_PER_WORD
- GET_MODE_SIZE (GET_MODE (inner)));
}
/* Note if the plus_constant doesn't make a valid address
then this combination won't be accepted. */
x = gen_rtx_MEM (mode,
plus_constant (XEXP (inner, 0),
(SUBREG_WORD (x) * UNITS_PER_WORD
+ endian_offset)));
plus_constant (XEXP (inner, 0), offset));
MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
@ -3806,12 +3796,58 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
or not at all if changing back to starting mode. */
if (GET_CODE (SUBREG_REG (x)) == SUBREG)
{
if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x)))
&& SUBREG_WORD (x) == 0 && SUBREG_WORD (SUBREG_REG (x)) == 0)
return SUBREG_REG (SUBREG_REG (x));
int final_offset;
enum machine_mode outer_mode, inner_mode;
SUBST_INT (SUBREG_WORD (x),
SUBREG_WORD (x) + SUBREG_WORD (SUBREG_REG (x)));
/* 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)));
}
@ -3831,10 +3867,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
#endif
&& REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM)
{
if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x),
mode))
return gen_rtx_REG (mode,
REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
int final_regno = subreg_hard_regno (x, 0);
if (HARD_REGNO_MODE_OK (final_regno, mode))
return gen_rtx_REG (mode, final_regno);
else
return gen_rtx_CLOBBER (mode, const0_rtx);
}
@ -3849,7 +3885,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
&& GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_INT)
{
temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x),
temp = operand_subword (SUBREG_REG (x),
(SUBREG_BYTE (x) / UNITS_PER_WORD),
0, op0_mode);
if (temp)
return temp;
@ -3863,11 +3900,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
if (CONSTANT_P (SUBREG_REG (x))
&& ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
|| ! WORDS_BIG_ENDIAN)
? SUBREG_WORD (x) == 0
: (SUBREG_WORD (x)
== ((GET_MODE_SIZE (op0_mode)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD)))
? SUBREG_BYTE (x) == 0
: (SUBREG_BYTE (x)
== (GET_MODE_SIZE (op0_mode) - GET_MODE_SIZE (mode))))
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
&& (! WORDS_BIG_ENDIAN
|| GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
@ -3879,8 +3914,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
&& GET_MODE_SIZE (mode) > GET_MODE_SIZE (op0_mode))
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
&& (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
return operand_subword (SUBREG_REG (x), SUBREG_WORD (x), 0, mode);
&& (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) != 0))
return constant_subword (SUBREG_REG (x),
SUBREG_BYTE (x) / UNITS_PER_WORD, mode);
return SUBREG_REG (x);
}
@ -5157,14 +5193,14 @@ simplify_set (x)
if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL
&& SUBREG_WORD (src) == 0
&& SUBREG_BYTE (src) == 0
&& (GET_MODE_SIZE (GET_MODE (src))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
&& GET_CODE (SUBREG_REG (src)) == MEM)
{
SUBST (SET_SRC (x),
gen_rtx (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
GET_MODE (src), XEXP (src, 0)));
GET_MODE (src), SUBREG_REG (src)));
src = SET_SRC (x);
}
@ -5756,9 +5792,11 @@ expand_field_assignment (x)
if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
&& GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
{
int byte_offset = SUBREG_BYTE (XEXP (SET_DEST (x), 0));
inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)));
pos = GEN_INT (BITS_PER_WORD * SUBREG_WORD (XEXP (SET_DEST (x), 0)));
pos = GEN_INT (BITS_PER_WORD * (byte_offset / UNITS_PER_WORD));
}
else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
&& GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
@ -5996,18 +6034,26 @@ make_extraction (mode, inner, pos, pos_rtx, len,
/* We can't call gen_lowpart_for_combine here since we always want
a SUBREG and it would sometimes return a new hard register. */
if (tmode != inner_mode)
new = gen_rtx_SUBREG (tmode, inner,
(WORDS_BIG_ENDIAN
&& (GET_MODE_SIZE (inner_mode)
> UNITS_PER_WORD)
? (((GET_MODE_SIZE (inner_mode)
- GET_MODE_SIZE (tmode))
/ UNITS_PER_WORD)
- pos / BITS_PER_WORD)
: pos / BITS_PER_WORD));
else
new = inner;
}
{
int final_word = pos / BITS_PER_WORD;
if (WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
final_word = ((GET_MODE_SIZE (inner_mode)
- GET_MODE_SIZE (tmode))
/ UNITS_PER_WORD) - final_word;
final_word *= UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN &&
GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (tmode))
final_word += (GET_MODE_SIZE (inner_mode)
- GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
new = gen_rtx_SUBREG (tmode, inner, final_word);
}
else
new = inner;
}
else
new = force_to_mode (inner, tmode,
len >= HOST_BITS_PER_WIDE_INT
@ -7395,11 +7441,11 @@ if_then_else_cond (x, ptrue, pfalse)
|| GET_CODE (SUBREG_REG (x)) == MEM
|| CONSTANT_P (SUBREG_REG (x)))
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
&& (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
&& (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) >= UNITS_PER_WORD))
{
true0 = operand_subword (true0, SUBREG_WORD (x), 0,
true0 = operand_subword (true0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
false0 = operand_subword (false0, SUBREG_WORD (x), 0,
false0 = operand_subword (false0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
}
*ptrue = force_to_mode (true0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
@ -7772,7 +7818,7 @@ apply_distributive_law (x)
case SUBREG:
/* Non-paradoxical SUBREGs distributes over all operations, provided
the inner modes and word numbers are the same, this is an extraction
the inner modes and byte offsets are the same, this is an extraction
of a low-order part, we don't convert an fp operation to int or
vice versa, and we would not be converting a single-word
operation into a multi-word operation. The latter test is not
@ -7783,7 +7829,7 @@ apply_distributive_law (x)
We produce the result slightly differently in this case. */
if (GET_MODE (SUBREG_REG (lhs)) != GET_MODE (SUBREG_REG (rhs))
|| SUBREG_WORD (lhs) != SUBREG_WORD (rhs)
|| SUBREG_BYTE (lhs) != SUBREG_BYTE (rhs)
|| ! subreg_lowpart_p (lhs)
|| (GET_MODE_CLASS (GET_MODE (lhs))
!= GET_MODE_CLASS (GET_MODE (SUBREG_REG (lhs))))
@ -9853,13 +9899,19 @@ gen_lowpart_for_combine (mode, x)
include an explicit SUBREG or we may simplify it further in combine. */
else
{
int word = 0;
int offset = 0;
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
word = ((GET_MODE_SIZE (GET_MODE (x))
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD);
return gen_rtx_SUBREG (mode, x, word);
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
&& GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode))
{
int difference = (GET_MODE_SIZE (GET_MODE (x))
- GET_MODE_SIZE (mode));
if (WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
return gen_rtx_SUBREG (mode, x, offset);
}
}
@ -11927,6 +11979,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
that accesses one word of a multi-word item, some
piece of everything register in the expression is used by
this insn, so remove any old death. */
/* ??? So why do we test for equality of the sizes? */
if (GET_CODE (dest) == ZERO_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART

View File

@ -262,9 +262,10 @@ gpc_reg_operand (op, mode)
regno = REGNO (op);
else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
{
regno = REGNO (SUBREG_REG (op));
if (regno < FIRST_PSEUDO_REGISTER)
regno += SUBREG_WORD (op);
if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
regno = subreg_regno (op);
else
regno = REGNO (SUBREG_REG (op));
}
else
return 0;
@ -467,7 +468,7 @@ a29k_get_reloaded_address (op)
{
if (GET_CODE (op) == SUBREG)
{
if (SUBREG_WORD (op) != 0)
if (SUBREG_BYTE (op) != 0)
abort ();
op = SUBREG_REG (op);
@ -1187,7 +1188,8 @@ print_operand (file, x, code)
if (GET_MODE (SUBREG_REG (XEXP (x, 0))) == SFmode)
fprintf (file, "$float");
else
fprintf (file, "$double%d", SUBREG_WORD (XEXP (x, 0)));
fprintf (file, "$double%d",
(SUBREG_BYTE (XEXP (x, 0)) / GET_MODE_SIZE (GET_MODE (x))));
memcpy ((char *) &u,
(char *) &CONST_DOUBLE_LOW (SUBREG_REG (XEXP (x, 0))), sizeof u);
fprintf (file, "(%.20e)", u.d);

View File

@ -4098,7 +4098,8 @@ print_operand_address (file, addr)
basereg = REGNO (addr);
else if (GET_CODE (addr) == SUBREG
&& GET_CODE (SUBREG_REG (addr)) == REG)
basereg = REGNO (SUBREG_REG (addr)) + SUBREG_WORD (addr);
basereg = REGNO (SUBREG_REG (addr))
+ SUBREG_BYTE (addr) / GET_MODE_SIZE (GET_MODE (addr));
else if (GET_CODE (addr) == CONST_INT)
offset = INTVAL (addr);
else

View File

@ -4748,11 +4748,7 @@ arm_reload_in_hi (operands)
if (GET_CODE (ref) == SUBREG)
{
offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
}
@ -4865,11 +4861,7 @@ arm_reload_out_hi (operands)
if (GET_CODE (ref) == SUBREG)
{
offset = SUBREG_WORD (ref) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref)))
- MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref)))));
offset = SUBREG_BYTE (ref);
ref = SUBREG_REG (ref);
}

View File

@ -2667,10 +2667,13 @@ d30v_split_double (value, p_high, p_low)
switch (GET_CODE (value))
{
case SUBREG:
offset = SUBREG_WORD (value);
value = SUBREG_REG (value);
if (GET_CODE (value) != REG)
if (GET_CODE (SUBREG_REG (value)) != REG)
abort ();
offset = subreg_regno_offset (REGNO (SUBREG_REG (value)),
GET_MODE (SUBREG_REG (value)),
SUBREG_BYTE (value),
GET_MODE (value));
value = SUBREG_REG (value);
/* fall through */
@ -2795,7 +2798,10 @@ d30v_print_operand_memory_reference (stream, x)
if (GET_CODE (x0) == SUBREG)
{
offset0 = SUBREG_WORD (x0);
offset0 = subreg_regno_offset (REGNO (SUBREG_REG (x0)),
GET_MODE (SUBREG_REG (x0)),
SUBREG_BYTE (x0),
GET_MODE (x0));
x0 = SUBREG_REG (x0);
}
@ -2828,7 +2834,10 @@ d30v_print_operand_memory_reference (stream, x)
switch (GET_CODE (x1))
{
case SUBREG:
offset1 = SUBREG_WORD (x1);
offset1 = subreg_regno_offset (REGNO (SUBREG_REG (x1)),
GET_MODE (SUBREG_REG (x1)),
SUBREG_BYTE (x1),
GET_MODE (x1));
x1 = SUBREG_REG (x1);
if (GET_CODE (x1) != REG)
fatal_insn ("Bad insn to d30v_print_operand_memory_reference:", x);

View File

@ -1258,7 +1258,7 @@
"
{
operands[2] = gen_reg_rtx (HImode);
operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
}")
;;(define_insn "extendqihi2"
@ -1308,7 +1308,7 @@
"
{
operands[2] = gen_reg_rtx (HImode);
operands[3] = gen_rtx_SUBREG (QImode, operands[2], 1);
operands[3] = gen_rtx_SUBREG (QImode, operands[2], GET_MODE_SIZE (QImode));
}")

View File

@ -1925,7 +1925,7 @@
(subreg:HI (zero_extract:SI
(match_operand:HI 1 "register_operand" "r")
(const_int 1)
(match_operand:HI 2 "immediate_operand" "n")) 1))]
(match_operand:HI 2 "immediate_operand" "n")) 2))]
""
"sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0"
[(set_attr "cc" "clobber")
@ -1966,7 +1966,7 @@
(subreg:HI
(lshiftrt:SI
(match_operand:SI 1 "register_operand" "Ur")
(match_operand:SI 2 "const_int_operand" "n")) 1))
(match_operand:SI 2 "const_int_operand" "n")) 2))
(const_int 1)))]
"INTVAL (operands[2]) < 16"
"sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"

View File

@ -537,12 +537,12 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
force_operand (XEXP (mem2, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), len);
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);
/* Compare! */
emit_insn (gen_cmpstrsi_1 (result, reg1, reg2));
@ -1409,11 +1409,11 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), zippo);
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), zippo);
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), zippo);
/* Copy! */
emit_insn (gen_movstrsi_1 (reg1, reg2));
@ -1476,12 +1476,12 @@ check_label_emit ();
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 1), len);
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
force_operand (XEXP (mem2, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 1), len);
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);
/* Copy! */
emit_insn (gen_movstrsi_1 (reg1, reg2));
@ -2425,11 +2425,12 @@ check_label_emit ();
* Dunno how to untwist it elegantly; but it seems to work for now.
*/
emit_insn (gen_rtx_SET (VOIDmode,
gen_rtx_SUBREG (SImode, r, 1), operands[1]));
gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)),
operands[1]));
emit_insn (gen_rtx_SET (VOIDmode, r,
gen_rtx_MULT (DImode, r, operands[2])));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_SUBREG (SImode, r, 1)));
gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode))));
}
DONE;
}")
@ -2534,7 +2535,7 @@ check_label_emit ();
emit_insn (gen_rtx_SET (VOIDmode, r,
gen_rtx_DIV (DImode, r, operands[2])));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_SUBREG (SImode, r, 1)));
gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode))));
DONE;
}")
@ -2552,7 +2553,7 @@ check_label_emit ();
{
rtx dr = gen_reg_rtx (DImode);
rtx dr_0 = gen_rtx_SUBREG (SImode, dr, 0);
rtx dr_1 = gen_rtx_SUBREG (SImode, dr, 1);
rtx dr_1 = gen_rtx_SUBREG (SImode, dr, GET_MODE_SIZE (SImode));
if (GET_CODE (operands[2]) == CONST_INT)

View File

@ -340,7 +340,7 @@ single_insn_src_p (op, mode)
return 1;
case SUBREG:
if (SUBREG_WORD (op) != 0)
if (SUBREG_BYTE (op) != 0)
return 0;
return single_insn_src_p (SUBREG_REG (op), mode);

View File

@ -1730,12 +1730,12 @@
}")
(define_expand "mulsi3_big"
[(set (subreg:SI (match_dup 4) 1) (match_operand:SI 1 "general_operand" ""))
(set (subreg:SI (match_dup 5) 1) (match_operand:SI 2 "general_operand" ""))
[(set (subreg:SI (match_dup 4) 4) (match_operand:SI 1 "general_operand" ""))
(set (subreg:SI (match_dup 5) 4) (match_operand:SI 2 "general_operand" ""))
(clobber (match_dup 3))
(set (subreg:SI (match_dup 3) 1)
(mult:SI (subreg:SI (match_dup 4) 1) (subreg:SI (match_dup 5) 1)))
(set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 1))]
(set (subreg:SI (match_dup 3) 4)
(mult:SI (subreg:SI (match_dup 4) 4) (subreg:SI (match_dup 5) 4)))
(set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 4))]
"WORDS_BIG_ENDIAN"
"
{
@ -1752,9 +1752,9 @@
"fmlow.dd %2,%1,%0")
(define_insn ""
[(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 1)
(mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 1)
(subreg:SI (match_operand:DI 2 "register_operand" "f") 1)))]
[(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 4)
(mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 4)
(subreg:SI (match_operand:DI 2 "register_operand" "f") 4)))]
"WORDS_BIG_ENDIAN"
"fmlow.dd %2,%1,%0")

View File

@ -1211,15 +1211,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
int op1_subreg_word = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
op1_subreg_byte /= GET_MODE_SIZE (SImode);
op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
@ -1246,15 +1248,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op1_subreg_word = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
op1_subreg_byte /= GET_MODE_SIZE (SImode);
op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
@ -1282,24 +1286,28 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op0_subreg_word = 0;
int op1_subreg_word = 0;
int op0_subreg_byte = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
op1_subreg_byte /= GET_MODE_SIZE (SImode);
op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
if (GET_CODE (operand0) == SUBREG)
{
op0_subreg_word = SUBREG_WORD (operand0);
op0_subreg_byte = SUBREG_BYTE (operand0);
op0_subreg_byte /= GET_MODE_SIZE (SImode);
op0_subreg_byte *= GET_MODE_SIZE (SImode);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
@ -1327,15 +1335,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
int op1_subreg_word = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
op1_subreg_byte /= GET_MODE_SIZE (SImode);
op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
@ -1367,15 +1377,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op1_subreg_word = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
op1_subreg_byte /= GET_MODE_SIZE (SImode);
op1_subreg_byte *= GET_MODE_SIZE (SImode);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
@ -1403,24 +1415,24 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op0_subreg_word = 0;
int op1_subreg_word = 0;
int op0_subreg_byte = 0;
int op1_subreg_byte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
op1_subreg_byte = SUBREG_BYTE (operand1);
operand1 = SUBREG_REG (operand1);
}
if (GET_MODE (operand1) != SImode)
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_byte);
if (GET_CODE (operand0) == SUBREG)
{
op0_subreg_word = SUBREG_WORD (operand0);
op0_subreg_byte = SUBREG_BYTE (operand0);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_word);
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subreg_byte);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));

View File

@ -1739,12 +1739,12 @@ m68hc11_gen_lowpart (mode, x)
return gen_rtx (REG, mode, HARD_B_REGNUM);
/* gen_lowpart crashes when it is called with a SUBREG. */
if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
{
if (mode == SImode)
return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 2);
return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
else if (mode == HImode)
return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + 1);
return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 1);
else
abort ();
}
@ -1844,7 +1844,7 @@ m68hc11_gen_highpart (mode, x)
}
/* gen_highpart crashes when it is called with a SUBREG. */
if (GET_CODE (x) == SUBREG && SUBREG_WORD (x) != 0)
if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
{
return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));
}

View File

@ -1554,7 +1554,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (HImode, SUBREG_REG (operands[0]),
SUBREG_WORD (operands[0]));
SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (HImode, operands[0], 0);
}")
@ -1570,7 +1570,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
SUBREG_WORD (operands[0]));
SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
}")
@ -1586,7 +1586,7 @@
operands[1] = make_safe_from (operands[1], operands[0]);
if (GET_CODE (operands[0]) == SUBREG)
operands[2] = gen_rtx_SUBREG (QImode, SUBREG_REG (operands[0]),
SUBREG_WORD (operands[0]));
SUBREG_BYTE (operands[0]));
else
operands[2] = gen_rtx_SUBREG (QImode, operands[0], 0);
}")
@ -3096,7 +3096,7 @@
;; the high-numbered word of the DImode operand[0] and operand[1].
(define_expand "umulsidi3"
[(parallel
[(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
[(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
(mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (subreg:SI (match_dup 0) 0)
@ -3135,7 +3135,7 @@
(define_expand "mulsidi3"
[(parallel
[(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
[(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
(mult:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonimmediate_operand" "")))
(set (subreg:SI (match_dup 0) 0)
@ -4731,7 +4731,7 @@
(define_insn "subreghi1ashrdi_const32"
[(set (match_operand:HI 0 "general_operand" "=rm")
(subreg:HI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
(const_int 32)) 4))]
""
"*
{
@ -4743,7 +4743,7 @@
(define_insn "subregsi1ashrdi_const32"
[(set (match_operand:SI 0 "general_operand" "=rm")
(subreg:SI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
(const_int 32)) 4))]
""
"*
{
@ -4894,10 +4894,10 @@
;;(define_insn ""
;; [(set (cc0)
;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro")
;; (const_int 32)) 1))
;; (const_int 32)) 4))
;; (set (match_operand:SI 1 "general_operand" "=dm")
;; (subreg:SI (lshiftrt:DI (match_dup 0)
;; (const_int 32)) 1))]
;; (const_int 32)) 4))]
;; ""
;; "*
;;{
@ -4924,7 +4924,7 @@
(define_insn "subreg1lshrdi_const32"
[(set (match_operand:SI 0 "general_operand" "=rm")
(subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 1))]
(const_int 32)) 4))]
""
"*
{

View File

@ -2295,10 +2295,10 @@
;;- sign extension instructions
(define_expand "extendsidi2"
[(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 1)
[(set (subreg:SI (match_operand:DI 0 "register_operand" "=r") 4)
(match_operand:SI 1 "general_operand" "g"))
(set (subreg:SI (match_dup 0) 0)
(ashiftrt:SI (subreg:SI (match_dup 0) 1)
(ashiftrt:SI (subreg:SI (match_dup 0) 4)
(const_int 31)))]
""
"")

View File

@ -1833,20 +1833,26 @@ mips_move_1word (operands, insn, unsignedp)
enum rtx_code code0 = GET_CODE (op0);
enum rtx_code code1 = GET_CODE (op1);
enum machine_mode mode = GET_MODE (op0);
int subreg_word0 = 0;
int subreg_word1 = 0;
int subreg_offset0 = 0;
int subreg_offset1 = 0;
enum delay_type delay = DELAY_NONE;
while (code0 == SUBREG)
{
subreg_word0 += SUBREG_WORD (op0);
subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
GET_MODE (SUBREG_REG (op0)),
SUBREG_BYTE (op0),
GET_MODE (op0));
op0 = SUBREG_REG (op0);
code0 = GET_CODE (op0);
}
while (code1 == SUBREG)
{
subreg_word1 += SUBREG_WORD (op1);
subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
GET_MODE (SUBREG_REG (op1)),
SUBREG_BYTE (op1),
GET_MODE (op1));
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
}
@ -1857,11 +1863,11 @@ mips_move_1word (operands, insn, unsignedp)
if (code0 == REG)
{
int regno0 = REGNO (op0) + subreg_word0;
int regno0 = REGNO (op0) + subreg_offset0;
if (code1 == REG)
{
int regno1 = REGNO (op1) + subreg_word1;
int regno1 = REGNO (op1) + subreg_offset1;
/* Just in case, don't do anything for assigning a register
to itself, unless we are filling a delay slot. */
@ -2146,7 +2152,7 @@ mips_move_1word (operands, insn, unsignedp)
if (code1 == REG)
{
int regno1 = REGNO (op1) + subreg_word1;
int regno1 = REGNO (op1) + subreg_offset1;
if (GP_REG_P (regno1))
{
@ -2225,13 +2231,16 @@ mips_move_2words (operands, insn)
rtx op1 = operands[1];
enum rtx_code code0 = GET_CODE (operands[0]);
enum rtx_code code1 = GET_CODE (operands[1]);
int subreg_word0 = 0;
int subreg_word1 = 0;
int subreg_offset0 = 0;
int subreg_offset1 = 0;
enum delay_type delay = DELAY_NONE;
while (code0 == SUBREG)
{
subreg_word0 += SUBREG_WORD (op0);
subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
GET_MODE (SUBREG_REG (op0)),
SUBREG_BYTE (op0),
GET_MODE (op0));
op0 = SUBREG_REG (op0);
code0 = GET_CODE (op0);
}
@ -2244,7 +2253,10 @@ mips_move_2words (operands, insn)
while (code1 == SUBREG)
{
subreg_word1 += SUBREG_WORD (op1);
subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
GET_MODE (SUBREG_REG (op1)),
SUBREG_BYTE (op1),
GET_MODE (op1));
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
}
@ -2262,11 +2274,11 @@ mips_move_2words (operands, insn)
if (code0 == REG)
{
int regno0 = REGNO (op0) + subreg_word0;
int regno0 = REGNO (op0) + subreg_offset0;
if (code1 == REG)
{
int regno1 = REGNO (op1) + subreg_word1;
int regno1 = REGNO (op1) + subreg_offset1;
/* Just in case, don't do anything for assigning a register
to itself, unless we are filling a delay slot. */
@ -2603,7 +2615,7 @@ mips_move_2words (operands, insn)
{
if (code1 == REG)
{
int regno1 = REGNO (op1) + subreg_word1;
int regno1 = REGNO (op1) + subreg_offset1;
if (FP_REG_P (regno1))
ret = "s.d\t%1,%0";
@ -7888,7 +7900,10 @@ mips_secondary_reload_class (class, mode, x, in_p)
{
while (GET_CODE (x) == SUBREG)
{
off += SUBREG_WORD (x);
off += subreg_regno_offset (REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x));
x = SUBREG_REG (x);
}

View File

@ -790,12 +790,12 @@
(ltu:SI (subreg:SI (match_dup 0) 0)
(subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1)
(plus:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
(set (subreg:SI (match_dup 0) 4)
(plus:SI (subreg:SI (match_dup 1) 4)
(subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 1)
(plus:SI (subreg:SI (match_dup 0) 1)
(set (subreg:SI (match_dup 0) 4)
(plus:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))]
"")
@ -812,13 +812,13 @@
&& (REGNO (operands[0]) != REGNO (operands[1])
|| REGNO (operands[0]) != REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 1)
(plus:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
[(set (subreg:SI (match_dup 0) 4)
(plus:SI (subreg:SI (match_dup 1) 4)
(subreg:SI (match_dup 2) 4)))
(set (match_dup 3)
(ltu:SI (subreg:SI (match_dup 0) 1)
(subreg:SI (match_dup 2) 1)))
(ltu:SI (subreg:SI (match_dup 0) 4)
(subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 0)
(plus:SI (subreg:SI (match_dup 1) 0)
@ -865,8 +865,8 @@
(ltu:SI (subreg:SI (match_dup 0) 0)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 1)
(plus:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(plus:SI (subreg:SI (match_dup 1) 4)
(match_dup 3)))]
"")
@ -881,12 +881,12 @@
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
&& INTVAL (operands[2]) > 0"
[(set (subreg:SI (match_dup 0) 1)
(plus:SI (subreg:SI (match_dup 1) 1)
[(set (subreg:SI (match_dup 0) 4)
(plus:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(ltu:SI (subreg:SI (match_dup 0) 1)
(ltu:SI (subreg:SI (match_dup 0) 4)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
@ -1307,12 +1307,12 @@
(minus:SI (subreg:SI (match_dup 1) 0)
(subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1)
(minus:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
(set (subreg:SI (match_dup 0) 4)
(minus:SI (subreg:SI (match_dup 1) 4)
(subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 1)
(minus:SI (subreg:SI (match_dup 0) 1)
(set (subreg:SI (match_dup 0) 4)
(minus:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))]
"")
@ -1328,12 +1328,12 @@
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (match_dup 3)
(ltu:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
(ltu:SI (subreg:SI (match_dup 1) 4)
(subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 1)
(minus:SI (subreg:SI (match_dup 1) 1)
(subreg:SI (match_dup 2) 1)))
(set (subreg:SI (match_dup 0) 4)
(minus:SI (subreg:SI (match_dup 1) 4)
(subreg:SI (match_dup 2) 4)))
(set (subreg:SI (match_dup 0) 0)
(minus:SI (subreg:SI (match_dup 1) 0)
@ -1378,8 +1378,8 @@
(minus:SI (subreg:SI (match_dup 1) 0)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 1)
(minus:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(minus:SI (subreg:SI (match_dup 1) 4)
(match_dup 3)))]
"")
@ -1395,11 +1395,11 @@
&& INTVAL (operands[2]) > 0"
[(set (match_dup 3)
(ltu:SI (subreg:SI (match_dup 1) 1)
(ltu:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 1)
(minus:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(minus:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (subreg:SI (match_dup 0) 0)
@ -3121,7 +3121,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
(set (subreg:SI (match_dup 0) 1) (not:SI (subreg:SI (match_dup 1) 1)))]
(set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
"")
@ -3224,7 +3224,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1) (and:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
(set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_insn "anddi3_internal1"
@ -3325,7 +3325,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1) (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
(set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_expand "xorsi3"
@ -3429,7 +3429,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0)))
(set (subreg:SI (match_dup 0) 1) (xor:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1)))]
(set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4) (subreg:SI (match_dup 2) 4)))]
"")
(define_insn "xordi3_immed"
@ -3478,7 +3478,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
[(set (subreg:SI (match_dup 0) 0) (and:SI (not:SI (subreg:SI (match_dup 1) 0)) (not:SI (subreg:SI (match_dup 2) 0))))
(set (subreg:SI (match_dup 0) 1) (and:SI (not:SI (subreg:SI (match_dup 1) 1)) (not:SI (subreg:SI (match_dup 2) 1))))]
(set (subreg:SI (match_dup 0) 4) (and:SI (not:SI (subreg:SI (match_dup 1) 4)) (not:SI (subreg:SI (match_dup 2) 4))))]
"")
;;
@ -4917,7 +4917,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
(set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))]
(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
(define_insn "movdi_internal2"
@ -6147,7 +6147,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
(set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))]
(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
;; Instructions to load the global pointer register.
@ -6516,7 +6516,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 1) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
[(set (subreg:SI (match_dup 0) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -6533,8 +6533,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
(set (subreg:SI (match_dup 0) 1) (const_int 0))]
[(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
(set (subreg:SI (match_dup 0) 4) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -6574,16 +6574,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
[(set (subreg:SI (match_dup 0) 1)
(ashift:SI (subreg:SI (match_dup 1) 1)
[(set (subreg:SI (match_dup 0) 4)
(ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(lshiftrt:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 1)
(ior:SI (subreg:SI (match_dup 0) 1)
(set (subreg:SI (match_dup 0) 4)
(ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)
@ -6614,15 +6614,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
(lshiftrt:SI (subreg:SI (match_dup 1) 1)
(lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 1)
(ashift:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@ -6871,8 +6871,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
(set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 1) (const_int 31)))]
[(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -6887,7 +6887,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 1) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
[(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -6932,15 +6932,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 1)
(ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 1)
(ashiftrt:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(ashiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@ -6962,16 +6962,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
[(set (subreg:SI (match_dup 0) 1)
(lshiftrt:SI (subreg:SI (match_dup 1) 1)
[(set (subreg:SI (match_dup 0) 4)
(lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 1)
(ior:SI (subreg:SI (match_dup 0) 1)
(set (subreg:SI (match_dup 0) 4)
(ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)
@ -7255,8 +7255,8 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 1) (match_dup 2)))
(set (subreg:SI (match_dup 0) 1) (const_int 0))]
[(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2)))
(set (subreg:SI (match_dup 0) 4) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -7272,7 +7272,7 @@ move\\t%0,%z4\\n\\
&& GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER
&& (INTVAL (operands[2]) & 32) != 0"
[(set (subreg:SI (match_dup 0) 1) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
[(set (subreg:SI (match_dup 0) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2)))
(set (subreg:SI (match_dup 0) 0) (const_int 0))]
"operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);")
@ -7317,15 +7317,15 @@ move\\t%0,%z4\\n\\
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 1)
(ashift:SI (subreg:SI (match_dup 1) 4)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 0)
(ior:SI (subreg:SI (match_dup 0) 0)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 1)
(lshiftrt:SI (subreg:SI (match_dup 1) 1)
(set (subreg:SI (match_dup 0) 4)
(lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))]
"
{
@ -7347,16 +7347,16 @@ move\\t%0,%z4\\n\\
&& (INTVAL (operands[2]) & 63) < 32
&& (INTVAL (operands[2]) & 63) != 0"
[(set (subreg:SI (match_dup 0) 1)
(lshiftrt:SI (subreg:SI (match_dup 1) 1)
[(set (subreg:SI (match_dup 0) 4)
(lshiftrt:SI (subreg:SI (match_dup 1) 4)
(match_dup 2)))
(set (match_dup 3)
(ashift:SI (subreg:SI (match_dup 1) 0)
(match_dup 4)))
(set (subreg:SI (match_dup 0) 1)
(ior:SI (subreg:SI (match_dup 0) 1)
(set (subreg:SI (match_dup 0) 4)
(ior:SI (subreg:SI (match_dup 0) 4)
(match_dup 3)))
(set (subreg:SI (match_dup 0) 0)

View File

@ -162,8 +162,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_DOUBLE:
@ -222,8 +221,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
break;
case CONST_DOUBLE:
@ -322,8 +320,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_INT:

View File

@ -143,8 +143,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
case CONST_DOUBLE:
@ -204,8 +203,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);
fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
break;
case CONST_DOUBLE:
@ -289,8 +287,7 @@ print_operand (file, x, code)
break;
case SUBREG:
fprintf (file, "%s",
reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);
fprintf (file, "%s", reg_names[subreg_regno (x)]);
break;
/* This will only be single precision.... */

View File

@ -1275,7 +1275,7 @@
;; Retain this insn which *does* have a pattern indicating what it does,
;; just in case the compiler is smart enough to recognize a substitution.
(define_insn "udivmoddisi4"
[(set (subreg:SI (match_operand:DI 0 "nonimmediate_operand" "=rm") 1)
[(set (subreg:SI (match_operand:DI 0 "nonimmediate_operand" "=rm") 4)
(truncate:SI (udiv:DI (match_operand:DI 1 "nonimmediate_operand" "0")
(zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))))
(set (subreg:SI (match_operand:DI 3 "nonimmediate_operand" "=0") 0)
@ -1338,7 +1338,7 @@
"deiw %2,%0")
(define_insn "udivmoddihi4"
[(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 1)
[(set (subreg:HI (match_operand:DI 0 "register_operand" "=r") 2)
(truncate:HI (udiv:DI (match_operand:DI 1 "register_operand" "0")
(zero_extend:DI (match_operand:HI 2 "nonimmediate_operand" "rm")))))
(set (subreg:HI (match_operand:DI 3 "register_operand" "=0") 0)

View File

@ -1192,11 +1192,11 @@ emit_move_sequence (operands, mode, scratch_reg)
&& GET_CODE (SUBREG_REG (operand0)) == REG
&& REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
{
/* We must not alter SUBREG_WORD (operand0) since that would confuse
/* We must not alter SUBREG_BYTE (operand0) since that would confuse
the code which tracks sets/uses for delete_output_reload. */
rtx temp = gen_rtx_SUBREG (GET_MODE (operand0),
reg_equiv_mem [REGNO (SUBREG_REG (operand0))],
SUBREG_WORD (operand0));
SUBREG_BYTE (operand0));
operand0 = alter_subreg (temp);
}
@ -1209,11 +1209,11 @@ emit_move_sequence (operands, mode, scratch_reg)
&& GET_CODE (SUBREG_REG (operand1)) == REG
&& REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
{
/* We must not alter SUBREG_WORD (operand0) since that would confuse
/* We must not alter SUBREG_BYTE (operand0) since that would confuse
the code which tracks sets/uses for delete_output_reload. */
rtx temp = gen_rtx_SUBREG (GET_MODE (operand1),
reg_equiv_mem [REGNO (SUBREG_REG (operand1))],
SUBREG_WORD (operand1));
SUBREG_BYTE (operand1));
operand1 = alter_subreg (temp);
}

View File

@ -3505,9 +3505,9 @@
(set_attr "length" "4")])
(define_expand "floatunssisf2"
[(set (subreg:SI (match_dup 2) 1)
[(set (subreg:SI (match_dup 2) 4)
(match_operand:SI 1 "register_operand" ""))
(set (subreg:SI (match_dup 2) 0)
(set (subreg:SI (match_dup 2) 4)
(const_int 0))
(set (match_operand:SF 0 "register_operand" "")
(float:SF (match_dup 2)))]
@ -3523,7 +3523,7 @@
}")
(define_expand "floatunssidf2"
[(set (subreg:SI (match_dup 2) 1)
[(set (subreg:SI (match_dup 2) 4)
(match_operand:SI 1 "register_operand" ""))
(set (subreg:SI (match_dup 2) 0)
(const_int 0))
@ -3891,7 +3891,7 @@
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_SUBREG (SImode, scratch, 1)));
gen_rtx_SUBREG (SImode, scratch, GET_MODE_SIZE (SImode))));
DONE;
}
operands[3] = gen_reg_rtx (SImode);

View File

@ -766,7 +766,7 @@
(define_expand "zero_extendhisi2"
[(set (subreg:HI
(match_dup 0)
1)
2)
(match_operand:HI 1 "register_operand" "r"))
(set (subreg:HI
(match_operand:SI 0 "register_operand" "=r")
@ -1782,16 +1782,16 @@
[(set_attr "length" "2")])
(define_expand "modhi3"
[(set (subreg:HI (match_dup 1) 1)
[(set (subreg:HI (match_dup 1) 2)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))
(set (match_operand:HI 0 "general_operand" "=r")
(subreg:HI (match_dup 1) 1))]
(subreg:HI (match_dup 1) 2))]
"TARGET_45"
"")
(define_insn ""
[(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 1)
[(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 4)
(mod:HI (match_operand:SI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
"TARGET_45"
@ -1802,11 +1802,11 @@
; [(parallel [(set (subreg:HI (match_dup 1) 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 1) 1)
; (set (subreg:HI (match_dup 1) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))])
; (set (match_operand:HI 3 "general_operand" "=r")
; (subreg:HI (match_dup 1) 1))
; (subreg:HI (match_dup 1) 2))
; (set (match_operand:HI 0 "general_operand" "=r")
; (subreg:HI (match_dup 1) 0))]
; "TARGET_45"
@ -1816,7 +1816,7 @@
; [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
; (div:HI (match_operand:SI 1 "general_operand" "0")
; (match_operand:HI 2 "general_operand" "g")))
; (set (subreg:HI (match_dup 0) 1)
; (set (subreg:HI (match_dup 0) 2)
; (mod:HI (match_dup 1)
; (match_dup 2)))]
; "TARGET_45"

View File

@ -269,12 +269,7 @@ memory_offset_in_range_p (op, mode, low, high)
while (GET_CODE (op) == SUBREG)
{
offset += SUBREG_WORD (op) * UNITS_PER_WORD;
#if BYTES_BIG_ENDIAN
offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- min (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))));
#endif
offset += SUBREG_BYTE (op);
op = SUBREG_REG (op);
}

View File

@ -666,7 +666,7 @@ output_movedouble (insn, operands, mode)
if (GET_CODE (inside) == REG)
ptrreg = REGNO (inside);
else if (GET_CODE (inside) == SUBREG)
ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
ptrreg = subreg_regno (inside);
else if (GET_CODE (inside) == PLUS)
{
ptrreg = REGNO (XEXP (inside, 0));
@ -1143,13 +1143,13 @@ gen_ashift_hi (type, n, reg)
gen_ashift_hi is only called in contexts where we know that the
sign extension works out correctly. */
{
int word = 0;
int offset = 0;
if (GET_CODE (reg) == SUBREG)
{
word = SUBREG_WORD (reg);
offset = SUBREG_BYTE (reg);
reg = SUBREG_REG (reg);
}
gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, word));
gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));
break;
}
case ASHIFT:
@ -2516,7 +2516,11 @@ regs_used (x, is_dest)
break;
if (REGNO (y) < 16)
return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
<< (REGNO (y) + SUBREG_WORD (x) + is_dest));
<< (REGNO (y) +
subreg_regno_offset (REGNO (y),
GET_MODE (y),
SUBREG_BYTE (x),
GET_MODE (x)) + is_dest));
return 0;
}
case SET:
@ -3260,7 +3264,10 @@ machine_dependent_reorg (first)
mode = HImode;
while (GET_CODE (dst) == SUBREG)
{
offset += SUBREG_WORD (dst);
offset += subreg_regno_offset (REGNO (SUBREG_REG (dst)),
GET_MODE (SUBREG_REG (dst)),
SUBREG_BYTE (dst),
GET_MODE (dst));
dst = SUBREG_REG (dst);
}
dst = gen_rtx_REG (HImode, REGNO (dst) + offset);

View File

@ -1401,7 +1401,7 @@ extern int current_function_anonymous_args;
((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
|| (GET_CODE (X) == SUBREG \
&& GET_CODE (SUBREG_REG (X)) == REG \
&& SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_WORD (X))))
&& SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
/* Jump to LABEL if X is a valid address RTX. This must also take
REG_OK_STRICT into account when deciding about valid registers, but it uses

View File

@ -2591,7 +2591,7 @@
if (GET_CODE (operands[0]) == REG)
regno = REGNO (operands[0]);
else if (GET_CODE (operands[0]) == SUBREG)
regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]);
regno = subreg_regno (operands[0]);
else if (GET_CODE (operands[0]) == MEM)
regno = -1;
@ -2729,7 +2729,7 @@
mem = operands[1];
store_p = 0;
}
if (GET_CODE (mem) == SUBREG && SUBREG_WORD (mem) == 0)
if (GET_CODE (mem) == SUBREG && SUBREG_BYTE (mem) == 0)
mem = SUBREG_REG (mem);
if (GET_CODE (mem) == MEM)
{
@ -2751,7 +2751,7 @@
mem = copy_rtx (mem);
PUT_MODE (mem, SImode);
word0 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 0));
word1 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 1));
word1 = alter_subreg (gen_rtx (SUBREG, SImode, regop, 4));
if (store_p || ! refers_to_regno_p (REGNO (word0),
REGNO (word0) + 1, addr, 0))
{
@ -2963,7 +2963,7 @@
if (GET_CODE (operands[0]) == REG)
regno = REGNO (operands[0]);
else if (GET_CODE (operands[0]) == SUBREG)
regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]);
regno = subreg_regno (operands[0]);
else if (GET_CODE (operands[0]) == MEM)
regno = -1;

View File

@ -7494,8 +7494,8 @@ ultra_find_type (type_mask, list, start)
&& GET_CODE (SET_SRC (pat)) == SUBREG
&& REGNO (SUBREG_REG (SET_DEST (slot_pat))) ==
REGNO (SUBREG_REG (SET_SRC (pat)))
&& SUBREG_WORD (SET_DEST (slot_pat)) ==
SUBREG_WORD (SET_SRC (pat)))))
&& SUBREG_BYTE (SET_DEST (slot_pat)) ==
SUBREG_BYTE (SET_SRC (pat)))))
|| (check_fpmode_conflict == 1
&& GET_CODE (slot_insn) == INSN
&& GET_CODE (slot_pat) == SET

View File

@ -1146,25 +1146,34 @@ while (0)
: (GET_MODE_SIZE (MODE) + 3) / 4) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* A subreg in 64 bit mode will have the wrong offset for a floating point
register. The least significant part is at offset 1, compared to 0 for
integer registers. This only applies when FMODE is a larger mode.
We also need to handle a special case of TF-->DF conversions. */
#define ALTER_HARD_SUBREG(TMODE, WORD, FMODE, REGNO) \
(TARGET_ARCH64 \
&& (REGNO) >= SPARC_FIRST_FP_REG \
&& (REGNO) <= SPARC_LAST_V9_FP_REG \
&& (TMODE) == SImode \
&& !((FMODE) == QImode || (FMODE) == HImode) \
? ((REGNO) + 1) \
: ((TMODE) == DFmode && (FMODE) == TFmode) \
? ((REGNO) + ((WORD) * 2)) \
: ((REGNO) + (WORD)))
/* Due to the ARCH64 descrepancy above we must override these
next two macros too. */
#define REG_SIZE(R) \
(TARGET_ARCH64 \
&& ((GET_CODE (R) == REG \
&& ((REGNO (R) >= FIRST_PSEUDO_REGISTER \
&& FLOAT_MODE_P (GET_MODE (R))) \
|| (REGNO (R) < FIRST_PSEUDO_REGISTER \
&& REGNO (R) >= 32))) \
|| (GET_CODE (R) == SUBREG \
&& ((REGNO (SUBREG_REG (R)) >= FIRST_PSEUDO_REGISTER \
&& FLOAT_MODE_P (GET_MODE (SUBREG_REG (R)))) \
|| (REGNO (SUBREG_REG (R)) < FIRST_PSEUDO_REGISTER \
&& REGNO (SUBREG_REG (R)) >= 32)))) \
? (GET_MODE_SIZE (GET_MODE (R)) + 3) / 4 \
: (GET_MODE_SIZE (GET_MODE (R)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
#define REGMODE_NATURAL_SIZE(MODE) \
((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
extern int *hard_regno_mode_classes;
extern int sparc_mode_class[];
/* ??? Because of the funny way we pass parameters we should allow certain
??? types of float/complex values to be in integer registers during
??? RTL generation. This only matters on arch32. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0)

View File

@ -4546,15 +4546,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (SImode);
op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
DONE;
@ -4624,15 +4626,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (DImode);
op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_lshrdi3 (operand0, temp, shift_48));
DONE;
@ -4794,7 +4798,7 @@
(define_insn "*cmp_siqi_trunc"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 3)
(const_int 0)))]
""
"andcc\\t%0, 0xff, %%g0"
@ -4803,10 +4807,10 @@
(define_insn "*cmp_siqi_trunc_set"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 0)
(compare:CC (subreg:QI (match_operand:SI 1 "register_operand" "r") 3)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
(subreg:QI (match_dup 1) 0))]
(subreg:QI (match_dup 1) 3))]
""
"andcc\\t%1, 0xff, %0"
[(set_attr "type" "compare")
@ -4814,7 +4818,7 @@
(define_insn "*cmp_diqi_trunc"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 0)
(compare:CC (subreg:QI (match_operand:DI 0 "register_operand" "r") 7)
(const_int 0)))]
"TARGET_ARCH64"
"andcc\\t%0, 0xff, %%g0"
@ -4823,10 +4827,10 @@
(define_insn "*cmp_diqi_trunc_set"
[(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 0)
(compare:CC (subreg:QI (match_operand:DI 1 "register_operand" "r") 7)
(const_int 0)))
(set (match_operand:QI 0 "register_operand" "=r")
(subreg:QI (match_dup 1) 0))]
(subreg:QI (match_dup 1) 7))]
"TARGET_ARCH64"
"andcc\\t%1, 0xff, %0"
[(set_attr "type" "compare")
@ -4846,15 +4850,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_16 = GEN_INT (16);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (SImode);
op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
DONE;
@ -4876,23 +4882,27 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op1_subword = 0;
int op0_subword = 0;
int op1_subbyte = 0;
int op0_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (SImode);
op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
if (GET_CODE (operand0) == SUBREG)
{
op0_subword = SUBREG_WORD (operand0);
op0_subbyte = SUBREG_BYTE (operand0);
op0_subbyte /= GET_MODE_SIZE (SImode);
op0_subbyte *= GET_MODE_SIZE (SImode);
operand0 = XEXP (operand0, 0);
}
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
if (GET_MODE (operand0) != SImode)
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subword);
operand0 = gen_rtx_SUBREG (SImode, operand0, op0_subbyte);
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
}")
@ -4913,15 +4923,17 @@
{
rtx temp = gen_reg_rtx (SImode);
rtx shift_24 = GEN_INT (24);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (SImode);
op1_subbyte *= GET_MODE_SIZE (SImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subword),
emit_insn (gen_ashlsi3 (temp, gen_rtx_SUBREG (SImode, operand1, op1_subbyte),
shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
@ -4943,15 +4955,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_56 = GEN_INT (56);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (DImode);
op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_56));
emit_insn (gen_ashrdi3 (operand0, temp, shift_56));
DONE;
@ -4973,15 +4987,17 @@
{
rtx temp = gen_reg_rtx (DImode);
rtx shift_48 = GEN_INT (48);
int op1_subword = 0;
int op1_subbyte = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subword = SUBREG_WORD (operand1);
op1_subbyte = SUBREG_BYTE (operand1);
op1_subbyte /= GET_MODE_SIZE (DImode);
op1_subbyte *= GET_MODE_SIZE (DImode);
operand1 = XEXP (operand1, 0);
}
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subword),
emit_insn (gen_ashldi3 (temp, gen_rtx_SUBREG (DImode, operand1, op1_subbyte),
shift_48));
emit_insn (gen_ashrdi3 (operand0, temp, shift_48));
DONE;
@ -6275,7 +6291,7 @@
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
(match_operand:SI 3 "const_int_operand" "i,i"))
1))
4))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
@ -8346,7 +8362,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
(const_int 32)) 0)
(const_int 32)) 4)
(match_operand:SI 2 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& ((GET_CODE (operands[2]) == CONST_INT
@ -8366,7 +8382,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
(const_int 32)) 0)
(const_int 32)) 4)
(match_operand:SI 2 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& ((GET_CODE (operands[2]) == CONST_INT
@ -8386,7 +8402,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "small_int_or_double" "n")) 0)
(match_operand:SI 2 "small_int_or_double" "n")) 4)
(match_operand:SI 3 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
@ -8405,7 +8421,7 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:SI 2 "small_int_or_double" "n")) 0)
(match_operand:SI 2 "small_int_or_double" "n")) 4)
(match_operand:SI 3 "small_int_or_double" "n")))]
"TARGET_ARCH64
&& GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT

View File

@ -541,7 +541,7 @@ print_operand (file, x, code)
fputs (reg_names[REGNO (x)], file);
break;
case SUBREG:
fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
fputs (reg_names[subreg_regno (x)], file);
break;
case CONST_INT:
case SYMBOL_REF:
@ -823,7 +823,7 @@ output_move_double (operands)
if (GET_CODE (inside) == REG)
ptrreg = REGNO (inside);
else if (GET_CODE (inside) == SUBREG)
ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
ptrreg = subreg_regno (inside);
else if (GET_CODE (inside) == PLUS)
ptrreg = REGNO (XEXP (inside, 0));
else if (GET_CODE (inside) == LO_SUM)

View File

@ -1220,11 +1220,11 @@ mention_regs (x)
/* If reg_tick has been incremented more than once since
reg_in_table was last set, that means that the entire
register has been set before, so discard anything memorized
for the entrire register, including all SUBREG expressions. */
for the entire register, including all SUBREG expressions. */
if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
remove_invalid_refs (i);
else
remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
}
REG_IN_TABLE (i) = REG_TICK (i);
@ -2004,32 +2004,31 @@ remove_invalid_refs (regno)
}
}
/* Likewise for a subreg with subreg_reg WORD and mode MODE. */
/* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
and mode MODE. */
static void
remove_invalid_subreg_refs (regno, word, mode)
remove_invalid_subreg_refs (regno, offset, mode)
unsigned int regno;
unsigned int word;
unsigned int offset;
enum machine_mode mode;
{
unsigned int i;
struct table_elt *p, *next;
unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
for (i = 0; i < HASH_SIZE; i++)
for (p = table[i]; p; p = next)
{
rtx exp;
rtx exp = p->exp;
next = p->next_same_hash;
exp = p->exp;
if (GET_CODE (p->exp) != REG
if (GET_CODE (exp) != REG
&& (GET_CODE (exp) != SUBREG
|| GET_CODE (SUBREG_REG (exp)) != REG
|| REGNO (SUBREG_REG (exp)) != regno
|| (((SUBREG_WORD (exp)
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1) / UNITS_PER_WORD)
>= word)
&& SUBREG_WORD (exp) <= end))
|| (((SUBREG_BYTE (exp)
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
&& SUBREG_BYTE (exp) <= end))
&& refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
remove_from_table (p, i);
}
@ -2302,7 +2301,8 @@ canon_hash (x, mode)
if (GET_CODE (SUBREG_REG (x)) == REG)
{
hash += (((unsigned) SUBREG << 7)
+ REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+ REGNO (SUBREG_REG (x))
+ (SUBREG_BYTE (x) / UNITS_PER_WORD));
return hash;
}
break;
@ -3413,7 +3413,8 @@ fold_rtx (x, insn)
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
new = operand_subword (folded_arg0, SUBREG_WORD (x), 0,
new = operand_subword (folded_arg0,
(SUBREG_BYTE (x) / UNITS_PER_WORD), 0,
GET_MODE (SUBREG_REG (x)));
if (new == 0 && subreg_lowpart_p (x))
new = gen_lowpart_if_possible (mode, folded_arg0);
@ -4393,10 +4394,12 @@ gen_lowpart_if_possible (mode, x)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
if (BYTES_BIG_ENDIAN)
/* Adjust the address so that the address-after-the-data is
unchanged. */
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
{
/* Adjust the address so that the address-after-the-data is
unchanged. */
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
}
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
if (! memory_address_p (mode, XEXP (new, 0)))
return 0;

View File

@ -2024,20 +2024,15 @@ dbxout_symbol_location (decl, type, suffix, home)
else if (GET_CODE (home) == SUBREG)
{
rtx value = home;
int offset = 0;
while (GET_CODE (value) == SUBREG)
{
offset += SUBREG_WORD (value);
value = SUBREG_REG (value);
}
value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return 0;
regno += offset;
}
alter_subreg (home);
regno = REGNO (alter_subreg (home));
}
/* The kind-of-variable letter depends on where

View File

@ -3494,7 +3494,7 @@ is_pseudo_reg (rtl)
{
return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
|| (GET_CODE (rtl) == SUBREG
&& REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
&& REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER));
}
/* Return a reference to a type, with its const and volatile qualifiers
@ -7038,7 +7038,7 @@ mem_loc_descriptor (rtl, mode)
up an entire register. For now, just assume that it is
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
rtl = XEXP (rtl, 0);
rtl = SUBREG_REG (rtl);
/* Fall through. */
@ -7182,7 +7182,7 @@ loc_descriptor (rtl)
up an entire register. For now, just assume that it is
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
rtl = XEXP (rtl, 0);
rtl = SUBREG_REG (rtl);
/* Fall through. */

View File

@ -817,7 +817,7 @@ is_pseudo_reg (rtl)
{
return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
|| ((GET_CODE (rtl) == SUBREG)
&& (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
&& (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)));
}
inline static tree
@ -1630,7 +1630,7 @@ output_mem_loc_descriptor (rtl)
legitimate to make the Dwarf info refer to the whole register
which contains the given subreg. */
rtl = XEXP (rtl, 0);
rtl = SUBREG_REG (rtl);
/* Drop thru. */
case REG:
@ -1714,7 +1714,7 @@ output_loc_descriptor (rtl)
legitimate to make the Dwarf info refer to the whole register
which contains the given subreg. */
rtl = XEXP (rtl, 0);
rtl = SUBREG_REG (rtl);
/* Drop thru. */
case REG:

View File

@ -348,6 +348,55 @@ gen_rtx_MEM (mode, addr)
return rt;
}
rtx
gen_rtx_SUBREG (mode, reg, offset)
enum machine_mode mode;
rtx reg;
int offset;
{
/* This is the most common failure type.
Catch it early so we can see who does it. */
if ((offset % GET_MODE_SIZE (mode)) != 0)
abort ();
/* This check isn't usable right now because combine will
throw arbitrary crap like a CALL into a SUBREG in
gen_lowpart_for_combine so we must just eat it. */
#if 0
/* Check for this too. */
if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
abort ();
#endif
return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
}
/* Generate a SUBREG representing the least-significant part
* of REG if MODE is smaller than mode of REG, otherwise
* paradoxical SUBREG. */
rtx
gen_lowpart_SUBREG (mode, reg)
enum machine_mode mode;
rtx reg;
{
enum machine_mode inmode;
int offset;
inmode = GET_MODE (reg);
if (inmode == VOIDmode)
inmode = mode;
offset = 0;
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
&& (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
{
offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
if (! BYTES_BIG_ENDIAN)
offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
else if (! WORDS_BIG_ENDIAN)
offset %= UNITS_PER_WORD;
}
return gen_rtx_SUBREG (mode, reg, offset);
}
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
@ -650,6 +699,38 @@ get_first_label_num ()
return first_label_num;
}
/* Return the final regno of X, which is a SUBREG of a hard
register. */
int
subreg_hard_regno (x, check_mode)
register rtx x;
int check_mode;
{
enum machine_mode mode = GET_MODE (x);
unsigned int byte_offset, base_regno, final_regno;
rtx reg = SUBREG_REG (x);
/* This is where we attempt to catch illegal subregs
created by the compiler. */
if (GET_CODE (x) != SUBREG
|| GET_CODE (reg) != REG)
abort ();
base_regno = REGNO (reg);
if (base_regno >= FIRST_PSEUDO_REGISTER)
abort ();
if (! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
abort ();
final_regno = subreg_regno (x);
return final_regno;
}
/* Return a value representing some low-order bits of X, where the number
of low-order bits is given by MODE. Note that no conversion is done
between floating-point and fixed-point values, rather, the bit
@ -666,22 +747,29 @@ gen_lowpart_common (mode, x)
enum machine_mode mode;
register rtx x;
{
int word = 0;
int msize = GET_MODE_SIZE (mode);
int xsize = GET_MODE_SIZE (GET_MODE (x));
int offset = 0;
if (GET_MODE (x) == mode)
return x;
/* MODE must occupy no more words than the mode of X. */
if (GET_MODE (x) != VOIDmode
&& ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
> ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
/ UNITS_PER_WORD)))
&& ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
> ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
return 0;
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
word = ((GET_MODE_SIZE (GET_MODE (x))
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD);
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
&& xsize > msize)
{
int difference = xsize - msize;
if (WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
&& (GET_MODE_CLASS (mode) == MODE_INT
@ -703,39 +791,40 @@ gen_lowpart_common (mode, x)
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
}
else if (GET_CODE (x) == SUBREG
&& (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
|| GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
|| GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
? SUBREG_REG (x)
: gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + word));
{
int final_offset;
if (GET_MODE (SUBREG_REG (x)) == mode && subreg_lowpart_p (x))
return SUBREG_REG (x);
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = SUBREG_BYTE (x) + offset;
final_offset = (final_offset / GET_MODE_SIZE (mode));
final_offset = (final_offset * GET_MODE_SIZE (mode));
return gen_rtx_SUBREG (mode, SUBREG_REG (x), final_offset);
}
else if (GET_CODE (x) == REG)
{
/* Let the backend decide how many registers to skip. This is needed
in particular for Sparc64 where fp regs are smaller than a word. */
/* ??? Note that subregs are now ambiguous, in that those against
pseudos are sized by the Word Size, while those against hard
regs are sized by the underlying register size. Better would be
to always interpret the subreg offset parameter as bytes or bits. */
/* 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 (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 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;
/* 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)
if ((! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x))
@ -752,9 +841,9 @@ gen_lowpart_common (mode, x)
&& x != arg_pointer_rtx
#endif
&& x != stack_pointer_rtx)
return gen_rtx_REG (mode, REGNO (x) + word);
else
return gen_rtx_SUBREG (mode, x, word);
return gen_rtx_REG (mode, final_regno);
}
return gen_rtx_SUBREG (mode, x, offset);
}
/* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
from the low-order part of the constant. */
@ -847,7 +936,7 @@ gen_lowpart_common (mode, x)
&& GET_CODE (x) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
return operand_subword (x, word, 0, GET_MODE (x));
return constant_subword (x, (offset / UNITS_PER_WORD), GET_MODE (x));
/* Similarly, if this is converting a floating-point value into a
two-word integer, we can do this one word at a time and make an
@ -863,11 +952,14 @@ gen_lowpart_common (mode, x)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
{
rtx lowpart
= operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));
rtx highpart
= operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
rtx lowpart, highpart;
lowpart = constant_subword (x,
(offset / UNITS_PER_WORD) + WORDS_BIG_ENDIAN,
GET_MODE (x));
highpart = constant_subword (x,
(offset / UNITS_PER_WORD) + (! WORDS_BIG_ENDIAN),
GET_MODE (x));
if (lowpart && GET_CODE (lowpart) == CONST_INT
&& highpart && GET_CODE (highpart) == CONST_INT)
return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
@ -1021,7 +1113,7 @@ gen_imagpart (mode, x)
return XEXP (x, 1);
else if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
else if (!WORDS_BIG_ENDIAN
else if (! WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
&& REG_P (x)
&& REGNO (x) < FIRST_PSEUDO_REGISTER)
@ -1043,7 +1135,7 @@ subreg_realpart_p (x)
if (GET_CODE (x) != SUBREG)
abort ();
return ((unsigned int) SUBREG_WORD (x) * UNITS_PER_WORD
return ((unsigned int) SUBREG_BYTE (x)
< GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))));
}
@ -1101,10 +1193,13 @@ gen_highpart (mode, x)
enum machine_mode mode;
register rtx x;
{
unsigned int msize = GET_MODE_SIZE (mode);
unsigned int xsize = GET_MODE_SIZE (GET_MODE (x));
/* This case loses if X is a subreg. To catch bugs early,
complain if an invalid MODE is used even in other cases. */
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
if (msize > UNITS_PER_WORD
&& msize != GET_MODE_UNIT_SIZE (GET_MODE (x)))
abort ();
if (GET_CODE (x) == CONST_DOUBLE
#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
@ -1121,15 +1216,14 @@ gen_highpart (mode, x)
else if (GET_CODE (x) == MEM)
{
register int offset = 0;
if (! WORDS_BIG_ENDIAN)
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
offset = (MAX (xsize, UNITS_PER_WORD)
- MAX (msize, UNITS_PER_WORD));
if (! BYTES_BIG_ENDIAN
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
offset -= (GET_MODE_SIZE (mode)
- MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (x))));
&& msize < UNITS_PER_WORD)
offset -= (msize - MIN (UNITS_PER_WORD, xsize));
return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
}
@ -1138,46 +1232,47 @@ gen_highpart (mode, x)
/* The only time this should occur is when we are looking at a
multi-word item with a SUBREG whose mode is the same as that of the
item. It isn't clear what we would do if it wasn't. */
if (SUBREG_WORD (x) != 0)
if (SUBREG_BYTE (x) != 0)
abort ();
return gen_highpart (mode, SUBREG_REG (x));
}
else if (GET_CODE (x) == REG)
{
int word;
/* Let the backend decide how many registers to skip. This is needed
in particular for sparc64 where fp regs are smaller than a word. */
/* ??? Note that subregs are now ambiguous, in that those against
pseudos are sized by the word size, while those against hard
regs are sized by the underlying register size. Better would be
to always interpret the subreg offset parameter as bytes or bits. */
int offset = 0;
if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
abort ();
else if (WORDS_BIG_ENDIAN)
word = 0;
else if (REGNO (x) < FIRST_PSEUDO_REGISTER)
word = (HARD_REGNO_NREGS (REGNO (x), GET_MODE (x))
- HARD_REGNO_NREGS (REGNO (x), mode));
else
word = ((GET_MODE_SIZE (GET_MODE (x))
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
/ UNITS_PER_WORD);
if (REGNO (x) < FIRST_PSEUDO_REGISTER
/* integrate.c can't handle parts of a return value register. */
&& (! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
if ((! WORDS_BIG_ENDIAN || ! BYTES_BIG_ENDIAN)
&& xsize > msize)
{
int difference = xsize - msize;
if (! WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (! BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
if (REGNO (x) < FIRST_PSEUDO_REGISTER)
{
int final_regno = REGNO (x) +
subreg_regno_offset (REGNO (x), GET_MODE (x), offset, mode);
/* integrate.c can't handle parts of a return value register.
??? Then integrate.c should be fixed!
??? What about CLASS_CANNOT_CHANGE_SIZE? */
if ((! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
/* We want to keep the stack, frame, and arg pointers special. */
&& x != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& x != arg_pointer_rtx
&& x != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& x != arg_pointer_rtx
#endif
&& x != stack_pointer_rtx)
return gen_rtx_REG (mode, REGNO (x) + word);
else
return gen_rtx_SUBREG (mode, x, word);
&& x != stack_pointer_rtx)
return gen_rtx_REG (mode, final_regno);
}
/* Just generate a normal SUBREG. */
return gen_rtx_SUBREG (mode, x, offset);
}
else
abort ();
@ -1191,154 +1286,44 @@ int
subreg_lowpart_p (x)
rtx x;
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- GET_MODE_SIZE (GET_MODE (x)));
if (GET_CODE (x) != SUBREG)
return 1;
else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
return 0;
if (WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
return (SUBREG_WORD (x)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
- MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
/ UNITS_PER_WORD));
if (difference > 0)
{
if (WORDS_BIG_ENDIAN)
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset += difference % UNITS_PER_WORD;
}
return SUBREG_WORD (x) == 0;
return SUBREG_BYTE (x) == offset;
}
/* Return subword I of operand OP.
The word number, I, is interpreted as the word number starting at the
low-order address. Word 0 is the low-order word if not WORDS_BIG_ENDIAN,
otherwise it is the high-order word.
If we cannot extract the required word, we return zero. Otherwise, an
rtx corresponding to the requested word will be returned.
VALIDATE_ADDRESS is nonzero if the address should be validated. Before
reload has completed, a valid address will always be returned. After
reload, if a valid address cannot be returned, we return zero.
If VALIDATE_ADDRESS is zero, we simply form the required address; validating
it is the responsibility of the caller.
MODE is the mode of OP in case it is a CONST_INT. */
/* Helper routine for all the constant cases of operand_subword.
Some places invoke this directly. */
rtx
operand_subword (op, i, validate_address, mode)
constant_subword (op, offset, mode)
rtx op;
unsigned int i;
int validate_address;
int offset;
enum machine_mode mode;
{
HOST_WIDE_INT val;
int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
if (mode == VOIDmode)
mode = GET_MODE (op);
if (mode == VOIDmode)
abort ();
/* If OP is narrower than a word, fail. */
if (mode != BLKmode
&& (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
return 0;
/* If we want a word outside OP, return zero. */
if (mode != BLKmode
&& (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
return const0_rtx;
HOST_WIDE_INT val;
/* If OP is already an integer word, return it. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
/* If OP is a REG or SUBREG, we can handle it very simply. */
if (GET_CODE (op) == REG)
{
/* ??? There is a potential problem with this code. It does not
properly handle extractions of a subword from a hard register
that is larger than word_mode. Presumably the check for
HARD_REGNO_MODE_OK catches these most of these cases. */
/* If OP is a hard register, but OP + I is not a hard register,
then extracting a subword is impossible.
For example, consider if OP is the last hard register and it is
larger than word_mode. If we wanted word N (for N > 0) because a
part of that hard register was known to contain a useful value,
then OP + I would refer to a pseudo, not the hard register we
actually wanted. */
if (REGNO (op) < FIRST_PSEUDO_REGISTER
&& REGNO (op) + i >= FIRST_PSEUDO_REGISTER)
return 0;
/* If the register is not valid for MODE, return 0. Note we
have to check both OP and OP + I since they may refer to
different parts of the register file.
Consider if OP refers to the last 96bit FP register and we want
subword 3 because that subword is known to contain a value we
needed. */
if (REGNO (op) < FIRST_PSEUDO_REGISTER
&& (! HARD_REGNO_MODE_OK (REGNO (op), word_mode)
|| ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)))
return 0;
else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| (REG_FUNCTION_VALUE_P (op)
&& rtx_equal_function_value_matters)
/* We want to keep the stack, frame, and arg pointers
special. */
|| op == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| op == arg_pointer_rtx
#endif
|| op == stack_pointer_rtx)
return gen_rtx_SUBREG (word_mode, op, i);
else
return gen_rtx_REG (word_mode, REGNO (op) + i);
}
else if (GET_CODE (op) == SUBREG)
return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));
else if (GET_CODE (op) == CONCAT)
{
unsigned int partwords
= GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
if (i < partwords)
return operand_subword (XEXP (op, 0), i, validate_address, mode);
return operand_subword (XEXP (op, 1), i - partwords,
validate_address, mode);
}
/* Form a new MEM at the requested address. */
if (GET_CODE (op) == MEM)
{
rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);
rtx new;
if (validate_address)
{
if (reload_completed)
{
if (! strict_memory_address_p (word_mode, addr))
return 0;
}
else
addr = memory_address (word_mode, addr);
}
new = gen_rtx_MEM (word_mode, addr);
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
/* The only remaining cases are when OP is a constant. If the host and
target floating formats are the same, handling two-word floating
constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
are defined as returning one or two 32 bit values, respectively,
and not values of BITS_PER_WORD bits. */
#ifdef REAL_ARITHMETIC
/* The output is some bits, the width of the target machine's word.
A wider-word host can surely hold them in a CONST_INT. A narrower-word
@ -1365,12 +1350,12 @@ operand_subword (op, i, validate_address, mode)
So we explicitly mask and sign-extend as necessary. */
if (BITS_PER_WORD == 32)
{
val = k[i];
val = k[offset];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
#if HOST_BITS_PER_WIDE_INT >= 64
else if (BITS_PER_WORD >= 64 && i == 0)
else if (BITS_PER_WORD >= 64 && offset == 0)
{
val = k[! WORDS_BIG_ENDIAN];
val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
@ -1380,8 +1365,8 @@ operand_subword (op, i, validate_address, mode)
#endif
else if (BITS_PER_WORD == 16)
{
val = k[i >> 1];
if ((i & 1) == !WORDS_BIG_ENDIAN)
val = k[offset >> 1];
if ((offset & 1) == ! WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
return GEN_INT (val);
@ -1402,16 +1387,16 @@ operand_subword (op, i, validate_address, mode)
if (BITS_PER_WORD == 32)
{
val = k[i];
val = k[offset];
val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
return GEN_INT (val);
}
#if HOST_BITS_PER_WIDE_INT >= 64
else if (BITS_PER_WORD >= 64 && i <= 1)
else if (BITS_PER_WORD >= 64 && offset <= 1)
{
val = k[i*2 + ! WORDS_BIG_ENDIAN];
val = k[offset * 2 + ! WORDS_BIG_ENDIAN];
val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
val |= (HOST_WIDE_INT) k[i*2 + WORDS_BIG_ENDIAN] & 0xffffffff;
val |= (HOST_WIDE_INT) k[offset * 2 + WORDS_BIG_ENDIAN] & 0xffffffff;
return GEN_INT (val);
}
#endif
@ -1431,10 +1416,10 @@ operand_subword (op, i, validate_address, mode)
compilers don't like a conditional inside macro args, so we have two
copies of the return. */
#ifdef HOST_WORDS_BIG_ENDIAN
return GEN_INT (i == WORDS_BIG_ENDIAN
return GEN_INT (offset == WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#else
return GEN_INT (i != WORDS_BIG_ENDIAN
return GEN_INT (offset != WORDS_BIG_ENDIAN
? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
#endif
}
@ -1460,7 +1445,7 @@ operand_subword (op, i, validate_address, mode)
if (BITS_PER_WORD == 16)
{
if ((i & 1) == !WORDS_BIG_ENDIAN)
if ((offset & 1) == ! WORDS_BIG_ENDIAN)
val >>= 16;
val &= 0xffff;
}
@ -1504,7 +1489,7 @@ operand_subword (op, i, validate_address, mode)
/* The only remaining cases that we can handle are integers.
Convert to proper endianness now since these cases need it.
At this point, i == 0 means the low-order word.
At this point, offset == 0 means the low-order word.
We do not want to handle the case when BITS_PER_WORD <= HOST_BITS_PER_INT
in general. However, if OP is (const_int 0), we can just return
@ -1519,39 +1504,184 @@ operand_subword (op, i, validate_address, mode)
return 0;
if (WORDS_BIG_ENDIAN)
i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
offset = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - offset;
/* Find out which word on the host machine this value is in and get
it from the constant. */
val = (i / size_ratio == 0
val = (offset / size_ratio == 0
? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))
: (GET_CODE (op) == CONST_INT
? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));
/* Get the value we want into the low bits of val. */
if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)
val = ((val >> ((i % size_ratio) * BITS_PER_WORD)));
val = ((val >> ((offset % size_ratio) * BITS_PER_WORD)));
val = trunc_int_for_mode (val, word_mode);
return GEN_INT (val);
}
/* Return subword OFFSET of operand OP.
The word number, OFFSET, is interpreted as the word number starting
at the low-order address. OFFSET 0 is the low-order word if not
WORDS_BIG_ENDIAN, otherwise it is the high-order word.
If we cannot extract the required word, we return zero. Otherwise,
an rtx corresponding to the requested word will be returned.
VALIDATE_ADDRESS is nonzero if the address should be validated. Before
reload has completed, a valid address will always be returned. After
reload, if a valid address cannot be returned, we return zero.
If VALIDATE_ADDRESS is zero, we simply form the required address; validating
it is the responsibility of the caller.
MODE is the mode of OP in case it is a CONST_INT.
??? This is still rather broken for some cases. The problem for the
moment is that all callers of this thing provide no 'goal mode' to
tell us to work with. This exists because all callers were written
in a word based SUBREG world. */
rtx
operand_subword (op, offset, validate_address, mode)
rtx op;
unsigned int offset;
int validate_address;
enum machine_mode mode;
{
if (mode == VOIDmode)
mode = GET_MODE (op);
if (mode == VOIDmode)
abort ();
/* If OP is narrower than a word, fail. */
if (mode != BLKmode
&& (GET_MODE_SIZE (mode) < UNITS_PER_WORD))
return 0;
/* If we want a word outside OP, return zero. */
if (mode != BLKmode
&& (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
return const0_rtx;
switch (GET_CODE (op))
{
case REG:
case SUBREG:
case CONCAT:
case MEM:
break;
default:
/* The only remaining cases are when OP is a constant. If the host and
target floating formats are the same, handling two-word floating
constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
are defined as returning one or two 32 bit values, respectively,
and not values of BITS_PER_WORD bits. */
return constant_subword (op, offset, mode);
}
/* If OP is already an integer word, return it. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
/* If OP is a REG or SUBREG, we can handle it very simply. */
if (GET_CODE (op) == REG)
{
if (REGNO (op) < FIRST_PSEUDO_REGISTER)
{
int final_regno = REGNO (op) +
subreg_regno_offset (REGNO (op), GET_MODE (op),
offset * UNITS_PER_WORD,
word_mode);
/* If the register is not valid for MODE, return 0. If we don't
do this, there is no way to fix up the resulting REG later. */
if (! HARD_REGNO_MODE_OK (final_regno, word_mode))
return 0;
/* integrate.c can't handle parts of a return value register.
??? Then integrate.c should be fixed!
??? What about CLASS_CANNOT_CHANGE_SIZE? */
if ((! REG_FUNCTION_VALUE_P (op)
|| ! rtx_equal_function_value_matters)
/* ??? What about CLASS_CANNOT_CHANGE_SIZE? */
/* We want to keep the stack, frame, and arg pointers
special. */
&& op != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& op != arg_pointer_rtx
#endif
&& op != stack_pointer_rtx)
return gen_rtx_REG (word_mode, final_regno);
}
/* Just return a normal SUBREG. */
return gen_rtx_SUBREG (word_mode, op,
(offset * UNITS_PER_WORD));
}
else if (GET_CODE (op) == SUBREG)
{
int final_offset = ((offset * UNITS_PER_WORD) + SUBREG_BYTE (op));
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (word_mode));
final_offset = (final_offset * GET_MODE_SIZE (word_mode));
return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), final_offset);
}
else if (GET_CODE (op) == CONCAT)
{
unsigned int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
if (offset < partwords)
return operand_subword (XEXP (op, 0), offset, validate_address, mode);
return operand_subword (XEXP (op, 1), offset - partwords,
validate_address, mode);
}
/* Form a new MEM at the requested address. */
if (GET_CODE (op) == MEM)
{
rtx addr = plus_constant (XEXP (op, 0), (offset * UNITS_PER_WORD));
rtx new;
if (validate_address)
{
if (reload_completed)
{
if (! strict_memory_address_p (word_mode, addr))
return 0;
}
else
addr = memory_address (word_mode, addr);
}
new = gen_rtx_MEM (word_mode, addr);
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
/* Unreachable... (famous last words) */
abort ();
}
/* Similar to `operand_subword', but never return 0. If we can't extract
the required subword, put OP into a register and try again. If that fails,
abort. We always validate the address in this case. It is not valid
to call this function after reload; it is mostly meant for RTL
generation.
abort. We always validate the address in this case.
MODE is the mode of OP, in case it is CONST_INT. */
rtx
operand_subword_force (op, i, mode)
operand_subword_force (op, offset, mode)
rtx op;
unsigned int i;
unsigned int offset;
enum machine_mode mode;
{
rtx result = operand_subword (op, i, 1, mode);
rtx result = operand_subword (op, offset, 1, mode);
if (result)
return result;
@ -1566,7 +1696,7 @@ operand_subword_force (op, i, mode)
op = force_reg (mode, op);
}
result = operand_subword (op, i, 1, mode);
result = operand_subword (op, offset, 1, mode);
if (result == 0)
abort ();

View File

@ -261,7 +261,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
meaningful at a much higher level; when structures are copied
between memory and regs, the higher-numbered regs
always get higher addresses. */
offset += SUBREG_WORD (op0);
offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
/* We used to adjust BITPOS here, but now we do the whole adjustment
right after the loop. */
op0 = SUBREG_REG (op0);
@ -311,7 +311,9 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
abort ();
}
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
op0 = gen_rtx_SUBREG (fieldmode, op0,
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD));
else
op0 = change_address (op0, fieldmode,
plus_constant (XEXP (op0, 0), offset));
@ -373,7 +375,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
}
emit_insn (GEN_FCN (icode)
(gen_rtx_SUBREG (fieldmode, op0, offset), value));
(gen_rtx_SUBREG (fieldmode, op0,
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD)),
value));
return value;
}
@ -447,7 +452,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
abort ();
}
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
op0, offset);
op0, (offset * UNITS_PER_WORD));
}
offset = 0;
}
@ -550,7 +555,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
if (GET_CODE (xop0) == SUBREG)
/* We can't just change the mode, because this might clobber op0,
and we will need the original value of op0 if insv fails. */
xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_WORD (xop0));
xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
@ -910,8 +915,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG)
{
word = operand_subword_force (SUBREG_REG (op0),
SUBREG_WORD (op0) + offset,
int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0)));
offset = 0;
}
@ -1008,7 +1013,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
offset += SUBREG_WORD (op0);
offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
inner_size = MIN (inner_size, BITS_PER_WORD);
@ -1104,7 +1109,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
abort ();
}
if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, offset);
op0 = gen_rtx_SUBREG (mode1, op0,
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD));
else
op0 = change_address (op0, mode1,
plus_constant (XEXP (op0, 0), offset));
@ -1213,7 +1220,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
if (GET_CODE (op0) != REG)
op0 = copy_to_reg (op0);
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
op0, offset);
op0, (offset * UNITS_PER_WORD));
}
offset = 0;
}
@ -1808,8 +1815,8 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG)
{
word = operand_subword_force (SUBREG_REG (op0),
SUBREG_WORD (op0) + offset,
int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0)));
offset = 0;
}
@ -1928,7 +1935,7 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
% GET_MODE_BITSIZE (mode));
else if (GET_CODE (op1) == SUBREG
&& SUBREG_WORD (op1) == 0)
&& SUBREG_BYTE (op1) == 0)
op1 = SUBREG_REG (op1);
}
#endif

View File

@ -4134,7 +4134,7 @@ store_expr (exp, target, want_value)
if (want_value && GET_MODE (temp) != GET_MODE (target)
&& GET_MODE (temp) != VOIDmode)
{
temp = gen_rtx_SUBREG (GET_MODE (target), temp, 0);
temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp)
= SUBREG_PROMOTED_UNSIGNED_P (target);
@ -6346,7 +6346,7 @@ expand_expr (exp, target, tmode, modifier)
!= promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
abort ();
temp = gen_rtx_SUBREG (mode, DECL_RTL (exp), 0);
temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
return temp;
@ -6466,7 +6466,7 @@ expand_expr (exp, target, tmode, modifier)
if (GET_CODE (temp) == REG && GET_MODE (temp) != mode)
{
temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
}
@ -6489,7 +6489,7 @@ expand_expr (exp, target, tmode, modifier)
{
/* Compute the signedness and make the proper SUBREG. */
promote_mode (type, mode, &unsignedp, 0);
temp = gen_rtx_SUBREG (mode, SAVE_EXPR_RTL (exp), 0);
temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
return temp;

View File

@ -3119,20 +3119,8 @@ alter_subreg (x)
if (GET_CODE (y) == REG)
{
int regno;
/* If the word size is larger than the size of this register,
adjust the register number to compensate. */
/* ??? Note that this just catches stragglers created by/for
integrate. It would be better if we either caught these
earlier, or kept _all_ subregs until now and eliminate
gen_lowpart and friends. */
int regno = subreg_hard_regno (x, 1);
#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);
@ -3142,11 +3130,12 @@ alter_subreg (x)
}
else if (GET_CODE (y) == MEM)
{
register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
register int offset = SUBREG_BYTE (x);
/* Catch these instead of generating incorrect code. */
if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
abort ();
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
MEM_COPY_ATTRIBUTES (x, y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);

View File

@ -3088,7 +3088,7 @@ set_noop_p (set)
if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
{
if (SUBREG_WORD (src) != SUBREG_WORD (dst))
if (SUBREG_BYTE (src) != SUBREG_BYTE (dst))
return 0;
src = SUBREG_REG (src);
dst = SUBREG_REG (dst);
@ -4669,12 +4669,9 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
regno_last = regno_first = REGNO (SUBREG_REG (reg));
if (regno_first < FIRST_PSEUDO_REGISTER)
{
#ifdef ALTER_HARD_SUBREG
regno_first = ALTER_HARD_SUBREG (outer_mode, SUBREG_WORD (reg),
inner_mode, regno_first);
#else
regno_first += SUBREG_WORD (reg);
#endif
regno_first += subreg_regno_offset (regno_first, inner_mode,
SUBREG_BYTE (reg),
outer_mode);
regno_last = (regno_first
+ HARD_REGNO_NREGS (regno_first, outer_mode) - 1);

View File

@ -2221,7 +2221,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
dest = XEXP (dest, 0);
if (GET_CODE (src) == SUBREG)
src = XEXP (src, 0);
src = SUBREG_REG (src);
/* If VAR does not appear at the top level of the SET
just scan the lower levels of the tree. */
@ -2505,7 +2505,7 @@ fixup_memory_subreg (x, insn, uncritical)
rtx insn;
int uncritical;
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
int offset = SUBREG_BYTE (x);
rtx addr = XEXP (SUBREG_REG (x), 0);
enum machine_mode mode = GET_MODE (x);
rtx result;
@ -2515,9 +2515,6 @@ fixup_memory_subreg (x, insn, uncritical)
&& ! uncritical)
abort ();
if (BYTES_BIG_ENDIAN)
offset += (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
addr = plus_constant (addr, offset);
if (!flag_force_addr && memory_address_p (mode, addr))
/* Shortcut if no insns need be emitted. */
@ -2711,7 +2708,8 @@ optimize_bit_field (body, insn, equiv_mem)
offset /= BITS_PER_UNIT;
if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
{
offset += SUBREG_WORD (XEXP (bitfield, 0)) * UNITS_PER_WORD;
offset += (SUBREG_BYTE (XEXP (bitfield, 0))
/ UNITS_PER_WORD) * UNITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
@ -2736,7 +2734,7 @@ optimize_bit_field (body, insn, equiv_mem)
{
rtx src = SET_SRC (body);
while (GET_CODE (src) == SUBREG
&& SUBREG_WORD (src) == 0)
&& SUBREG_BYTE (src) == 0)
src = SUBREG_REG (src);
if (GET_MODE (src) != GET_MODE (memref))
src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
@ -2757,7 +2755,7 @@ optimize_bit_field (body, insn, equiv_mem)
rtx dest = SET_DEST (body);
while (GET_CODE (dest) == SUBREG
&& SUBREG_WORD (dest) == 0
&& SUBREG_BYTE (dest) == 0
&& (GET_MODE_CLASS (GET_MODE (dest))
== GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
@ -3067,7 +3065,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
code did. This is especially true of
REG_RETVAL. */
if (GET_CODE (z) == SUBREG && SUBREG_WORD (z) == 0)
if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
z = SUBREG_REG (z);
if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
@ -3443,17 +3441,22 @@ purge_single_hard_subreg_set (pattern)
{
rtx reg = SET_DEST (pattern);
enum machine_mode mode = GET_MODE (SET_DEST (pattern));
int word = 0;
while (GET_CODE (reg) == SUBREG)
int offset = 0;
if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG
&& REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER)
{
word += SUBREG_WORD (reg);
offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
GET_MODE (SUBREG_REG (reg)),
SUBREG_BYTE (reg),
GET_MODE (reg));
reg = SUBREG_REG (reg);
}
if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
{
reg = gen_rtx_REG (mode, REGNO (reg) + word);
reg = gen_rtx_REG (mode, REGNO (reg) + offset);
SET_DEST (pattern) = reg;
}
}
@ -4737,6 +4740,20 @@ assign_parms (fndecl)
push_to_sequence (conversion_insns);
tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
if (GET_CODE (tempreg) == SUBREG
&& GET_MODE (tempreg) == nominal_mode
&& GET_CODE (SUBREG_REG (tempreg)) == REG
&& nominal_mode == passed_mode
&& GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (entry_parm)
&& GET_MODE_SIZE (GET_MODE (tempreg))
< GET_MODE_SIZE (GET_MODE (entry_parm)))
{
/* The argument is already sign/zero extended, so note it
into the subreg. */
SUBREG_PROMOTED_VAR_P (tempreg) = 1;
SUBREG_PROMOTED_UNSIGNED_P (tempreg) = unsignedp;
}
/* TREE_USED gets set erroneously during expand_assignment. */
save_tree_used = TREE_USED (parm);
expand_assignment (parm,

View File

@ -208,6 +208,7 @@ special_rtx (idx)
return (strcmp (defs[idx].enumname, "CONST_INT") == 0
|| strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
|| strcmp (defs[idx].enumname, "REG") == 0
|| strcmp (defs[idx].enumname, "SUBREG") == 0
|| strcmp (defs[idx].enumname, "MEM") == 0);
}

View File

@ -1422,17 +1422,8 @@ mark_reg_store (reg, setter, data)
{
register int regno;
/* WORD is which word of a multi-register group is being stored.
For the case where the store is actually into a SUBREG of REG.
Except we don't use it; I believe the entire REG needs to be
made live. */
int word = 0;
if (GET_CODE (reg) == SUBREG)
{
word = SUBREG_WORD (reg);
reg = SUBREG_REG (reg);
}
reg = SUBREG_REG (reg);
if (GET_CODE (reg) != REG)
return;
@ -1456,7 +1447,7 @@ mark_reg_store (reg, setter, data)
}
if (reg_renumber[regno] >= 0)
regno = reg_renumber[regno] /* + word */;
regno = reg_renumber[regno];
/* Handle hardware regs (and pseudos allocated to hard regs). */
if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
@ -1606,7 +1597,15 @@ set_preference (dest, src)
else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
{
src_regno = REGNO (SUBREG_REG (src));
offset += SUBREG_WORD (src);
if (REGNO (SUBREG_REG (src)) < FIRST_PSEUDO_REGISTER)
offset += subreg_regno_offset (REGNO (SUBREG_REG (src)),
GET_MODE (SUBREG_REG (src)),
SUBREG_BYTE (src),
GET_MODE (src));
else
offset += (SUBREG_BYTE (src)
/ REGMODE_NATURAL_SIZE (GET_MODE (src)));
}
else
return;
@ -1616,7 +1615,15 @@ set_preference (dest, src)
else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
{
dest_regno = REGNO (SUBREG_REG (dest));
offset -= SUBREG_WORD (dest);
if (REGNO (SUBREG_REG (dest)) < FIRST_PSEUDO_REGISTER)
offset -= subreg_regno_offset (REGNO (SUBREG_REG (dest)),
GET_MODE (SUBREG_REG (dest)),
SUBREG_BYTE (dest),
GET_MODE (dest));
else
offset -= (SUBREG_BYTE (dest)
/ REGMODE_NATURAL_SIZE (GET_MODE (dest)));
}
else
return;

View File

@ -557,10 +557,7 @@ noce_emit_move_insn (x, y)
inner = XEXP (outer, 0);
outmode = GET_MODE (outer);
inmode = GET_MODE (inner);
bitpos = SUBREG_WORD (outer) * BITS_PER_WORD;
if (BYTES_BIG_ENDIAN)
bitpos += (GET_MODE_BITSIZE (inmode) - GET_MODE_BITSIZE (outmode))
% BITS_PER_WORD;
bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
store_bit_field (inner, GET_MODE_BITSIZE (outmode),
bitpos, outmode, y, GET_MODE_BITSIZE (inmode),
GET_MODE_BITSIZE (inmode));

View File

@ -1895,23 +1895,33 @@ copy_rtx_and_substitute (orig, map, for_lhs)
copy = copy_rtx_and_substitute (SUBREG_REG (orig), map, for_lhs);
/* SUBREG is ordinary, but don't make nested SUBREGs. */
if (GET_CODE (copy) == SUBREG)
return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
SUBREG_WORD (orig) + SUBREG_WORD (copy));
{
int final_offset = SUBREG_BYTE (orig) + SUBREG_BYTE (copy);
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
return gen_rtx_SUBREG (GET_MODE (orig), SUBREG_REG (copy),
final_offset);
}
else if (GET_CODE (copy) == CONCAT)
{
rtx retval = subreg_realpart_p (orig) ? XEXP (copy, 0) : XEXP (copy, 1);
int final_offset;
if (GET_MODE (retval) == GET_MODE (orig))
return retval;
else
return gen_rtx_SUBREG (GET_MODE (orig), retval,
(SUBREG_WORD (orig) %
(GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)))
/ (unsigned) UNITS_PER_WORD)));
final_offset = SUBREG_BYTE (orig) %
GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (orig)));
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (orig)));
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (orig)));
return gen_rtx_SUBREG (GET_MODE (orig), retval, final_offset);
}
else
return gen_rtx_SUBREG (GET_MODE (orig), copy,
SUBREG_WORD (orig));
SUBREG_BYTE (orig));
case ADDRESSOF:
copy = gen_rtx_ADDRESSOF (mode,
@ -2397,8 +2407,8 @@ subst_constants (loc, insn, map, memonly)
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
&& GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
new = operand_subword (inner, SUBREG_WORD (x), 0,
GET_MODE (SUBREG_REG (x)));
new = operand_subword (inner, SUBREG_BYTE (x) / UNITS_PER_WORD,
0, GET_MODE (SUBREG_REG (x)));
cancel_changes (num_changes);
if (new == 0 && subreg_lowpart_p (x))
@ -2675,7 +2685,12 @@ mark_stores (dest, x, data)
regno = REGNO (dest), mode = GET_MODE (dest);
else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
{
regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
regno = REGNO (SUBREG_REG (dest));
if (regno < FIRST_PSEUDO_REGISTER)
regno += subreg_regno_offset (REGNO (SUBREG_REG (dest)),
GET_MODE (SUBREG_REG (dest)),
SUBREG_BYTE (dest),
GET_MODE (dest));
mode = GET_MODE (SUBREG_REG (dest));
}

View File

@ -3543,7 +3543,7 @@ rtx_renumbered_equal_p (x, y)
&& GET_CODE (SUBREG_REG (y)) == REG)))
{
int reg_x = -1, reg_y = -1;
int word_x = 0, word_y = 0;
int byte_x = 0, byte_y = 0;
if (GET_MODE (x) != GET_MODE (y))
return 0;
@ -3556,15 +3556,17 @@ rtx_renumbered_equal_p (x, y)
if (code == SUBREG)
{
reg_x = REGNO (SUBREG_REG (x));
word_x = SUBREG_WORD (x);
byte_x = SUBREG_BYTE (x);
if (reg_renumber[reg_x] >= 0)
{
reg_x = reg_renumber[reg_x] + word_x;
word_x = 0;
reg_x = subreg_regno_offset (reg_renumber[reg_x],
GET_MODE (SUBREG_REG (x)),
byte_x,
GET_MODE (x));
byte_x = 0;
}
}
else
{
reg_x = REGNO (x);
@ -3575,15 +3577,17 @@ rtx_renumbered_equal_p (x, y)
if (GET_CODE (y) == SUBREG)
{
reg_y = REGNO (SUBREG_REG (y));
word_y = SUBREG_WORD (y);
byte_y = SUBREG_BYTE (y);
if (reg_renumber[reg_y] >= 0)
{
reg_y = reg_renumber[reg_y];
word_y = 0;
reg_y = subreg_regno_offset (reg_renumber[reg_y],
GET_MODE (SUBREG_REG (y)),
byte_y,
GET_MODE (y));
byte_y = 0;
}
}
else
{
reg_y = REGNO (y);
@ -3591,7 +3595,7 @@ rtx_renumbered_equal_p (x, y)
reg_y = reg_renumber[reg_y];
}
return reg_x >= 0 && reg_x == reg_y && word_x == word_y;
return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
}
/* Now we have disposed of all the cases
@ -3722,7 +3726,9 @@ true_regnum (x)
{
int base = true_regnum (SUBREG_REG (x));
if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
return SUBREG_WORD (x) + base;
return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x), GET_MODE (x));
}
return -1;
}

View File

@ -1813,25 +1813,49 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
may_save_copy = 0;
offset += SUBREG_WORD (usedreg);
if (REGNO (SUBREG_REG (usedreg)) < FIRST_PSEUDO_REGISTER)
offset += subreg_regno_offset (REGNO (SUBREG_REG (usedreg)),
GET_MODE (SUBREG_REG (usedreg)),
SUBREG_BYTE (usedreg),
GET_MODE (usedreg));
else
offset += (SUBREG_BYTE (usedreg)
/ REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
usedreg = SUBREG_REG (usedreg);
}
if (GET_CODE (usedreg) != REG)
return 0;
ureg = REGNO (usedreg);
usize = REG_SIZE (usedreg);
if (ureg < FIRST_PSEUDO_REGISTER)
usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
else
usize = ((GET_MODE_SIZE (GET_MODE (usedreg))
+ (REGMODE_NATURAL_SIZE (GET_MODE (usedreg)) - 1))
/ REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
while (GET_CODE (setreg) == SUBREG)
{
if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (setreg))) > UNITS_PER_WORD)
may_save_copy = 0;
offset -= SUBREG_WORD (setreg);
if (REGNO (SUBREG_REG (setreg)) < FIRST_PSEUDO_REGISTER)
offset -= subreg_regno_offset (REGNO (SUBREG_REG (setreg)),
GET_MODE (SUBREG_REG (setreg)),
SUBREG_BYTE (setreg),
GET_MODE (setreg));
else
offset -= (SUBREG_BYTE (setreg)
/ REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
setreg = SUBREG_REG (setreg);
}
if (GET_CODE (setreg) != REG)
return 0;
sreg = REGNO (setreg);
ssize = REG_SIZE (setreg);
if (sreg < FIRST_PSEUDO_REGISTER)
ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
else
ssize = ((GET_MODE_SIZE (GET_MODE (setreg))
+ (REGMODE_NATURAL_SIZE (GET_MODE (setreg)) - 1))
/ REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
/* If UREG is a pseudo-register that hasn't already been assigned a
quantity number, it means that it is not local to this block or dies
@ -2032,7 +2056,11 @@ reg_is_born (reg, birth)
register int regno;
if (GET_CODE (reg) == SUBREG)
regno = REGNO (SUBREG_REG (reg)) + SUBREG_WORD (reg);
{
regno = REGNO (SUBREG_REG (reg));
if (regno < FIRST_PSEUDO_REGISTER)
regno = subreg_hard_regno (reg, 1);
}
else
regno = REGNO (reg);

View File

@ -517,13 +517,15 @@ validate_replace_rtx_1 (loc, from, to, object)
if (GET_CODE (XEXP (x, 0)) == SUBREG)
{
if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD)
to = operand_subword (to, SUBREG_WORD (XEXP (x, 0)),
to = operand_subword (to,
(SUBREG_BYTE (XEXP (x, 0))
/ UNITS_PER_WORD),
0, GET_MODE (from));
else if (GET_MODE_CLASS (GET_MODE (from)) == MODE_INT
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
<= HOST_BITS_PER_WIDE_INT))
{
int i = SUBREG_WORD (XEXP (x, 0)) * BITS_PER_WORD;
int i = SUBREG_BYTE (XEXP (x, 0)) * BITS_PER_UNIT;
HOST_WIDE_INT valh;
unsigned HOST_WIDE_INT vall;
@ -569,26 +571,21 @@ validate_replace_rtx_1 (loc, from, to, object)
break;
case SUBREG:
/* In case we are replacing by constant, attempt to simplify it to non-SUBREG
expression. We can't do this later, since the information about inner mode
may be lost. */
/* In case we are replacing by constant, attempt to simplify it to
non-SUBREG expression. We can't do this later, since the information
about inner mode may be lost. */
if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
{
if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
&& GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
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 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);
rtx new = gen_lowpart_if_possible (GET_MODE (x), to);
if (new)
{
validate_change (object, loc, new, 1);
@ -596,13 +593,67 @@ validate_replace_rtx_1 (loc, from, to, object)
}
}
/* A paradoxical SUBREG of a VOIDmode constant is the same constant,
since we are saying that the high bits don't matter. */
if (GET_MODE (to) == VOIDmode
&& GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (from)))
offset = SUBREG_BYTE (x) * BITS_PER_UNIT;
switch (GET_CODE (to))
{
validate_change (object, loc, to, 1);
return;
case CONST_DOUBLE:
if (GET_MODE (to) != VOIDmode)
break;
part = offset >= HOST_BITS_PER_WIDE_INT;
if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
&& BYTES_BIG_ENDIAN)
|| (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
&& WORDS_BIG_ENDIAN))
part = !part;
val = part ? CONST_DOUBLE_HIGH (to) : CONST_DOUBLE_LOW (to);
offset %= HOST_BITS_PER_WIDE_INT;
/* FALLTHROUGH */
case CONST_INT:
if (GET_CODE (to) == CONST_INT)
val = INTVAL (to);
{
/* Avoid creating bogus SUBREGs */
enum machine_mode mode = GET_MODE (x);
enum machine_mode inner_mode = GET_MODE (from);
/* We've already picked the word we want from a double, so
pretend this is actually an integer. */
if (GET_CODE (to) == CONST_DOUBLE)
inner_mode = SImode;
if (GET_MODE_CLASS (mode) != MODE_INT)
abort ();
if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
{
if (WORDS_BIG_ENDIAN)
offset = GET_MODE_BITSIZE (inner_mode)
- GET_MODE_BITSIZE (mode) - offset;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
offset = offset + BITS_PER_WORD - GET_MODE_BITSIZE (mode)
- 2 * (offset % BITS_PER_WORD);
}
if (offset >= HOST_BITS_PER_WIDE_INT)
to = ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
else
{
val >>= offset;
if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)
val = trunc_int_for_mode (val, mode);
to = GEN_INT (val);
}
validate_change (object, loc, to, 1);
return;
}
default:
break;
}
}
@ -612,15 +663,26 @@ validate_replace_rtx_1 (loc, from, to, object)
&& rtx_equal_p (SUBREG_REG (x), from))
{
if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))
&& SUBREG_WORD (x) == 0 && SUBREG_WORD (to) == 0)
&& SUBREG_BYTE (x) == 0 && SUBREG_BYTE (to) == 0)
{
validate_change (object, loc, SUBREG_REG (to), 1);
return;
}
validate_change (object, loc,
gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
SUBREG_WORD (x) + SUBREG_WORD (to)), 1);
/* Make sure the 2 byte counts added together are an even unit
of x's mode, and combine them if so. Otherwise we run
into problems with something like:
(subreg:HI (subreg:QI (SI:55) 3) 0)
we end up with an odd offset into a HI which is invalid. */
if (SUBREG_BYTE (to) % GET_MODE_SIZE (GET_MODE (x)) == 0)
validate_change (object, loc,
gen_rtx_SUBREG (GET_MODE (x), SUBREG_REG (to),
SUBREG_BYTE(x) + SUBREG_BYTE (to)),
1);
else
validate_change (object, loc, to, 1);
return;
}
@ -636,15 +698,10 @@ validate_replace_rtx_1 (loc, from, to, object)
&& ! MEM_VOLATILE_P (to)
&& GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
rtx new;
if (BYTES_BIG_ENDIAN)
offset += (MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset));
MEM_COPY_ATTRIBUTES (new, to);
validate_change (object, loc, new, 1);
@ -694,8 +751,8 @@ validate_replace_rtx_1 (loc, from, to, object)
int offset = pos / BITS_PER_UNIT;
rtx newmem;
/* If the bytes and bits are counted differently, we
must adjust the offset. */
/* If the bytes and bits are counted differently, we
must adjust the offset. */
if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode)
- offset);
@ -1040,7 +1097,6 @@ general_operand (op, mode)
enum machine_mode mode;
{
register enum rtx_code code = GET_CODE (op);
int mode_altering_drug = 0;
if (mode == VOIDmode)
mode = GET_MODE (op);
@ -1078,11 +1134,6 @@ general_operand (op, mode)
op = SUBREG_REG (op);
code = GET_CODE (op);
#if 0
/* No longer needed, since (SUBREG (MEM...))
will load the MEM into a reload reg in the MEM's own mode. */
mode_altering_drug = 1;
#endif
}
if (code == REG)
@ -1113,8 +1164,6 @@ general_operand (op, mode)
return 0;
win:
if (mode_altering_drug)
return ! mode_dependent_address_p (XEXP (op, 0));
return 1;
}
@ -1467,13 +1516,9 @@ indirect_operand (op, mode)
if (! reload_completed
&& GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
{
register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
register int offset = SUBREG_BYTE (op);
rtx inner = SUBREG_REG (op);
if (BYTES_BIG_ENDIAN)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner))));
if (mode != VOIDmode && GET_MODE (op) != mode)
return 0;
@ -2482,7 +2527,10 @@ constrain_operands (strict)
{
if (GET_CODE (SUBREG_REG (op)) == REG
&& REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
offset = SUBREG_WORD (op);
offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
GET_MODE (SUBREG_REG (op)),
SUBREG_BYTE (op),
GET_MODE (op));
op = SUBREG_REG (op);
}

View File

@ -557,7 +557,11 @@ get_true_reg (pat)
rtx subreg;
if (FP_REG_P (subreg = SUBREG_REG (*pat)))
{
*pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
int regno_off = subreg_regno_offset (REGNO (subreg),
GET_MODE (subreg),
SUBREG_BYTE (*pat),
GET_MODE (*pat));
*pat = FP_MODE_REG (REGNO (subreg) + regno_off,
GET_MODE (subreg));
default:
return pat;

View File

@ -717,7 +717,7 @@ optimize_reg_copy_3 (insn, dest, src)
/* Now walk forward making additional replacements. We want to be able
to undo all the changes if a later substitution fails. */
subreg = gen_rtx_SUBREG (old_mode, src_reg, 0);
subreg = gen_lowpart_SUBREG (old_mode, src_reg);
while (p = NEXT_INSN (p), p != insn)
{
if (! INSN_P (p))
@ -1168,7 +1168,7 @@ regmove_optimize (f, nregs, regmove_dump_file)
{
src_subreg
= gen_rtx_SUBREG (GET_MODE (SUBREG_REG (dst)),
src, SUBREG_WORD (dst));
src, SUBREG_BYTE (dst));
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG

View File

@ -24,12 +24,28 @@ Boston, MA 02111-1307, USA. */
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
/* Get the number of consecutive hard regs required to hold the REG rtx R.
/* Get the number of consecutive hard regs required to hold the REG or
SUBREG rtx R.
When something may be an explicit hard reg, REG_SIZE is the only
valid way to get this value. You cannot get it from the regno. */
valid way to get this value. You cannot get it from the regno.
A target may override this definition, the case where you would do
this is where there are registers which are smaller than WORD_SIZE
such as the SFmode registers on sparc64. */
#ifndef REG_SIZE
#define REG_SIZE(R) \
((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
#endif
/* When you only have the mode of a pseudo register before it has a hard
register chosen for it, this reports the size of each hard register
a pseudo in such a mode would get allocated to. Like REG_SIZE, a
target may override this. */
#ifndef REGMODE_NATURAL_SIZE
#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
#endif
#ifndef SMALL_REGISTER_CLASSES
#define SMALL_REGISTER_CLASSES 0

View File

@ -791,7 +791,7 @@ reload_inner_reg_of_subreg (x, mode)
return 0;
/* If INNER is not ok for MODE, then INNER will need reloading. */
if (! HARD_REGNO_MODE_OK (REGNO (inner) + SUBREG_WORD (x), mode))
if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
return 1;
/* If the outer part is a word or smaller, INNER larger than a
@ -938,13 +938,12 @@ push_reload (in, out, inloc, outloc, class,
Finally, reload the inner expression if it is a register that is in
the class whose registers cannot be referenced in a different size
and M1 is not the same size as M2. If SUBREG_WORD is nonzero, we
and M1 is not the same size as M2. If SUBREG_BYTE is nonzero, we
cannot reload just the inside since we might end up with the wrong
register class. But if it is inside a STRICT_LOW_PART, we have
no choice, so we hope we do get the right register class there. */
if (in != 0 && GET_CODE (in) == SUBREG
&& (SUBREG_WORD (in) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
@ -978,7 +977,7 @@ push_reload (in, out, inloc, outloc, class,
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
/* The case where out is nonzero
is handled differently in the following statement. */
&& (out == 0 || SUBREG_WORD (in) == 0)
&& (out == 0 || SUBREG_BYTE (in) == 0)
&& ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
> UNITS_PER_WORD)
@ -986,9 +985,7 @@ push_reload (in, out, inloc, outloc, class,
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)))))
|| ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (in))
+ SUBREG_WORD (in)),
inmode)))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
&& (SECONDARY_INPUT_RELOAD_CLASS (class,
@ -1028,7 +1025,7 @@ push_reload (in, out, inloc, outloc, class,
that case. */
/* Similar issue for (SUBREG constant ...) if it was not handled by the
code above. This can happen if SUBREG_WORD != 0. */
code above. This can happen if SUBREG_BYTE != 0. */
if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
{
@ -1038,7 +1035,11 @@ push_reload (in, out, inloc, outloc, class,
RELOAD_OTHER, we are guaranteed that this inner reload will be
output before the outer reload. */
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
find_valid_class (inmode, SUBREG_WORD (in)),
find_valid_class (inmode,
subreg_regno_offset (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)),
SUBREG_BYTE (in),
GET_MODE (in))),
VOIDmode, VOIDmode, 0, 0, opnum, type);
dont_remove_subreg = 1;
}
@ -1050,7 +1051,7 @@ push_reload (in, out, inloc, outloc, class,
(except in the case of STRICT_LOW_PART,
and in that case the constraint should label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (SUBREG_WORD (out) == 0 || strict_low)
&& (SUBREG_BYTE (out) == 0 || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
@ -1080,9 +1081,7 @@ push_reload (in, out, inloc, outloc, class,
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)))))
|| ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (out))
+ SUBREG_WORD (out)),
outmode)))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
&& (SECONDARY_OUTPUT_RELOAD_CLASS (class,
@ -1129,7 +1128,11 @@ push_reload (in, out, inloc, outloc, class,
dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
&SUBREG_REG (out),
find_valid_class (outmode, SUBREG_WORD (out)),
find_valid_class (outmode,
subreg_regno_offset (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
SUBREG_BYTE (out),
GET_MODE (out))),
VOIDmode, VOIDmode, 0, 0,
opnum, RELOAD_OTHER);
}
@ -1146,16 +1149,14 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
in = gen_rtx_REG (GET_MODE (in),
REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
/* Similarly for OUT. */
if (out != 0 && GET_CODE (out) == SUBREG
&& GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& ! dont_remove_subreg)
out = gen_rtx_REG (GET_MODE (out),
REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
/* Narrow down the class of register wanted if that is
desirable on this machine for efficiency. */
@ -1810,15 +1811,28 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
|| GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
return 0;
/* Note that {in,out}_offset are needed only when 'in' or 'out'
respectively refers to a hard register. */
/* Find the inside of any subregs. */
while (GET_CODE (out) == SUBREG)
{
out_offset = SUBREG_WORD (out);
if (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
SUBREG_BYTE (out),
GET_MODE (out));
out = SUBREG_REG (out);
}
while (GET_CODE (in) == SUBREG)
{
in_offset = SUBREG_WORD (in);
if (GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)),
SUBREG_BYTE (in),
GET_MODE (in));
in = SUBREG_REG (in);
}
@ -2035,7 +2049,10 @@ operands_match_p (x, y)
i = REGNO (SUBREG_REG (x));
if (i >= FIRST_PSEUDO_REGISTER)
goto slow;
i += SUBREG_WORD (x);
i += subreg_regno_offset (REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x));
}
else
i = REGNO (x);
@ -2045,7 +2062,10 @@ operands_match_p (x, y)
j = REGNO (SUBREG_REG (y));
if (j >= FIRST_PSEUDO_REGISTER)
goto slow;
j += SUBREG_WORD (y);
j += subreg_regno_offset (REGNO (SUBREG_REG (y)),
GET_MODE (SUBREG_REG (y)),
SUBREG_BYTE (y),
GET_MODE (y));
}
else
j = REGNO (y);
@ -2777,7 +2797,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
while (GET_CODE (operand) == SUBREG)
{
offset += SUBREG_WORD (operand);
/* Offset only matters when operand is a REG and
it is a hard reg. This is because it is passed
to reg_fits_class_p if it is a REG and all pseudos
return 0 from that function. */
if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
GET_MODE (operand));
}
operand = SUBREG_REG (operand);
/* Force reload if this is a constant or PLUS or if there may
be a problem accessing OPERAND in the outer mode. */
@ -2828,6 +2859,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
)
#endif
)
/* This following hunk of code should no longer be
needed at all with SUBREG_BYTE. If you need this
code back, please explain to me why so I can
fix the real problem. -DaveM */
#if 0
/* Subreg of a hard reg which can't handle the subreg's mode
or which would handle that mode in the wrong number of
registers for subregging to work. */
@ -2841,7 +2877,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
!= HARD_REGNO_NREGS (REGNO (operand),
GET_MODE (operand))))
|| ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
operand_mode[i]))))
operand_mode[i])))
#endif
)
force_reload = 1;
}
@ -3716,7 +3754,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx operand = recog_data.operand[i];
while (GET_CODE (operand) == SUBREG)
operand = XEXP (operand, 0);
operand = SUBREG_REG (operand);
if ((GET_CODE (operand) == MEM
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
@ -3766,7 +3804,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
operand = *recog_data.operand_loc[i];
while (GET_CODE (operand) == SUBREG)
operand = XEXP (operand, 0);
operand = SUBREG_REG (operand);
if (GET_CODE (operand) == REG)
{
if (modified[i] != RELOAD_WRITE)
@ -3789,7 +3827,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
rtx operand = recog_data.operand[i];
while (GET_CODE (operand) == SUBREG)
operand = XEXP (operand, 0);
operand = SUBREG_REG (operand);
if ((GET_CODE (operand) == MEM
|| (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
@ -4303,7 +4341,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
&& regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0
&& (tem = operand_subword (reg_equiv_constant[regno],
SUBREG_WORD (x), 0,
SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)))) != 0)
{
/* TEM is now a word sized constant for the bits from X that
@ -4329,7 +4367,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
&& (GET_MODE_SIZE (GET_MODE (x))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
int shift = SUBREG_WORD (x) * BITS_PER_WORD;
int shift = SUBREG_BYTE (x) * BITS_PER_UNIT;
if (WORDS_BIG_ENDIAN)
shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- GET_MODE_BITSIZE (GET_MODE (x))
@ -4383,13 +4421,18 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
the meaning of the memory access. */
enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
/* SUBREG_REG (x) is a MEM, so we cant take the offset, instead we
calculate the register number as :
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode) */
if (is_set_dest)
push_reload (NULL_RTX, SUBREG_REG (x), NULL_PTR, &SUBREG_REG (x),
find_valid_class (subreg_mode, SUBREG_WORD (x)),
find_valid_class (subreg_mode,
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
VOIDmode, subreg_mode, 0, 0, opnum, type);
else
push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), NULL_PTR,
find_valid_class (subreg_mode, SUBREG_WORD (x)),
find_valid_class (subreg_mode,
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
subreg_mode, VOIDmode, 0, 0, opnum, type);
}
@ -5075,7 +5118,11 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
code0 = GET_CODE (op0);
if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
op0 = gen_rtx_REG (word_mode,
REGNO (op0) + SUBREG_WORD (orig_op0));
(REGNO (op0) +
subreg_regno_offset (REGNO (SUBREG_REG (orig_op0)),
GET_MODE (SUBREG_REG (orig_op0)),
SUBREG_BYTE (orig_op0),
GET_MODE (orig_op0))));
}
if (GET_CODE (op1) == SUBREG)
@ -5083,8 +5130,14 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
/* ??? Why is this given op1's mode and above for
??? op0 SUBREGs we use word_mode? */
op1 = gen_rtx_REG (GET_MODE (op1),
REGNO (op1) + SUBREG_WORD (orig_op1));
(REGNO (op1) +
subreg_regno_offset (REGNO (SUBREG_REG (orig_op1)),
GET_MODE (SUBREG_REG (orig_op1)),
SUBREG_BYTE (orig_op1),
GET_MODE (orig_op1))));
}
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
@ -5492,7 +5545,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
needless copies if SUBREG_REG is multi-word. */
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
int regno = subreg_regno (x);
if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
: REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
@ -5646,15 +5699,10 @@ find_reloads_subreg_address (x, force_replace, opnum, type,
if (force_replace
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
int offset = SUBREG_BYTE (x);
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
if (BYTES_BIG_ENDIAN)
{
offset += MIN (inner_size, UNITS_PER_WORD);
offset -= MIN (outer_size, UNITS_PER_WORD);
}
XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
PUT_MODE (tem, GET_MODE (x));
@ -5741,8 +5789,18 @@ subst_reloads (insn)
*r->subreg_loc = SUBREG_REG (reloadreg);
else
{
int final_offset =
SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset /
GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
final_offset = (final_offset *
GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
*r->where = SUBREG_REG (reloadreg);
SUBREG_WORD (*r->subreg_loc) += SUBREG_WORD (reloadreg);
SUBREG_BYTE (*r->subreg_loc) = final_offset;
}
}
else
@ -5843,12 +5901,24 @@ find_replacement (loc)
if (GET_CODE (reloadreg) == REG)
return gen_rtx_REG (GET_MODE (*loc),
REGNO (reloadreg) + SUBREG_WORD (*loc));
(REGNO (reloadreg) +
subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
GET_MODE (SUBREG_REG (*loc)),
SUBREG_BYTE (*loc),
GET_MODE (*loc))));
else if (GET_MODE (reloadreg) == GET_MODE (*loc))
return reloadreg;
else
return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc));
{
int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
final_offset);
}
}
}
@ -5925,7 +5995,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
@ -6020,7 +6090,10 @@ reg_overlap_mentioned_for_reload_p (x, in)
{
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
regno += SUBREG_WORD (x);
regno += subreg_regno_offset (REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x));
}
else if (GET_CODE (x) == REG)
{

View File

@ -2509,7 +2509,7 @@ eliminate_regs (x, mem_mode, insn)
return x;
case SUBREG:
/* Similar to above processing, but preserve SUBREG_WORD.
/* Similar to above processing, but preserve SUBREG_BYTE.
Convert (subreg (mem)) to (mem) if not paradoxical.
Also, if we have a non-paradoxical (subreg (pseudo)) and the
pseudo didn't get a hard reg, we must replace this with the
@ -2526,7 +2526,7 @@ eliminate_regs (x, mem_mode, insn)
else
new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
if (new != XEXP (x, 0))
if (new != SUBREG_REG (x))
{
int x_size = GET_MODE_SIZE (GET_MODE (x));
int new_size = GET_MODE_SIZE (GET_MODE (new));
@ -2547,20 +2547,15 @@ eliminate_regs (x, mem_mode, insn)
|| (x_size == new_size))
)
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
int offset = SUBREG_BYTE (x);
enum machine_mode mode = GET_MODE (x);
if (BYTES_BIG_ENDIAN)
offset += (MIN (UNITS_PER_WORD,
GET_MODE_SIZE (GET_MODE (new)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
PUT_MODE (new, mode);
XEXP (new, 0) = plus_constant (XEXP (new, 0), offset);
return new;
}
else
return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_WORD (x));
return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
}
return x;
@ -4088,10 +4083,14 @@ forget_old_reloads_1 (x, ignored, data)
unsigned int nr;
int offset = 0;
/* note_stores does give us subregs of hard regs. */
/* note_stores does give us subregs of hard regs,
subreg_regno_offset will abort if it is not a hard reg. */
while (GET_CODE (x) == SUBREG)
{
offset += SUBREG_WORD (x);
offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x));
x = SUBREG_REG (x);
}
@ -5401,7 +5400,7 @@ choose_reload_regs (chain)
if (inheritance)
{
int word = 0;
int byte = 0;
register int regno = -1;
enum machine_mode mode = VOIDmode;
@ -5420,10 +5419,10 @@ choose_reload_regs (chain)
else if (GET_CODE (rld[r].in_reg) == SUBREG
&& GET_CODE (SUBREG_REG (rld[r].in_reg)) == REG)
{
word = SUBREG_WORD (rld[r].in_reg);
byte = SUBREG_BYTE (rld[r].in_reg);
regno = REGNO (SUBREG_REG (rld[r].in_reg));
if (regno < FIRST_PSEUDO_REGISTER)
regno += word;
regno = subreg_regno (rld[r].in_reg);
mode = GET_MODE (rld[r].in_reg);
}
#ifdef AUTO_INC_DEC
@ -5444,7 +5443,7 @@ choose_reload_regs (chain)
that can invalidate an inherited reload of part of a pseudoreg. */
else if (GET_CODE (rld[r].in) == SUBREG
&& GET_CODE (SUBREG_REG (rld[r].in)) == REG)
regno = REGNO (SUBREG_REG (rld[r].in)) + SUBREG_WORD (rld[r].in);
regno = subreg_regno (rld[r].in);
#endif
if (regno >= 0 && reg_last_reload_reg[regno] != 0)
@ -5453,15 +5452,15 @@ choose_reload_regs (chain)
rtx last_reg = reg_last_reload_reg[regno];
enum machine_mode need_mode;
i = REGNO (last_reg) + word;
i = REGNO (last_reg);
i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
last_class = REGNO_REG_CLASS (i);
if (word == 0)
if (byte == 0)
need_mode = mode;
else
need_mode
= smallest_mode_for_size (GET_MODE_SIZE (mode)
+ word * UNITS_PER_WORD,
= smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
GET_MODE_CLASS (mode));
if (
@ -5631,7 +5630,7 @@ choose_reload_regs (chain)
Make a new REG since this might be used in an
address and not all machines support SUBREGs
there. */
regno = REGNO (SUBREG_REG (equiv)) + SUBREG_WORD (equiv);
regno = subreg_regno (equiv);
equiv = gen_rtx_REG (rld[r].mode, regno);
}
else
@ -6261,7 +6260,7 @@ emit_input_reload_insns (chain, rl, old, j)
oldequiv = SUBREG_REG (oldequiv);
if (GET_MODE (oldequiv) != VOIDmode
&& mode != GET_MODE (oldequiv))
oldequiv = gen_rtx_SUBREG (mode, oldequiv, 0);
oldequiv = gen_lowpart_SUBREG (mode, oldequiv);
/* Switch to the right place to emit the reload insns. */
switch (rl->when_needed)
@ -8885,7 +8884,10 @@ reload_combine_note_store (dst, set, data)
if (GET_CODE (dst) == SUBREG)
{
regno = SUBREG_WORD (dst);
regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
GET_MODE (SUBREG_REG (dst)),
SUBREG_BYTE (dst),
GET_MODE (dst));
dst = SUBREG_REG (dst);
}
if (GET_CODE (dst) != REG)
@ -9276,7 +9278,10 @@ move2add_note_store (dst, set, data)
if (GET_CODE (dst) == SUBREG)
{
regno = SUBREG_WORD (dst);
regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
GET_MODE (SUBREG_REG (dst)),
SUBREG_BYTE (dst),
GET_MODE (dst));
dst = SUBREG_REG (dst);
}

View File

@ -100,7 +100,7 @@ update_live_status (dest, x, data)
return;
if (GET_CODE (dest) == SUBREG)
first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
first_regno = subreg_regno (dest);
else
first_regno = REGNO (dest);
@ -222,7 +222,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
mark_referenced_resources (SUBREG_REG (x), res, 0);
else
{
unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
unsigned int regno = subreg_regno (x);
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
@ -780,7 +780,7 @@ mark_set_resources (x, res, in_dest, mark_type)
mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
else
{
unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
unsigned int regno = subreg_regno (x);
unsigned int last_regno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (x));

View File

@ -789,10 +789,17 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
#define CONST_DOUBLE_MEM(r) XCEXP (r, 0, CONST_DOUBLE)
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
SUBREG_WORD extracts the word-number. */
SUBREG_BYTE extracts the byte-number. */
#define SUBREG_REG(RTX) XCEXP(RTX, 0, SUBREG)
#define SUBREG_WORD(RTX) XCUINT(RTX, 1, SUBREG)
#define SUBREG_BYTE(RTX) XCUINT(RTX, 1, SUBREG)
/* in rtlanal.c */
extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
enum machine_mode,
unsigned int,
enum machine_mode));
extern unsigned int subreg_regno PARAMS ((rtx));
/* 1 if the REG contained in SUBREG_REG is already known to be
sign- or zero-extended from the mode of the SUBREG to the mode of
@ -1179,6 +1186,7 @@ extern int rtx_equal_p PARAMS ((rtx, rtx));
extern rtvec gen_rtvec_v PARAMS ((int, rtx *));
extern rtx gen_reg_rtx PARAMS ((enum machine_mode));
extern rtx gen_label_rtx PARAMS ((void));
extern int subreg_hard_regno PARAMS ((rtx, int));
extern rtx gen_lowpart_common PARAMS ((enum machine_mode, rtx));
extern rtx gen_lowpart PARAMS ((enum machine_mode, rtx));
@ -1191,6 +1199,8 @@ extern rtx gen_realpart PARAMS ((enum machine_mode, rtx));
extern rtx gen_imagpart PARAMS ((enum machine_mode, rtx));
extern rtx operand_subword PARAMS ((rtx, unsigned int, int,
enum machine_mode));
extern rtx constant_subword PARAMS ((rtx, int,
enum machine_mode));
/* In emit-rtl.c */
extern rtx operand_subword_force PARAMS ((rtx, unsigned int,
@ -1569,8 +1579,11 @@ extern rtx gen_rtx_CONST_DOUBLE PARAMS ((enum machine_mode, rtx,
extern rtx gen_rtx_CONST_INT PARAMS ((enum machine_mode, HOST_WIDE_INT));
extern rtx gen_raw_REG PARAMS ((enum machine_mode, int));
extern rtx gen_rtx_REG PARAMS ((enum machine_mode, int));
extern rtx gen_rtx_SUBREG PARAMS ((enum machine_mode, rtx, int));
extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
extern rtx gen_lowpart_SUBREG PARAMS ((enum machine_mode, rtx));
/* We need the cast here to ensure that we get the same result both with
and without prototypes. */
#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (HOST_WIDE_INT) (N))

View File

@ -1166,16 +1166,16 @@ This virtual register is replaced by the sum of the register given by
@end table
@findex subreg
@item (subreg:@var{m} @var{reg} @var{wordnum})
@item (subreg:@var{m} @var{reg} @var{bytenum})
@code{subreg} expressions are used to refer to a register in a machine
mode other than its natural one, or to refer to one register of
a multi-word @code{reg} that actually refers to several registers.
a multi-part @code{reg} that actually refers to several registers.
Each pseudo-register has a natural mode. If it is necessary to
operate on it in a different mode---for example, to perform a fullword
move instruction on a pseudo-register that contains a single
byte---the pseudo-register must be enclosed in a @code{subreg}. In
such a case, @var{wordnum} is zero.
such a case, @var{bytenum} is zero.
Usually @var{m} is at least as narrow as the mode of @var{reg}, in which
case it is restricting consideration to only the bits of @var{reg} that
@ -1192,7 +1192,7 @@ a multi-register value. Machine modes such as @code{DImode} and
@code{TImode} can indicate values longer than a word, values which
usually require two or more consecutive registers. To access one of the
registers, use a @code{subreg} with mode @code{SImode} and a
@var{wordnum} that says which register.
@var{bytenum} offset that says which register.
Storing in a non-paradoxical @code{subreg} has undefined results for
bits belonging to the same word as the @code{subreg}. This laxity makes
@ -1202,8 +1202,13 @@ the @code{subreg}, use @code{strict_low_part} around the @code{subreg}.
@cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
that word number zero is the most significant part; otherwise, it is
the least significant part.
that byte number zero is part of the most significant word; otherwise,
it is part of the least significant word.
@cindex @code{BYTES_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{BYTES_BIG_ENDIAN}, if set to 1, says
that byte number zero is the most significant byte within a word;
otherwise, it is the least significant byte within a word.
@cindex @code{FLOAT_WORDS_BIG_ENDIAN}, (lack of) effect on @code{subreg}
On a few targets, @code{FLOAT_WORDS_BIG_ENDIAN} disagrees with
@ -1239,10 +1244,10 @@ a single machine register. The reload pass prevents @code{subreg}
expressions such as these from being formed.
@findex SUBREG_REG
@findex SUBREG_WORD
@findex SUBREG_BYTE
The first operand of a @code{subreg} expression is customarily accessed
with the @code{SUBREG_REG} macro and the second operand is customarily
accessed with the @code{SUBREG_WORD} macro.
accessed with the @code{SUBREG_BYTE} macro.
@findex scratch
@cindex scratch operands

View File

@ -1083,7 +1083,7 @@ refers_to_regno_p (regno, endregno, x, loc)
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
unsigned int inner_regno = subreg_regno (x);
unsigned int inner_endregno
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
@ -1170,7 +1170,7 @@ reg_overlap_mentioned_p (x, in)
case SUBREG:
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
regno += SUBREG_WORD (x);
regno = subreg_regno (x);
goto do_reg;
case REG:
@ -2229,18 +2229,32 @@ replace_regs (x, reg_map, nregs, replace_dest)
return map_inner;
else
{
int final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (map_val);
/* When working with REG SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (x)));
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (x)));
/* We cannot call gen_rtx here since we may be linked with
genattrtab.c. */
/* Let's try clobbering the incoming SUBREG and see
if this is really safe. */
SUBREG_REG (x) = map_inner;
SUBREG_WORD (x) += SUBREG_WORD (map_val);
SUBREG_BYTE (x) = final_offset;
return x;
#if 0
rtx new = rtx_alloc (SUBREG);
int final_offset = SUBREG_BYTE (x) + SUBREG_BYTE (map_val);
/* When working with REG SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (x)));
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (x)));
PUT_MODE (new, GET_MODE (x));
SUBREG_REG (new) = map_inner;
SUBREG_WORD (new) = SUBREG_WORD (x) + SUBREG_WORD (map_val);
SUBREG_BYTE (new) = final_offset;
#endif
}
}
@ -2613,3 +2627,65 @@ loc_mentioned_in_p (loc, in)
}
return 0;
}
/* This function returns the regno offset of a subreg expression.
xregno - A regno of an inner hard subreg_reg (or what will become one).
xmode - The mode of xregno.
offset - The byte offset.
ymode - The mode of a top level SUBREG (or what may become one).
RETURN - The regno offset which would be used.
This function can be overridden by defining SUBREG_REGNO_OFFSET,
taking the same parameters. */
unsigned int
subreg_regno_offset (xregno, xmode, offset, ymode)
unsigned int xregno;
enum machine_mode xmode;
unsigned int offset;
enum machine_mode ymode;
{
unsigned ret;
int nregs_xmode, nregs_ymode;
int mode_multiple, nregs_multiple;
int y_offset;
/* Check for an override, and use it instead. */
#ifdef SUBREG_REGNO_OFFSET
ret = SUBREG_REGNO_OFFSET (xregno, xmode, offset, ymode)
#else
if (xregno >= FIRST_PSEUDO_REGISTER)
abort ();
nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
if (offset == 0 || nregs_xmode == nregs_ymode)
return 0;
/* size of ymode must not be greater than the size of xmode. */
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
if (mode_multiple == 0)
abort ();
y_offset = offset / GET_MODE_SIZE (ymode);
nregs_multiple = nregs_xmode / nregs_ymode;
ret = (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
#endif
return ret;
}
/* Return the final regno that a subreg expression refers to. */
unsigned int
subreg_regno (x)
rtx x;
{
unsigned int ret;
rtx subreg = SUBREG_REG (x);
int regno = REGNO (subreg);
ret = regno + subreg_regno_offset (regno,
GET_MODE (subreg),
SUBREG_BYTE (x),
GET_MODE (x));
return ret;
}

View File

@ -591,7 +591,7 @@ print_value (buf, x, verbose)
case SUBREG:
print_value (t, SUBREG_REG (x), verbose);
cur = safe_concat (buf, cur, t);
sprintf (t, "#%d", SUBREG_WORD (x));
sprintf (t, "#%d", SUBREG_BYTE (x));
cur = safe_concat (buf, cur, t);
break;
case SCRATCH:

View File

@ -776,19 +776,15 @@ sdbout_symbol (decl, local)
else if (GET_CODE (value) == SUBREG)
{
int offset = 0;
while (GET_CODE (value) == SUBREG)
{
offset += SUBREG_WORD (value);
value = SUBREG_REG (value);
}
value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
regno = REGNO (value);
if (regno >= FIRST_PSEUDO_REGISTER)
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return;
regno += offset;
}
alter_subreg (DECL_RTL (decl));
regno = REGNO (alter_subreg (DECL_RTL (decl)));
value = DECL_RTL (decl);
}
/* Don't output anything if an auto variable

View File

@ -4166,7 +4166,7 @@ expand_anon_union_decl (decl, cleanup, decl_elts)
if (mode == GET_MODE (x))
SET_DECL_RTL (decl_elt, x);
else
SET_DECL_RTL (decl_elt, gen_rtx_SUBREG (mode, x, 0));
SET_DECL_RTL (decl_elt, gen_lowpart_SUBREG (mode, x));
}
else
abort ();

View File

@ -1697,17 +1697,6 @@ definition of this macro is
/ UNITS_PER_WORD)
@end smallexample
@findex ALTER_HARD_SUBREG
@item ALTER_HARD_SUBREG (@var{tgt_mode}, @var{word}, @var{src_mode}, @var{regno})
A C expression that returns an adjusted hard register number for
@smallexample
(subreg:@var{tgt_mode} (reg:@var{src_mode} @var{regno}) @var{word})
@end smallexample
This may be needed if the target machine has mixed sized big-endian
registers, like Sparc v9.
@findex HARD_REGNO_MODE_OK
@item HARD_REGNO_MODE_OK (@var{regno}, @var{mode})
A C expression that is nonzero if it is permissible to store a value
@ -1790,6 +1779,19 @@ allocation.
Define this macro if the compiler should avoid copies to/from @code{CCmode}
registers. You should only define this macro if support for copying to/from
@code{CCmode} is incomplete.
@findex SUBREG_REGNO_OFFSET
@item SUBREG_REGNO_OFFSET
Define this macro if the compiler needs to handle subregs in a non-standard
way. The macro returns the correct regno offset for mode @code{YMODE} given
a subreg of type @code{XMODE}.
This macro takes 4 parameters:
@code{XREGNO} - A regno of an inner hard subreg_reg (or what will become one).
@code{XMODE} - The mode of xregno.
@code{OFFSET} - The byte offset.
@code{YMODE} - The mode of a top level SUBREG (or what may become one).
The default function can be found in rtlanal.c, function
@code{subreg_regno_offset}. Normally this does not need to be defined.
@end table
@node Leaf Functions