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:
parent
924c96ebc4
commit
ddef6bc7a3
64 changed files with 1634 additions and 867 deletions
212
gcc/ChangeLog
212
gcc/ChangeLog
|
@ -1,3 +1,215 @@
|
|||
2001-04-03 Jakub Jelinek <jakub@redhat.com>
|
||||
David S. Miller <davem@pierdol.cobaltmicro.com>
|
||||
Andrew MacLeod <amacleod@redhat.com>
|
||||
|
||||
Use byte offsets in SUBREGs instead of words.
|
||||
|
||||
* alias.c (nonlocal_mentioned_p): Use subreg_regno function.
|
||||
* caller-save.c (mark_set_regs): Change callers of subreg_hard_regno
|
||||
to pass new argument.
|
||||
(add_stored_regs): Use subreg_regno_offset function.
|
||||
* calls.c (expand_call): For non-paradoxical SUBREG take endianess
|
||||
into account.
|
||||
(precompute_arguments): Use gen_lowpart_SUBREG.
|
||||
* combine.c (try_combine): Replace explicit XEXP with SUBREG_REG.
|
||||
(combine_simplify_rtx): Rework to use SUBREG_BYTE.
|
||||
(simplify_set): Rework to use SUBREG_BYTE.
|
||||
(expand_field_assignment): Use SUBREG_BYTE.
|
||||
(make_extraction): Use SUBREG_BYTE.
|
||||
(if_then_else_cond): Use SUBREG_BYTE.
|
||||
(apply_distributive_law): Use SUBREG_BYTE and fixup subreg comments.
|
||||
(gen_lowpart_for_combine): Compute full byte offset.
|
||||
* cse.c (mention_regs): Use SUBREG_BYTE.
|
||||
(remove_invalid_subreg_refs): Rework to use SUBREG_BYTE.
|
||||
(canon_hash): Use SUBREG_BYTE.
|
||||
(fold_rtx): Pass SUBREG_BYTE div UNITS_PER_WORD to operand_subword.
|
||||
(gen_lowpart_if_possible): Formatting.
|
||||
* dbxout.c (dbxout_symbol_location): Compute SUBREG hard regnos
|
||||
correctly.
|
||||
* dwarf2out.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
|
||||
(mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
|
||||
(loc_descriptor): Fixup explicit XEXP into SUBREG_REG
|
||||
* dwarfout.c (is_pseudo_reg): Fixup explicit XEXP into SUBREG_REG
|
||||
(output_mem_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
|
||||
(output_loc_descriptor): Fixup explicit XEXP into SUBREG_REG
|
||||
* emit-rtl.c (gen_rtx_SUBREG): New function, used to verify
|
||||
certain invariants about SUBREGs the compiler creates.
|
||||
(gen_lowpart_SUBREG): New function.
|
||||
(subreg_hard_regno): New function to get the final register number.
|
||||
(gen_lowpart_common): Use SUBREG_BYTE.
|
||||
(gen_imagpart): Spacing nits.
|
||||
(subreg_realpart_p): Use SUBREG_BYTE.
|
||||
(gen_highpart): Use SUBREG_BYTE.
|
||||
(subreg_lowpart_p): Always compute endian corrected goal offset,
|
||||
even at the byte level, then compare against that.
|
||||
(constant_subword): New function, pulled out all constant cases
|
||||
from operand_subword and changed second argument name to offset.
|
||||
(operand_subword): Detect non REG/SUBREG/CONCAT/MEM cases early
|
||||
and call constant_subword to do the work. Return const0_rtx if
|
||||
looking for a word outside of OP.
|
||||
(operand_subword_force): Change second arg name to offset.
|
||||
* expmed.c (store_bit_field): Use SUBREG_BYTE.
|
||||
(store_split_bit_field): Use SUBREG_BYTE.
|
||||
(extract_bit_field): Use SUBREG_BYTE.
|
||||
(extract_split_bit_field): Use SUBREG_BYTE.
|
||||
(expand_shift): Use SUBREG_BYTE.
|
||||
* expr.c (store_expr, expand_expr): Use gen_lowpart_SUBREG.
|
||||
* final.c (alter_subreg) Use subreg_hard_regno and SUBREG_BYTE.
|
||||
* flow.c (set_noop_p): Use SUBREG_BYTE.
|
||||
(mark_set_1): Remove ALTER_HARD_SUBREG. Use subreg_regno_offset instead.
|
||||
* function.c (fixup_var_refs_1): Fixup explicit XEXP into a SUBREG_REG.
|
||||
(fixup_memory_subreg): Use SUBREG_BYTE and remove byte endian
|
||||
correction code.
|
||||
(optimize_bit_field): Use SUBREG_BYTE.
|
||||
(purge_addressof_1): Use SUBREG_BYTE.
|
||||
(purge_single_hard_subreg_set): Use subreg_regno_offset function.
|
||||
(assign_params): Mark arguments SUBREG_PROMOTED_VAR_P if they are
|
||||
actually promoted by the caller and PROMOTE_FOR_CALLS_ONLY is true.
|
||||
* gengenrtl.c (special_rtx): Add SUBREG.
|
||||
* global.c (mark_reg_store): Use SUBREG_BYTE.
|
||||
(set_preference): Rework to use subreg_regno_offset and SUBREG_BYTE.
|
||||
* ifcvt (noce_emit_move_insn): Use SUBREG_BYTE.
|
||||
* integrate.c (copy_rtx_and_substitute): Use SUBREG_BYTE and make sure
|
||||
final byte offset is congruent to subreg's mode size.
|
||||
(subst_constants): Use SUBREG_BYTE.
|
||||
(mark_stores): Use subreg_regno_offset function.
|
||||
* jump.c (rtx_renumbered_equal_p, true_regnum): Use subreg_regno_offset
|
||||
function and SUBREG_BYTE.
|
||||
* local-alloc.c (combine_regs): Use subreg_regno_offset function.
|
||||
(reg_is_born): Use subreg_hard_regno.
|
||||
* recog.c (valid_replace_rtx_1): Use SUBREG_BYTE and remove byte
|
||||
endian correction code. Don't combine subregs unless resulting
|
||||
offset aligns with type. Fix subreg constant extraction for DImode.
|
||||
Simplify SUBREG of VOIDmode CONST_DOUBLE.
|
||||
(general_operand): Remove dead mode_altering_drug code.
|
||||
(indirect_operand): Use SUBREG_BYTE.
|
||||
(constrain_operands): Use subreg_regno_offset function.
|
||||
* reg-stack.c (get_true_reg): Use subreg_regno_offset function.
|
||||
* regmove.c (regmove_optimize): Use SUBREG_BYTE.
|
||||
(optimize_reg_copy_3): Use gen_lowpart_SUBREG.
|
||||
* regs.h (REG_SIZE): Allow target to override.
|
||||
(REGMODE_NATURAL_SIZE): New macro which target can override.
|
||||
* reload.c (reload_inner_reg_of_subreg): subreg_regno should be used
|
||||
on the entire subreg rtx.
|
||||
(push_reload): Use SUBREG_BYTE in comments and code.
|
||||
(find_dummy_reload): Use subreg_regno_offset. Only adjust offsets
|
||||
for hard registers inside subregs.
|
||||
(operands_match_p): Use subreg_regno_offset.
|
||||
(find_reloads): Use SUBREG_BYTE and only advance offset for subregs
|
||||
containing hard regs.
|
||||
(find_reload_toplev): Use SUBREG_BYTE. Remove byte endian
|
||||
corrections when fixing up MEM subregs.
|
||||
(find_reloads_address_1): Use SUBREG_BYTE, subreg_regno, and
|
||||
subreg_regno_offset where appropriate.
|
||||
(find_reloads_subreg_address): Use SUBREG_BYTE. Remove
|
||||
byte endian corrections when fixing up MEM subregs.
|
||||
(subst_reloads): When combining two subregs, make sure final
|
||||
offset is congruent to subreg's mode size.
|
||||
(find_replacement): Use SUBREG_BYTE and subreg_regno_offset.
|
||||
(refers_to_regno_for_reload_p): Use subreg_regno.
|
||||
(reg_overlap_mentioned_for_reload_p): Use subreg_regno_offset.
|
||||
* reload1.c (eliminate_regs) Use SUBREG_BYTE. Remove byte endian
|
||||
correction code for memory subreg fixups.
|
||||
(forget_old_reload_1): Use subreg_regno_offset.
|
||||
(choose_reload_regs): Use subreg_regno.
|
||||
(emit_input_reload_insns): Use SUBREG_BYTE.
|
||||
(reload_combine_note_store): Use subreg_regno_offset.
|
||||
(move2add_note_store): Use subreg_regno_offset.
|
||||
* resource.c (update_live_status, mark_referenced_resources): Use
|
||||
subreg_regno function.
|
||||
(mark_set_resources): Use subreg_regno function.
|
||||
* rtl.h (SUBREG_WORD): Rename to SUBREG_BYTE.
|
||||
(subreg_regno_offset, subreg_regno): Define prototypes.
|
||||
(subreg_hard_regno, constant_subword, gen_rtx_SUBREG): Newi functions.
|
||||
(gen_lowpart_SUBREG): Add prototype.
|
||||
* rtl.texi (subreg): Update to reflect new byte offset representation.
|
||||
Add mentioning of the effect that BYTES_BIG_ENDIAN has on subregs now.
|
||||
* rtlanal.c (refers_to_regno_p): Use subreg_regno.
|
||||
(reg_overlap_mentioned_p): Use subreg_regno.
|
||||
(replace_regs); Make sure final offset of combined subreg is
|
||||
congruent to size of subreg's mode.
|
||||
(subreg_regno_offset): New function.
|
||||
(subreg_regno): New function.
|
||||
* sched-vis.c (print_value): Change SUBREG_WORD to SUBREG_BYTE.
|
||||
* sdbout.c (sdbout_symbol): Compute offset using alter_subreg.
|
||||
* stmt.c (expand_anon_union_decl): Use gen_lowpart_SUBREG.
|
||||
* tm.texi (ALTER_HARD_SUBREG): Remove, it is now dead.
|
||||
(SUBREG_REGNO_OFFSET): Describe SUBREG_REGNO_OFFSET overrides.
|
||||
* config/a29k/a29k.c (gpc_reg_operand): Use subreg_regno.
|
||||
(a29k_get_reloaded_address): Use SUBREG_BYTE.
|
||||
(print_operand): Use SUBREG_BYTE.
|
||||
* config/alpha/alpha.c (print_operand_address): Use SUBREG_BYTE.
|
||||
* config/arm/arm.c (arm_reload_in_hi): Use SUBREG_BYTE.
|
||||
(arm_reload_out_hi): Use SUBREG_BYTE.
|
||||
* config/d30v/d30v.c (d30v_split_double): Use subreg_regno_offset
|
||||
instead of SUBREG_WORD.
|
||||
(d30v_print_operand_memory_reference): Use subreg_regno_offset.
|
||||
* config/dsp16xx/dsp16xx.md (extendqihi2, zero_extendqihi2): Fix
|
||||
SUBREG creation to use byte offset.
|
||||
* config/h8300/h8300.md (Unnamed HImode zero extraction and 16bit
|
||||
inverted load insns): Fix explicit rtl subregs to use byte
|
||||
offsets.
|
||||
* config/i370/i370.md (cmpstrsi, movstrsi, mulsi3, divsi3,
|
||||
udivsi3, umodsi3): Generate SUBREGs with byte offsets.
|
||||
* config/i860/i860.c (single_insn_src_p): Use SUBREG_BYTE.
|
||||
* config/i860/i860.md (mulsi3_big): Fixup explicit SUBREGs in rtl
|
||||
to use byte offsets.
|
||||
(unnamed fmlow.dd insn): Fixup SUBREGS to use byte offsets.
|
||||
* config/i960/i960.md (extendhisi2): Generate SUBREGs with byte
|
||||
offsets, also make sure it is congruent to SUBREG's mode size.
|
||||
(extendqisi2, extendqihi2, zero_extendhisi2, zero_extendqisi2,
|
||||
unnamed ldob insn): Generate SUBREGs with byte offset.
|
||||
(zero_extendqihi2): SUBREG's are byte offsets.
|
||||
* config/m68hc11/m68hc11.c (m68hc11_gen_lowpart): Use SUBREG_BYTE.
|
||||
(m68hc11_gen_highpart): Use SUBREG_BYTE.
|
||||
* config/m68k/m68k.md (zero_extendhisi2, zero_extendqihi2,
|
||||
zero-extendqisi2): Generate SUBREGs with byte offset.
|
||||
(umulsidi3, mulsidi3, subreghi1ashrdi_const32,
|
||||
subregsi1ashrdi_const32, subreg1lshrdi_const32): Fixup explicit
|
||||
subregs in rtl to use byte offsets.
|
||||
* config/m88k/m88k.md (extendsidi2): fixup subregs to use byte offset.
|
||||
* config/mips/mips.c (mips_move_1word): Use subreg_regno_offset.
|
||||
(mips_move_2words): Use subreg_regno_offset.
|
||||
(mips_secondary_reload_class): Use subreg_regno_offset.
|
||||
* config/mips/mips.md (DImode plus, minus, move, and logical op
|
||||
splits): Fixup explicit subregs in rtl to use byte offsets.
|
||||
* config/mn10200/mn10200.c (print_operand): Use subreg_regno function.
|
||||
* config/mn10300/mn10300.c (print_operand): Use subreg_regno function.
|
||||
* config/ns32k/ns32k.md (udivmoddisi4): Fix explicit subregs in
|
||||
rtl to use byte offsets.
|
||||
* config/pa/pa.c (emit_move_sequence): Use SUBREG_BYTE.
|
||||
* config/pa/pa.md (floatunssisf2, floatunssidf2, mulsi3): fix explicit
|
||||
subregs to use byte offsets.
|
||||
* config/pdp11/pdp11.md (zero_extendhisi2, modhi3, modhi3+1):
|
||||
Fixup explicit subregs in rtl to use byte offsets.
|
||||
* config/romp/romp.c (memory_offset_in_range_p): Use SUBREG_BYTE
|
||||
and remove byte endian correction code.
|
||||
* config/sh/sh.c (output_movedouble): Use subreg_regno.
|
||||
(gen_ashift_hi): Use SUBREG_BYTE.
|
||||
(regs_used): Use subreg_regno_offset.
|
||||
(machine_dependent_reorg): Use subreg_regno_offset.
|
||||
* config/sh/sh.h (INDEX_REGISTER_RTX_P): Use SUBREG_BYTE.
|
||||
* config/sh/sh.md (DImode and DFmode move splits): Use subreg_regno.
|
||||
(movdf_i4): Subregs are byte offsets now.
|
||||
* config/sparc/sparc.c (ultra_find_type): Use SUBREG_BYTE.
|
||||
* config/sparc/sparc.h (ALTER_HARD_SUBREG): Removed.
|
||||
(REGMODE_NATURAL_SIZE): Override.
|
||||
(REG_SIZE): For SUBREG check float mode on SUBREG_REG's mode.
|
||||
* config/sparc/sparc.md (TFmode move splits): Generate SUBREGs
|
||||
with byte offsets.
|
||||
(zero_extendhisi2, zero_extendqidi2_insn, extendhisi2,
|
||||
extendqihi2, sign_extendqihi2_insn, sign_extendqisi2_insn,
|
||||
extendqidi2): Generate SUBREGs with byte offsets, also make sure
|
||||
it is congruent to SUBREG's mode size.
|
||||
(smulsi3_highpart_v8plus): Fix explicit subregs in rtl to use byte
|
||||
offsets.
|
||||
(cmp_siqi_trunc, cmp_siqi_trunc_set, cmp_diqi_trunc,
|
||||
cmp_diqi_trunc_set, lshrdi3_v8plus+1, lshrdi3_v8plus+2,
|
||||
lshrdi3_v8plus+3, lshrdi3_v8plus+4): Use proper
|
||||
SUBREG_BYTE offset for non-paradoxical subregs in patterns.
|
||||
* config/v850/v850.c (print_operand, output_move_double): Use
|
||||
subreg_regno function.
|
||||
|
||||
2001-04-03 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* configure.in (target_subdir): Use target_alias, not target.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++)
|
||||
|
|
25
gcc/calls.c
25
gcc/calls.c
|
@ -1462,6 +1462,8 @@ precompute_arguments (flags, num_actuals, args)
|
|||
if ((flags & (ECF_CONST | ECF_PURE))
|
||||
|| calls_function (args[i].tree_value, !ACCUMULATE_OUTGOING_ARGS))
|
||||
{
|
||||
enum machine_mode mode;
|
||||
|
||||
/* If this is an addressable type, we cannot pre-evaluate it. */
|
||||
if (TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)))
|
||||
abort ();
|
||||
|
@ -1481,11 +1483,11 @@ precompute_arguments (flags, num_actuals, args)
|
|||
args[i].initial_value = args[i].value
|
||||
= protect_from_queue (args[i].value, 0);
|
||||
|
||||
if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) != args[i].mode)
|
||||
mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
|
||||
if (mode != args[i].mode)
|
||||
{
|
||||
args[i].value
|
||||
= convert_modes (args[i].mode,
|
||||
TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||
= convert_modes (args[i].mode, mode,
|
||||
args[i].value, args[i].unsignedp);
|
||||
#ifdef PROMOTE_FOR_CALL_ONLY
|
||||
/* CSE will replace this only if it contains args[i].value
|
||||
|
@ -1495,8 +1497,7 @@ precompute_arguments (flags, num_actuals, args)
|
|||
&& GET_MODE_CLASS (args[i].mode) == MODE_INT)
|
||||
{
|
||||
args[i].initial_value
|
||||
= gen_rtx_SUBREG (TYPE_MODE (TREE_TYPE (args[i].tree_value)),
|
||||
args[i].value, 0);
|
||||
= gen_lowpart_SUBREG (mode, args[i].value);
|
||||
SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
|
||||
SUBREG_PROMOTED_UNSIGNED_P (args[i].initial_value)
|
||||
= args[i].unsignedp;
|
||||
|
@ -3272,13 +3273,25 @@ expand_call (exp, target, ignore)
|
|||
{
|
||||
tree type = TREE_TYPE (exp);
|
||||
int unsignedp = TREE_UNSIGNED (type);
|
||||
int offset = 0;
|
||||
|
||||
/* If we don't promote as expected, something is wrong. */
|
||||
if (GET_MODE (target)
|
||||
!= promote_mode (type, TYPE_MODE (type), &unsignedp, 1))
|
||||
abort ();
|
||||
|
||||
target = gen_rtx_SUBREG (TYPE_MODE (type), target, 0);
|
||||
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
|
||||
&& GET_MODE_SIZE (GET_MODE (target))
|
||||
> GET_MODE_SIZE (TYPE_MODE (type)))
|
||||
{
|
||||
offset = GET_MODE_SIZE (GET_MODE (target))
|
||||
- GET_MODE_SIZE (TYPE_MODE (type));
|
||||
if (! BYTES_BIG_ENDIAN)
|
||||
offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
|
||||
else if (! WORDS_BIG_ENDIAN)
|
||||
offset %= UNITS_PER_WORD;
|
||||
}
|
||||
target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
|
||||
SUBREG_PROMOTED_VAR_P (target) = 1;
|
||||
SUBREG_PROMOTED_UNSIGNED_P (target) = unsignedp;
|
||||
}
|
||||
|
|
165
gcc/combine.c
165
gcc/combine.c
|
@ -2249,7 +2249,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
|
|||
be written as a ZERO_EXTEND. */
|
||||
if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
|
||||
SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
|
||||
XEXP (*split, 0)));
|
||||
SUBREG_REG (*split)));
|
||||
#endif
|
||||
|
||||
newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
|
||||
|
@ -3773,27 +3773,17 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
|
|||
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
|
||||
{
|
||||
rtx inner = SUBREG_REG (x);
|
||||
int endian_offset = 0;
|
||||
int offset = SUBREG_BYTE (x);
|
||||
/* Don't change the mode of the MEM
|
||||
if that would change the meaning of the address. */
|
||||
if (MEM_VOLATILE_P (SUBREG_REG (x))
|
||||
|| mode_dependent_address_p (XEXP (inner, 0)))
|
||||
return gen_rtx_CLOBBER (mode, const0_rtx);
|
||||
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
{
|
||||
if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
|
||||
endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (mode);
|
||||
if (GET_MODE_SIZE (GET_MODE (inner)) < UNITS_PER_WORD)
|
||||
endian_offset -= (UNITS_PER_WORD
|
||||
- GET_MODE_SIZE (GET_MODE (inner)));
|
||||
}
|
||||
/* Note if the plus_constant doesn't make a valid address
|
||||
then this combination won't be accepted. */
|
||||
x = gen_rtx_MEM (mode,
|
||||
plus_constant (XEXP (inner, 0),
|
||||
(SUBREG_WORD (x) * UNITS_PER_WORD
|
||||
+ endian_offset)));
|
||||
plus_constant (XEXP (inner, 0), offset));
|
||||
MEM_COPY_ATTRIBUTES (x, inner);
|
||||
return x;
|
||||
}
|
||||
|
@ -3806,12 +3796,58 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
|
|||
or not at all if changing back to starting mode. */
|
||||
if (GET_CODE (SUBREG_REG (x)) == SUBREG)
|
||||
{
|
||||
if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x)))
|
||||
&& SUBREG_WORD (x) == 0 && SUBREG_WORD (SUBREG_REG (x)) == 0)
|
||||
return SUBREG_REG (SUBREG_REG (x));
|
||||
int final_offset;
|
||||
enum machine_mode outer_mode, inner_mode;
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}")
|
||||
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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))]
|
||||
""
|
||||
"*
|
||||
{
|
||||
|
|
|
@ -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)))]
|
||||
""
|
||||
"")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.... */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
41
gcc/cse.c
41
gcc/cse.c
|
@ -1220,11 +1220,11 @@ mention_regs (x)
|
|||
/* If reg_tick has been incremented more than once since
|
||||
reg_in_table was last set, that means that the entire
|
||||
register has been set before, so discard anything memorized
|
||||
for the entrire register, including all SUBREG expressions. */
|
||||
for the entire register, including all SUBREG expressions. */
|
||||
if (REG_IN_TABLE (i) != REG_TICK (i) - 1)
|
||||
remove_invalid_refs (i);
|
||||
else
|
||||
remove_invalid_subreg_refs (i, SUBREG_WORD (x), GET_MODE (x));
|
||||
remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
|
||||
}
|
||||
|
||||
REG_IN_TABLE (i) = REG_TICK (i);
|
||||
|
@ -2004,32 +2004,31 @@ remove_invalid_refs (regno)
|
|||
}
|
||||
}
|
||||
|
||||
/* Likewise for a subreg with subreg_reg WORD and mode MODE. */
|
||||
/* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
|
||||
and mode MODE. */
|
||||
static void
|
||||
remove_invalid_subreg_refs (regno, word, mode)
|
||||
remove_invalid_subreg_refs (regno, offset, mode)
|
||||
unsigned int regno;
|
||||
unsigned int word;
|
||||
unsigned int offset;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
unsigned int i;
|
||||
struct table_elt *p, *next;
|
||||
unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
|
||||
unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++)
|
||||
for (p = table[i]; p; p = next)
|
||||
{
|
||||
rtx exp;
|
||||
rtx exp = p->exp;
|
||||
next = p->next_same_hash;
|
||||
|
||||
exp = p->exp;
|
||||
if (GET_CODE (p->exp) != REG
|
||||
if (GET_CODE (exp) != REG
|
||||
&& (GET_CODE (exp) != SUBREG
|
||||
|| GET_CODE (SUBREG_REG (exp)) != REG
|
||||
|| REGNO (SUBREG_REG (exp)) != regno
|
||||
|| (((SUBREG_WORD (exp)
|
||||
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1) / UNITS_PER_WORD)
|
||||
>= word)
|
||||
&& SUBREG_WORD (exp) <= end))
|
||||
|| (((SUBREG_BYTE (exp)
|
||||
+ (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
|
||||
&& SUBREG_BYTE (exp) <= end))
|
||||
&& refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
|
||||
remove_from_table (p, i);
|
||||
}
|
||||
|
@ -2302,7 +2301,8 @@ canon_hash (x, mode)
|
|||
if (GET_CODE (SUBREG_REG (x)) == REG)
|
||||
{
|
||||
hash += (((unsigned) SUBREG << 7)
|
||||
+ REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
|
||||
+ REGNO (SUBREG_REG (x))
|
||||
+ (SUBREG_BYTE (x) / UNITS_PER_WORD));
|
||||
return hash;
|
||||
}
|
||||
break;
|
||||
|
@ -3413,7 +3413,8 @@ fold_rtx (x, insn)
|
|||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
|
||||
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
|
||||
new = operand_subword (folded_arg0, SUBREG_WORD (x), 0,
|
||||
new = operand_subword (folded_arg0,
|
||||
(SUBREG_BYTE (x) / UNITS_PER_WORD), 0,
|
||||
GET_MODE (SUBREG_REG (x)));
|
||||
if (new == 0 && subreg_lowpart_p (x))
|
||||
new = gen_lowpart_if_possible (mode, folded_arg0);
|
||||
|
@ -4393,10 +4394,12 @@ gen_lowpart_if_possible (mode, x)
|
|||
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
|
||||
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
/* Adjust the address so that the address-after-the-data is
|
||||
unchanged. */
|
||||
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
|
||||
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
|
||||
{
|
||||
/* Adjust the address so that the address-after-the-data is
|
||||
unchanged. */
|
||||
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
|
||||
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
|
||||
}
|
||||
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
|
||||
if (! memory_address_p (mode, XEXP (new, 0)))
|
||||
return 0;
|
||||
|
|
13
gcc/dbxout.c
13
gcc/dbxout.c
|
@ -2024,20 +2024,15 @@ dbxout_symbol_location (decl, type, suffix, home)
|
|||
else if (GET_CODE (home) == SUBREG)
|
||||
{
|
||||
rtx value = home;
|
||||
int offset = 0;
|
||||
|
||||
while (GET_CODE (value) == SUBREG)
|
||||
{
|
||||
offset += SUBREG_WORD (value);
|
||||
value = SUBREG_REG (value);
|
||||
}
|
||||
value = SUBREG_REG (value);
|
||||
if (GET_CODE (value) == REG)
|
||||
{
|
||||
regno = REGNO (value);
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
|
||||
return 0;
|
||||
regno += offset;
|
||||
}
|
||||
alter_subreg (home);
|
||||
regno = REGNO (alter_subreg (home));
|
||||
}
|
||||
|
||||
/* The kind-of-variable letter depends on where
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
592
gcc/emit-rtl.c
592
gcc/emit-rtl.c
|
@ -348,6 +348,55 @@ gen_rtx_MEM (mode, addr)
|
|||
|
||||
return rt;
|
||||
}
|
||||
|
||||
rtx
|
||||
gen_rtx_SUBREG (mode, reg, offset)
|
||||
enum machine_mode mode;
|
||||
rtx reg;
|
||||
int offset;
|
||||
{
|
||||
/* This is the most common failure type.
|
||||
Catch it early so we can see who does it. */
|
||||
if ((offset % GET_MODE_SIZE (mode)) != 0)
|
||||
abort ();
|
||||
|
||||
/* This check isn't usable right now because combine will
|
||||
throw arbitrary crap like a CALL into a SUBREG in
|
||||
gen_lowpart_for_combine so we must just eat it. */
|
||||
#if 0
|
||||
/* Check for this too. */
|
||||
if (offset >= GET_MODE_SIZE (GET_MODE (reg)))
|
||||
abort ();
|
||||
#endif
|
||||
return gen_rtx_fmt_ei (SUBREG, mode, reg, offset);
|
||||
}
|
||||
|
||||
/* Generate a SUBREG representing the least-significant part
|
||||
* of REG if MODE is smaller than mode of REG, otherwise
|
||||
* paradoxical SUBREG. */
|
||||
rtx
|
||||
gen_lowpart_SUBREG (mode, reg)
|
||||
enum machine_mode mode;
|
||||
rtx reg;
|
||||
{
|
||||
enum machine_mode inmode;
|
||||
int offset;
|
||||
|
||||
inmode = GET_MODE (reg);
|
||||
if (inmode == VOIDmode)
|
||||
inmode = mode;
|
||||
offset = 0;
|
||||
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (inmode)
|
||||
&& (WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN))
|
||||
{
|
||||
offset = GET_MODE_SIZE (inmode) - GET_MODE_SIZE (mode);
|
||||
if (! BYTES_BIG_ENDIAN)
|
||||
offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
|
||||
else if (! WORDS_BIG_ENDIAN)
|
||||
offset %= UNITS_PER_WORD;
|
||||
}
|
||||
return gen_rtx_SUBREG (mode, reg, offset);
|
||||
}
|
||||
|
||||
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
|
||||
**
|
||||
|
@ -650,6 +699,38 @@ get_first_label_num ()
|
|||
return first_label_num;
|
||||
}
|
||||
|
||||
/* Return the final regno of X, which is a SUBREG of a hard
|
||||
register. */
|
||||
int
|
||||
subreg_hard_regno (x, check_mode)
|
||||
register rtx x;
|
||||
int check_mode;
|
||||
{
|
||||
enum machine_mode mode = GET_MODE (x);
|
||||
unsigned int byte_offset, base_regno, final_regno;
|
||||
rtx reg = SUBREG_REG (x);
|
||||
|
||||
/* This is where we attempt to catch illegal subregs
|
||||
created by the compiler. */
|
||||
if (GET_CODE (x) != SUBREG
|
||||
|| GET_CODE (reg) != REG)
|
||||
abort ();
|
||||
base_regno = REGNO (reg);
|
||||
if (base_regno >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
if (! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
|
||||
abort ();
|
||||
|
||||
/* Catch non-congruent offsets too. */
|
||||
byte_offset = SUBREG_BYTE (x);
|
||||
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
|
||||
abort ();
|
||||
|
||||
final_regno = subreg_regno (x);
|
||||
|
||||
return final_regno;
|
||||
}
|
||||
|
||||
/* Return a value representing some low-order bits of X, where the number
|
||||
of low-order bits is given by MODE. Note that no conversion is done
|
||||
between floating-point and fixed-point values, rather, the bit
|
||||
|
@ -666,22 +747,29 @@ gen_lowpart_common (mode, x)
|
|||
enum machine_mode mode;
|
||||
register rtx x;
|
||||
{
|
||||
int word = 0;
|
||||
int msize = GET_MODE_SIZE (mode);
|
||||
int xsize = GET_MODE_SIZE (GET_MODE (x));
|
||||
int offset = 0;
|
||||
|
||||
if (GET_MODE (x) == mode)
|
||||
return x;
|
||||
|
||||
/* MODE must occupy no more words than the mode of X. */
|
||||
if (GET_MODE (x) != VOIDmode
|
||||
&& ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
|
||||
> ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
|
||||
/ UNITS_PER_WORD)))
|
||||
&& ((msize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
|
||||
> ((xsize + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
|
||||
return 0;
|
||||
|
||||
if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
|
||||
word = ((GET_MODE_SIZE (GET_MODE (x))
|
||||
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
|
||||
/ UNITS_PER_WORD);
|
||||
if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
|
||||
&& xsize > msize)
|
||||
{
|
||||
int difference = xsize - msize;
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
offset += difference % UNITS_PER_WORD;
|
||||
}
|
||||
|
||||
if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
|
||||
&& (GET_MODE_CLASS (mode) == MODE_INT
|
||||
|
@ -703,39 +791,40 @@ gen_lowpart_common (mode, x)
|
|||
return gen_rtx_fmt_e (GET_CODE (x), mode, XEXP (x, 0));
|
||||
}
|
||||
else if (GET_CODE (x) == SUBREG
|
||||
&& (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
|
||||
|| GET_MODE_SIZE (mode) <= UNITS_PER_WORD
|
||||
&& (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
|
||||
|| GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
|
||||
return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
|
||||
? SUBREG_REG (x)
|
||||
: gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_WORD (x) + word));
|
||||
{
|
||||
int final_offset;
|
||||
|
||||
if (GET_MODE (SUBREG_REG (x)) == mode && subreg_lowpart_p (x))
|
||||
return SUBREG_REG (x);
|
||||
|
||||
/* When working with SUBREGs the rule is that the byte
|
||||
offset must be a multiple of the SUBREG's mode. */
|
||||
final_offset = SUBREG_BYTE (x) + offset;
|
||||
final_offset = (final_offset / GET_MODE_SIZE (mode));
|
||||
final_offset = (final_offset * GET_MODE_SIZE (mode));
|
||||
return gen_rtx_SUBREG (mode, SUBREG_REG (x), final_offset);
|
||||
}
|
||||
else if (GET_CODE (x) == REG)
|
||||
{
|
||||
/* Let the backend decide how many registers to skip. This is needed
|
||||
in particular for Sparc64 where fp regs are smaller than a word. */
|
||||
/* ??? Note that subregs are now ambiguous, in that those against
|
||||
pseudos are sized by the Word Size, while those against hard
|
||||
regs are sized by the underlying register size. Better would be
|
||||
to always interpret the subreg offset parameter as bytes or bits. */
|
||||
/* 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 ();
|
||||
|
||||
|
|
33
gcc/expmed.c
33
gcc/expmed.c
|
@ -261,7 +261,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
|
|||
meaningful at a much higher level; when structures are copied
|
||||
between memory and regs, the higher-numbered regs
|
||||
always get higher addresses. */
|
||||
offset += SUBREG_WORD (op0);
|
||||
offset += (SUBREG_BYTE (op0) / UNITS_PER_WORD);
|
||||
/* We used to adjust BITPOS here, but now we do the whole adjustment
|
||||
right after the loop. */
|
||||
op0 = SUBREG_REG (op0);
|
||||
|
@ -311,7 +311,9 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
|
|||
abort ();
|
||||
}
|
||||
if (GET_CODE (op0) == REG)
|
||||
op0 = gen_rtx_SUBREG (fieldmode, op0, offset);
|
||||
op0 = gen_rtx_SUBREG (fieldmode, op0,
|
||||
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
|
||||
+ (offset * UNITS_PER_WORD));
|
||||
else
|
||||
op0 = change_address (op0, fieldmode,
|
||||
plus_constant (XEXP (op0, 0), offset));
|
||||
|
@ -373,7 +375,10 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
|
|||
}
|
||||
|
||||
emit_insn (GEN_FCN (icode)
|
||||
(gen_rtx_SUBREG (fieldmode, op0, offset), value));
|
||||
(gen_rtx_SUBREG (fieldmode, op0,
|
||||
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
|
||||
+ (offset * UNITS_PER_WORD)),
|
||||
value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -447,7 +452,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
|
|||
abort ();
|
||||
}
|
||||
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
|
||||
op0, offset);
|
||||
op0, (offset * UNITS_PER_WORD));
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
|
@ -550,7 +555,7 @@ store_bit_field (str_rtx, bitsize, bitnum, fieldmode, value, align, total_size)
|
|||
if (GET_CODE (xop0) == SUBREG)
|
||||
/* We can't just change the mode, because this might clobber op0,
|
||||
and we will need the original value of op0 if insv fails. */
|
||||
xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_WORD (xop0));
|
||||
xop0 = gen_rtx_SUBREG (maxmode, SUBREG_REG (xop0), SUBREG_BYTE (xop0));
|
||||
if (GET_CODE (xop0) == REG && GET_MODE (xop0) != maxmode)
|
||||
xop0 = gen_rtx_SUBREG (maxmode, xop0, 0);
|
||||
|
||||
|
@ -910,8 +915,8 @@ store_split_bit_field (op0, bitsize, bitpos, value, align)
|
|||
the current word starting from the base register. */
|
||||
if (GET_CODE (op0) == SUBREG)
|
||||
{
|
||||
word = operand_subword_force (SUBREG_REG (op0),
|
||||
SUBREG_WORD (op0) + offset,
|
||||
int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
|
||||
word = operand_subword_force (SUBREG_REG (op0), word_offset,
|
||||
GET_MODE (SUBREG_REG (op0)));
|
||||
offset = 0;
|
||||
}
|
||||
|
@ -1008,7 +1013,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
|
|||
int outer_size = GET_MODE_BITSIZE (GET_MODE (op0));
|
||||
int inner_size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)));
|
||||
|
||||
offset += SUBREG_WORD (op0);
|
||||
offset += SUBREG_BYTE (op0) / UNITS_PER_WORD;
|
||||
|
||||
inner_size = MIN (inner_size, BITS_PER_WORD);
|
||||
|
||||
|
@ -1104,7 +1109,9 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
|
|||
abort ();
|
||||
}
|
||||
if (GET_CODE (op0) == REG)
|
||||
op0 = gen_rtx_SUBREG (mode1, op0, offset);
|
||||
op0 = gen_rtx_SUBREG (mode1, op0,
|
||||
(bitnum % BITS_PER_WORD) / BITS_PER_UNIT
|
||||
+ (offset * UNITS_PER_WORD));
|
||||
else
|
||||
op0 = change_address (op0, mode1,
|
||||
plus_constant (XEXP (op0, 0), offset));
|
||||
|
@ -1213,7 +1220,7 @@ extract_bit_field (str_rtx, bitsize, bitnum, unsignedp,
|
|||
if (GET_CODE (op0) != REG)
|
||||
op0 = copy_to_reg (op0);
|
||||
op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
|
||||
op0, offset);
|
||||
op0, (offset * UNITS_PER_WORD));
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
|
@ -1808,8 +1815,8 @@ extract_split_bit_field (op0, bitsize, bitpos, unsignedp, align)
|
|||
the current word starting from the base register. */
|
||||
if (GET_CODE (op0) == SUBREG)
|
||||
{
|
||||
word = operand_subword_force (SUBREG_REG (op0),
|
||||
SUBREG_WORD (op0) + offset,
|
||||
int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
|
||||
word = operand_subword_force (SUBREG_REG (op0), word_offset,
|
||||
GET_MODE (SUBREG_REG (op0)));
|
||||
offset = 0;
|
||||
}
|
||||
|
@ -1928,7 +1935,7 @@ expand_shift (code, mode, shifted, amount, target, unsignedp)
|
|||
op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
|
||||
% GET_MODE_BITSIZE (mode));
|
||||
else if (GET_CODE (op1) == SUBREG
|
||||
&& SUBREG_WORD (op1) == 0)
|
||||
&& SUBREG_BYTE (op1) == 0)
|
||||
op1 = SUBREG_REG (op1);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
23
gcc/final.c
23
gcc/final.c
|
@ -3119,20 +3119,8 @@ alter_subreg (x)
|
|||
|
||||
if (GET_CODE (y) == REG)
|
||||
{
|
||||
int regno;
|
||||
/* If the word size is larger than the size of this register,
|
||||
adjust the register number to compensate. */
|
||||
/* ??? Note that this just catches stragglers created by/for
|
||||
integrate. It would be better if we either caught these
|
||||
earlier, or kept _all_ subregs until now and eliminate
|
||||
gen_lowpart and friends. */
|
||||
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);
|
||||
|
|
11
gcc/flow.c
11
gcc/flow.c
|
@ -3088,7 +3088,7 @@ set_noop_p (set)
|
|||
|
||||
if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
|
||||
{
|
||||
if (SUBREG_WORD (src) != SUBREG_WORD (dst))
|
||||
if (SUBREG_BYTE (src) != SUBREG_BYTE (dst))
|
||||
return 0;
|
||||
src = SUBREG_REG (src);
|
||||
dst = SUBREG_REG (dst);
|
||||
|
@ -4669,12 +4669,9 @@ mark_set_1 (pbi, code, reg, cond, insn, flags)
|
|||
regno_last = regno_first = REGNO (SUBREG_REG (reg));
|
||||
if (regno_first < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
#ifdef ALTER_HARD_SUBREG
|
||||
regno_first = ALTER_HARD_SUBREG (outer_mode, SUBREG_WORD (reg),
|
||||
inner_mode, regno_first);
|
||||
#else
|
||||
regno_first += SUBREG_WORD (reg);
|
||||
#endif
|
||||
regno_first += subreg_regno_offset (regno_first, inner_mode,
|
||||
SUBREG_BYTE (reg),
|
||||
outer_mode);
|
||||
regno_last = (regno_first
|
||||
+ HARD_REGNO_NREGS (regno_first, outer_mode) - 1);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
33
gcc/global.c
33
gcc/global.c
|
@ -1422,17 +1422,8 @@ mark_reg_store (reg, setter, data)
|
|||
{
|
||||
register int regno;
|
||||
|
||||
/* WORD is which word of a multi-register group is being stored.
|
||||
For the case where the store is actually into a SUBREG of REG.
|
||||
Except we don't use it; I believe the entire REG needs to be
|
||||
made live. */
|
||||
int word = 0;
|
||||
|
||||
if (GET_CODE (reg) == SUBREG)
|
||||
{
|
||||
word = SUBREG_WORD (reg);
|
||||
reg = SUBREG_REG (reg);
|
||||
}
|
||||
reg = SUBREG_REG (reg);
|
||||
|
||||
if (GET_CODE (reg) != REG)
|
||||
return;
|
||||
|
@ -1456,7 +1447,7 @@ mark_reg_store (reg, setter, data)
|
|||
}
|
||||
|
||||
if (reg_renumber[regno] >= 0)
|
||||
regno = reg_renumber[regno] /* + word */;
|
||||
regno = reg_renumber[regno];
|
||||
|
||||
/* Handle hardware regs (and pseudos allocated to hard regs). */
|
||||
if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
|
||||
|
@ -1606,7 +1597,15 @@ set_preference (dest, src)
|
|||
else if (GET_CODE (src) == SUBREG && GET_CODE (SUBREG_REG (src)) == REG)
|
||||
{
|
||||
src_regno = REGNO (SUBREG_REG (src));
|
||||
offset += SUBREG_WORD (src);
|
||||
|
||||
if (REGNO (SUBREG_REG (src)) < FIRST_PSEUDO_REGISTER)
|
||||
offset += subreg_regno_offset (REGNO (SUBREG_REG (src)),
|
||||
GET_MODE (SUBREG_REG (src)),
|
||||
SUBREG_BYTE (src),
|
||||
GET_MODE (src));
|
||||
else
|
||||
offset += (SUBREG_BYTE (src)
|
||||
/ REGMODE_NATURAL_SIZE (GET_MODE (src)));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
@ -1616,7 +1615,15 @@ set_preference (dest, src)
|
|||
else if (GET_CODE (dest) == SUBREG && GET_CODE (SUBREG_REG (dest)) == REG)
|
||||
{
|
||||
dest_regno = REGNO (SUBREG_REG (dest));
|
||||
offset -= SUBREG_WORD (dest);
|
||||
|
||||
if (REGNO (SUBREG_REG (dest)) < FIRST_PSEUDO_REGISTER)
|
||||
offset -= subreg_regno_offset (REGNO (SUBREG_REG (dest)),
|
||||
GET_MODE (SUBREG_REG (dest)),
|
||||
SUBREG_BYTE (dest),
|
||||
GET_MODE (dest));
|
||||
else
|
||||
offset -= (SUBREG_BYTE (dest)
|
||||
/ REGMODE_NATURAL_SIZE (GET_MODE (dest)));
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
28
gcc/jump.c
28
gcc/jump.c
|
@ -3543,7 +3543,7 @@ rtx_renumbered_equal_p (x, y)
|
|||
&& GET_CODE (SUBREG_REG (y)) == REG)))
|
||||
{
|
||||
int reg_x = -1, reg_y = -1;
|
||||
int word_x = 0, word_y = 0;
|
||||
int byte_x = 0, byte_y = 0;
|
||||
|
||||
if (GET_MODE (x) != GET_MODE (y))
|
||||
return 0;
|
||||
|
@ -3556,15 +3556,17 @@ rtx_renumbered_equal_p (x, y)
|
|||
if (code == SUBREG)
|
||||
{
|
||||
reg_x = REGNO (SUBREG_REG (x));
|
||||
word_x = SUBREG_WORD (x);
|
||||
byte_x = SUBREG_BYTE (x);
|
||||
|
||||
if (reg_renumber[reg_x] >= 0)
|
||||
{
|
||||
reg_x = reg_renumber[reg_x] + word_x;
|
||||
word_x = 0;
|
||||
reg_x = subreg_regno_offset (reg_renumber[reg_x],
|
||||
GET_MODE (SUBREG_REG (x)),
|
||||
byte_x,
|
||||
GET_MODE (x));
|
||||
byte_x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
reg_x = REGNO (x);
|
||||
|
@ -3575,15 +3577,17 @@ rtx_renumbered_equal_p (x, y)
|
|||
if (GET_CODE (y) == SUBREG)
|
||||
{
|
||||
reg_y = REGNO (SUBREG_REG (y));
|
||||
word_y = SUBREG_WORD (y);
|
||||
byte_y = SUBREG_BYTE (y);
|
||||
|
||||
if (reg_renumber[reg_y] >= 0)
|
||||
{
|
||||
reg_y = reg_renumber[reg_y];
|
||||
word_y = 0;
|
||||
reg_y = subreg_regno_offset (reg_renumber[reg_y],
|
||||
GET_MODE (SUBREG_REG (y)),
|
||||
byte_y,
|
||||
GET_MODE (y));
|
||||
byte_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
reg_y = REGNO (y);
|
||||
|
@ -3591,7 +3595,7 @@ rtx_renumbered_equal_p (x, y)
|
|||
reg_y = reg_renumber[reg_y];
|
||||
}
|
||||
|
||||
return reg_x >= 0 && reg_x == reg_y && word_x == word_y;
|
||||
return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
|
||||
}
|
||||
|
||||
/* Now we have disposed of all the cases
|
||||
|
@ -3722,7 +3726,9 @@ true_regnum (x)
|
|||
{
|
||||
int base = true_regnum (SUBREG_REG (x));
|
||||
if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
|
||||
return SUBREG_WORD (x) + base;
|
||||
return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
|
||||
GET_MODE (SUBREG_REG (x)),
|
||||
SUBREG_BYTE (x), GET_MODE (x));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
150
gcc/recog.c
150
gcc/recog.c
|
@ -517,13 +517,15 @@ validate_replace_rtx_1 (loc, from, to, object)
|
|||
if (GET_CODE (XEXP (x, 0)) == SUBREG)
|
||||
{
|
||||
if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) <= UNITS_PER_WORD)
|
||||
to = operand_subword (to, SUBREG_WORD (XEXP (x, 0)),
|
||||
to = operand_subword (to,
|
||||
(SUBREG_BYTE (XEXP (x, 0))
|
||||
/ UNITS_PER_WORD),
|
||||
0, GET_MODE (from));
|
||||
else if (GET_MODE_CLASS (GET_MODE (from)) == MODE_INT
|
||||
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
|
||||
<= HOST_BITS_PER_WIDE_INT))
|
||||
{
|
||||
int i = SUBREG_WORD (XEXP (x, 0)) * BITS_PER_WORD;
|
||||
int i = SUBREG_BYTE (XEXP (x, 0)) * BITS_PER_UNIT;
|
||||
HOST_WIDE_INT valh;
|
||||
unsigned HOST_WIDE_INT vall;
|
||||
|
||||
|
@ -569,26 +571,21 @@ validate_replace_rtx_1 (loc, from, to, object)
|
|||
break;
|
||||
|
||||
case SUBREG:
|
||||
/* In case we are replacing by constant, attempt to simplify it to non-SUBREG
|
||||
expression. We can't do this later, since the information about inner mode
|
||||
may be lost. */
|
||||
/* In case we are replacing by constant, attempt to simplify it to
|
||||
non-SUBREG expression. We can't do this later, since the information
|
||||
about inner mode may be lost. */
|
||||
if (CONSTANT_P (to) && rtx_equal_p (SUBREG_REG (x), from))
|
||||
{
|
||||
if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
|
||||
&& GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD
|
||||
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
20
gcc/regs.h
20
gcc/regs.h
|
@ -24,12 +24,28 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
|
||||
|
||||
/* Get the number of consecutive hard regs required to hold the REG rtx R.
|
||||
/* Get the number of consecutive hard regs required to hold the REG or
|
||||
SUBREG rtx R.
|
||||
When something may be an explicit hard reg, REG_SIZE is the only
|
||||
valid way to get this value. You cannot get it from the regno. */
|
||||
valid way to get this value. You cannot get it from the regno.
|
||||
|
||||
A target may override this definition, the case where you would do
|
||||
this is where there are registers which are smaller than WORD_SIZE
|
||||
such as the SFmode registers on sparc64. */
|
||||
|
||||
#ifndef REG_SIZE
|
||||
#define REG_SIZE(R) \
|
||||
((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
||||
#endif
|
||||
|
||||
/* When you only have the mode of a pseudo register before it has a hard
|
||||
register chosen for it, this reports the size of each hard register
|
||||
a pseudo in such a mode would get allocated to. Like REG_SIZE, a
|
||||
target may override this. */
|
||||
|
||||
#ifndef REGMODE_NATURAL_SIZE
|
||||
#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
|
||||
#endif
|
||||
|
||||
#ifndef SMALL_REGISTER_CLASSES
|
||||
#define SMALL_REGISTER_CLASSES 0
|
||||
|
|
165
gcc/reload.c
165
gcc/reload.c
|
@ -791,7 +791,7 @@ reload_inner_reg_of_subreg (x, mode)
|
|||
return 0;
|
||||
|
||||
/* If INNER is not ok for MODE, then INNER will need reloading. */
|
||||
if (! HARD_REGNO_MODE_OK (REGNO (inner) + SUBREG_WORD (x), mode))
|
||||
if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
|
||||
return 1;
|
||||
|
||||
/* If the outer part is a word or smaller, INNER larger than a
|
||||
|
@ -938,13 +938,12 @@ push_reload (in, out, inloc, outloc, class,
|
|||
|
||||
Finally, reload the inner expression if it is a register that is in
|
||||
the class whose registers cannot be referenced in a different size
|
||||
and M1 is not the same size as M2. If SUBREG_WORD is nonzero, we
|
||||
and M1 is not the same size as M2. If SUBREG_BYTE is nonzero, we
|
||||
cannot reload just the inside since we might end up with the wrong
|
||||
register class. But if it is inside a STRICT_LOW_PART, we have
|
||||
no choice, so we hope we do get the right register class there. */
|
||||
|
||||
if (in != 0 && GET_CODE (in) == SUBREG
|
||||
&& (SUBREG_WORD (in) == 0 || strict_low)
|
||||
#ifdef CLASS_CANNOT_CHANGE_MODE
|
||||
&& (class != CLASS_CANNOT_CHANGE_MODE
|
||||
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
|
||||
|
@ -978,7 +977,7 @@ push_reload (in, out, inloc, outloc, class,
|
|||
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
|
||||
/* The case where out is nonzero
|
||||
is handled differently in the following statement. */
|
||||
&& (out == 0 || SUBREG_WORD (in) == 0)
|
||||
&& (out == 0 || SUBREG_BYTE (in) == 0)
|
||||
&& ((GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
|
||||
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
|
||||
> UNITS_PER_WORD)
|
||||
|
@ -986,9 +985,7 @@ push_reload (in, out, inloc, outloc, class,
|
|||
/ UNITS_PER_WORD)
|
||||
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
|
||||
GET_MODE (SUBREG_REG (in)))))
|
||||
|| ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (in))
|
||||
+ SUBREG_WORD (in)),
|
||||
inmode)))
|
||||
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
|
||||
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|
||||
|| (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
|
||||
&& (SECONDARY_INPUT_RELOAD_CLASS (class,
|
||||
|
@ -1028,7 +1025,7 @@ push_reload (in, out, inloc, outloc, class,
|
|||
that case. */
|
||||
|
||||
/* Similar issue for (SUBREG constant ...) if it was not handled by the
|
||||
code above. This can happen if SUBREG_WORD != 0. */
|
||||
code above. This can happen if SUBREG_BYTE != 0. */
|
||||
|
||||
if (in != 0 && reload_inner_reg_of_subreg (in, inmode))
|
||||
{
|
||||
|
@ -1038,7 +1035,11 @@ push_reload (in, out, inloc, outloc, class,
|
|||
RELOAD_OTHER, we are guaranteed that this inner reload will be
|
||||
output before the outer reload. */
|
||||
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
|
||||
find_valid_class (inmode, SUBREG_WORD (in)),
|
||||
find_valid_class (inmode,
|
||||
subreg_regno_offset (REGNO (SUBREG_REG (in)),
|
||||
GET_MODE (SUBREG_REG (in)),
|
||||
SUBREG_BYTE (in),
|
||||
GET_MODE (in))),
|
||||
VOIDmode, VOIDmode, 0, 0, opnum, type);
|
||||
dont_remove_subreg = 1;
|
||||
}
|
||||
|
@ -1050,7 +1051,7 @@ push_reload (in, out, inloc, outloc, class,
|
|||
(except in the case of STRICT_LOW_PART,
|
||||
and in that case the constraint should label it input-output.) */
|
||||
if (out != 0 && GET_CODE (out) == SUBREG
|
||||
&& (SUBREG_WORD (out) == 0 || strict_low)
|
||||
&& (SUBREG_BYTE (out) == 0 || strict_low)
|
||||
#ifdef CLASS_CANNOT_CHANGE_MODE
|
||||
&& (class != CLASS_CANNOT_CHANGE_MODE
|
||||
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
|
||||
|
@ -1080,9 +1081,7 @@ push_reload (in, out, inloc, outloc, class,
|
|||
/ UNITS_PER_WORD)
|
||||
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
|
||||
GET_MODE (SUBREG_REG (out)))))
|
||||
|| ! HARD_REGNO_MODE_OK ((REGNO (SUBREG_REG (out))
|
||||
+ SUBREG_WORD (out)),
|
||||
outmode)))
|
||||
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
|
||||
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|
||||
|| (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
|
||||
&& (SECONDARY_OUTPUT_RELOAD_CLASS (class,
|
||||
|
@ -1129,7 +1128,11 @@ push_reload (in, out, inloc, outloc, class,
|
|||
dont_remove_subreg = 1;
|
||||
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
|
||||
&SUBREG_REG (out),
|
||||
find_valid_class (outmode, SUBREG_WORD (out)),
|
||||
find_valid_class (outmode,
|
||||
subreg_regno_offset (REGNO (SUBREG_REG (out)),
|
||||
GET_MODE (SUBREG_REG (out)),
|
||||
SUBREG_BYTE (out),
|
||||
GET_MODE (out))),
|
||||
VOIDmode, VOIDmode, 0, 0,
|
||||
opnum, RELOAD_OTHER);
|
||||
}
|
||||
|
@ -1146,16 +1149,14 @@ push_reload (in, out, inloc, outloc, class,
|
|||
if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
|
||||
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
|
||||
&& ! dont_remove_subreg)
|
||||
in = gen_rtx_REG (GET_MODE (in),
|
||||
REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
|
||||
in = gen_rtx_REG (GET_MODE (in), subreg_regno (in));
|
||||
|
||||
/* Similarly for OUT. */
|
||||
if (out != 0 && GET_CODE (out) == SUBREG
|
||||
&& GET_CODE (SUBREG_REG (out)) == REG
|
||||
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
|
||||
&& ! dont_remove_subreg)
|
||||
out = gen_rtx_REG (GET_MODE (out),
|
||||
REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
|
||||
out = gen_rtx_REG (GET_MODE (out), subreg_regno (out));
|
||||
|
||||
/* Narrow down the class of register wanted if that is
|
||||
desirable on this machine for efficiency. */
|
||||
|
@ -1810,15 +1811,28 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
|
|||
|| GET_MODE_SIZE (inmode) > UNITS_PER_WORD))
|
||||
return 0;
|
||||
|
||||
/* Note that {in,out}_offset are needed only when 'in' or 'out'
|
||||
respectively refers to a hard register. */
|
||||
|
||||
/* Find the inside of any subregs. */
|
||||
while (GET_CODE (out) == SUBREG)
|
||||
{
|
||||
out_offset = SUBREG_WORD (out);
|
||||
if (GET_CODE (SUBREG_REG (out)) == REG
|
||||
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
|
||||
out_offset += subreg_regno_offset (REGNO (SUBREG_REG (out)),
|
||||
GET_MODE (SUBREG_REG (out)),
|
||||
SUBREG_BYTE (out),
|
||||
GET_MODE (out));
|
||||
out = SUBREG_REG (out);
|
||||
}
|
||||
while (GET_CODE (in) == SUBREG)
|
||||
{
|
||||
in_offset = SUBREG_WORD (in);
|
||||
if (GET_CODE (SUBREG_REG (in)) == REG
|
||||
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
|
||||
in_offset += subreg_regno_offset (REGNO (SUBREG_REG (in)),
|
||||
GET_MODE (SUBREG_REG (in)),
|
||||
SUBREG_BYTE (in),
|
||||
GET_MODE (in));
|
||||
in = SUBREG_REG (in);
|
||||
}
|
||||
|
||||
|
@ -2035,7 +2049,10 @@ operands_match_p (x, y)
|
|||
i = REGNO (SUBREG_REG (x));
|
||||
if (i >= FIRST_PSEUDO_REGISTER)
|
||||
goto slow;
|
||||
i += SUBREG_WORD (x);
|
||||
i += subreg_regno_offset (REGNO (SUBREG_REG (x)),
|
||||
GET_MODE (SUBREG_REG (x)),
|
||||
SUBREG_BYTE (x),
|
||||
GET_MODE (x));
|
||||
}
|
||||
else
|
||||
i = REGNO (x);
|
||||
|
@ -2045,7 +2062,10 @@ operands_match_p (x, y)
|
|||
j = REGNO (SUBREG_REG (y));
|
||||
if (j >= FIRST_PSEUDO_REGISTER)
|
||||
goto slow;
|
||||
j += SUBREG_WORD (y);
|
||||
j += subreg_regno_offset (REGNO (SUBREG_REG (y)),
|
||||
GET_MODE (SUBREG_REG (y)),
|
||||
SUBREG_BYTE (y),
|
||||
GET_MODE (y));
|
||||
}
|
||||
else
|
||||
j = REGNO (y);
|
||||
|
@ -2777,7 +2797,18 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
|
||||
while (GET_CODE (operand) == SUBREG)
|
||||
{
|
||||
offset += SUBREG_WORD (operand);
|
||||
/* Offset only matters when operand is a REG and
|
||||
it is a hard reg. This is because it is passed
|
||||
to reg_fits_class_p if it is a REG and all pseudos
|
||||
return 0 from that function. */
|
||||
if (GET_CODE (SUBREG_REG (operand)) == REG
|
||||
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
|
||||
GET_MODE (SUBREG_REG (operand)),
|
||||
SUBREG_BYTE (operand),
|
||||
GET_MODE (operand));
|
||||
}
|
||||
operand = SUBREG_REG (operand);
|
||||
/* Force reload if this is a constant or PLUS or if there may
|
||||
be a problem accessing OPERAND in the outer mode. */
|
||||
|
@ -2828,6 +2859,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
)
|
||||
#endif
|
||||
)
|
||||
/* This following hunk of code should no longer be
|
||||
needed at all with SUBREG_BYTE. If you need this
|
||||
code back, please explain to me why so I can
|
||||
fix the real problem. -DaveM */
|
||||
#if 0
|
||||
/* Subreg of a hard reg which can't handle the subreg's mode
|
||||
or which would handle that mode in the wrong number of
|
||||
registers for subregging to work. */
|
||||
|
@ -2841,7 +2877,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
!= HARD_REGNO_NREGS (REGNO (operand),
|
||||
GET_MODE (operand))))
|
||||
|| ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
|
||||
operand_mode[i]))))
|
||||
operand_mode[i])))
|
||||
#endif
|
||||
)
|
||||
force_reload = 1;
|
||||
}
|
||||
|
||||
|
@ -3716,7 +3754,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
rtx operand = recog_data.operand[i];
|
||||
|
||||
while (GET_CODE (operand) == SUBREG)
|
||||
operand = XEXP (operand, 0);
|
||||
operand = SUBREG_REG (operand);
|
||||
if ((GET_CODE (operand) == MEM
|
||||
|| (GET_CODE (operand) == REG
|
||||
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
|
||||
|
@ -3766,7 +3804,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
operand = *recog_data.operand_loc[i];
|
||||
|
||||
while (GET_CODE (operand) == SUBREG)
|
||||
operand = XEXP (operand, 0);
|
||||
operand = SUBREG_REG (operand);
|
||||
if (GET_CODE (operand) == REG)
|
||||
{
|
||||
if (modified[i] != RELOAD_WRITE)
|
||||
|
@ -3789,7 +3827,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
rtx operand = recog_data.operand[i];
|
||||
|
||||
while (GET_CODE (operand) == SUBREG)
|
||||
operand = XEXP (operand, 0);
|
||||
operand = SUBREG_REG (operand);
|
||||
if ((GET_CODE (operand) == MEM
|
||||
|| (GET_CODE (operand) == REG
|
||||
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
|
||||
|
@ -4303,7 +4341,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
|
|||
&& regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
|
||||
&& reg_equiv_constant[regno] != 0
|
||||
&& (tem = operand_subword (reg_equiv_constant[regno],
|
||||
SUBREG_WORD (x), 0,
|
||||
SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
|
||||
GET_MODE (SUBREG_REG (x)))) != 0)
|
||||
{
|
||||
/* TEM is now a word sized constant for the bits from X that
|
||||
|
@ -4329,7 +4367,7 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
|
|||
&& (GET_MODE_SIZE (GET_MODE (x))
|
||||
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
|
||||
{
|
||||
int shift = SUBREG_WORD (x) * BITS_PER_WORD;
|
||||
int shift = SUBREG_BYTE (x) * BITS_PER_UNIT;
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
|
||||
- GET_MODE_BITSIZE (GET_MODE (x))
|
||||
|
@ -4383,13 +4421,18 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
|
|||
the meaning of the memory access. */
|
||||
enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
|
||||
|
||||
/* SUBREG_REG (x) is a MEM, so we cant take the offset, instead we
|
||||
calculate the register number as :
|
||||
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode) */
|
||||
if (is_set_dest)
|
||||
push_reload (NULL_RTX, SUBREG_REG (x), NULL_PTR, &SUBREG_REG (x),
|
||||
find_valid_class (subreg_mode, SUBREG_WORD (x)),
|
||||
find_valid_class (subreg_mode,
|
||||
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
|
||||
VOIDmode, subreg_mode, 0, 0, opnum, type);
|
||||
else
|
||||
push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), NULL_PTR,
|
||||
find_valid_class (subreg_mode, SUBREG_WORD (x)),
|
||||
find_valid_class (subreg_mode,
|
||||
SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
|
||||
subreg_mode, VOIDmode, 0, 0, opnum, type);
|
||||
}
|
||||
|
||||
|
@ -5075,7 +5118,11 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
|
|||
code0 = GET_CODE (op0);
|
||||
if (code0 == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER)
|
||||
op0 = gen_rtx_REG (word_mode,
|
||||
REGNO (op0) + SUBREG_WORD (orig_op0));
|
||||
(REGNO (op0) +
|
||||
subreg_regno_offset (REGNO (SUBREG_REG (orig_op0)),
|
||||
GET_MODE (SUBREG_REG (orig_op0)),
|
||||
SUBREG_BYTE (orig_op0),
|
||||
GET_MODE (orig_op0))));
|
||||
}
|
||||
|
||||
if (GET_CODE (op1) == SUBREG)
|
||||
|
@ -5083,8 +5130,14 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
|
|||
op1 = SUBREG_REG (op1);
|
||||
code1 = GET_CODE (op1);
|
||||
if (code1 == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER)
|
||||
/* ??? Why is this given op1's mode and above for
|
||||
??? op0 SUBREGs we use word_mode? */
|
||||
op1 = gen_rtx_REG (GET_MODE (op1),
|
||||
REGNO (op1) + SUBREG_WORD (orig_op1));
|
||||
(REGNO (op1) +
|
||||
subreg_regno_offset (REGNO (SUBREG_REG (orig_op1)),
|
||||
GET_MODE (SUBREG_REG (orig_op1)),
|
||||
SUBREG_BYTE (orig_op1),
|
||||
GET_MODE (orig_op1))));
|
||||
}
|
||||
|
||||
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|
||||
|
@ -5492,7 +5545,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
|
|||
needless copies if SUBREG_REG is multi-word. */
|
||||
if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
|
||||
int regno = subreg_regno (x);
|
||||
|
||||
if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
|
||||
: REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
|
||||
|
@ -5646,15 +5699,10 @@ find_reloads_subreg_address (x, force_replace, opnum, type,
|
|||
if (force_replace
|
||||
|| ! rtx_equal_p (tem, reg_equiv_mem[regno]))
|
||||
{
|
||||
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
|
||||
int offset = SUBREG_BYTE (x);
|
||||
unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
|
||||
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
|
||||
|
||||
if (BYTES_BIG_ENDIAN)
|
||||
{
|
||||
offset += MIN (inner_size, UNITS_PER_WORD);
|
||||
offset -= MIN (outer_size, UNITS_PER_WORD);
|
||||
}
|
||||
XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
|
||||
PUT_MODE (tem, GET_MODE (x));
|
||||
|
||||
|
@ -5741,8 +5789,18 @@ subst_reloads (insn)
|
|||
*r->subreg_loc = SUBREG_REG (reloadreg);
|
||||
else
|
||||
{
|
||||
int final_offset =
|
||||
SUBREG_BYTE (*r->subreg_loc) + SUBREG_BYTE (reloadreg);
|
||||
|
||||
/* When working with SUBREGs the rule is that the byte
|
||||
offset must be a multiple of the SUBREG's mode. */
|
||||
final_offset = (final_offset /
|
||||
GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
|
||||
final_offset = (final_offset *
|
||||
GET_MODE_SIZE (GET_MODE (*r->subreg_loc)));
|
||||
|
||||
*r->where = SUBREG_REG (reloadreg);
|
||||
SUBREG_WORD (*r->subreg_loc) += SUBREG_WORD (reloadreg);
|
||||
SUBREG_BYTE (*r->subreg_loc) = final_offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -5843,12 +5901,24 @@ find_replacement (loc)
|
|||
|
||||
if (GET_CODE (reloadreg) == REG)
|
||||
return gen_rtx_REG (GET_MODE (*loc),
|
||||
REGNO (reloadreg) + SUBREG_WORD (*loc));
|
||||
(REGNO (reloadreg) +
|
||||
subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
|
||||
GET_MODE (SUBREG_REG (*loc)),
|
||||
SUBREG_BYTE (*loc),
|
||||
GET_MODE (*loc))));
|
||||
else if (GET_MODE (reloadreg) == GET_MODE (*loc))
|
||||
return reloadreg;
|
||||
else
|
||||
return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
|
||||
SUBREG_WORD (reloadreg) + SUBREG_WORD (*loc));
|
||||
{
|
||||
int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
|
||||
|
||||
/* When working with SUBREGs the rule is that the byte
|
||||
offset must be a multiple of the SUBREG's mode. */
|
||||
final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
|
||||
final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
|
||||
return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
|
||||
final_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5925,7 +5995,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
|
|||
if (GET_CODE (SUBREG_REG (x)) == REG
|
||||
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
|
||||
unsigned int inner_regno = subreg_regno (x);
|
||||
unsigned int inner_endregno
|
||||
= inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
|
||||
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
|
||||
|
@ -6020,7 +6090,10 @@ reg_overlap_mentioned_for_reload_p (x, in)
|
|||
{
|
||||
regno = REGNO (SUBREG_REG (x));
|
||||
if (regno < FIRST_PSEUDO_REGISTER)
|
||||
regno += SUBREG_WORD (x);
|
||||
regno += subreg_regno_offset (REGNO (SUBREG_REG (x)),
|
||||
GET_MODE (SUBREG_REG (x)),
|
||||
SUBREG_BYTE (x),
|
||||
GET_MODE (x));
|
||||
}
|
||||
else if (GET_CODE (x) == REG)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
17
gcc/rtl.h
17
gcc/rtl.h
|
@ -789,10 +789,17 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
|
|||
#define CONST_DOUBLE_MEM(r) XCEXP (r, 0, CONST_DOUBLE)
|
||||
|
||||
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
|
||||
SUBREG_WORD extracts the word-number. */
|
||||
SUBREG_BYTE extracts the byte-number. */
|
||||
|
||||
#define SUBREG_REG(RTX) XCEXP(RTX, 0, SUBREG)
|
||||
#define SUBREG_WORD(RTX) XCUINT(RTX, 1, SUBREG)
|
||||
#define SUBREG_BYTE(RTX) XCUINT(RTX, 1, SUBREG)
|
||||
|
||||
/* in rtlanal.c */
|
||||
extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
|
||||
enum machine_mode,
|
||||
unsigned int,
|
||||
enum machine_mode));
|
||||
extern unsigned int subreg_regno PARAMS ((rtx));
|
||||
|
||||
/* 1 if the REG contained in SUBREG_REG is already known to be
|
||||
sign- or zero-extended from the mode of the SUBREG to the mode of
|
||||
|
@ -1179,6 +1186,7 @@ extern int rtx_equal_p PARAMS ((rtx, rtx));
|
|||
extern rtvec gen_rtvec_v PARAMS ((int, rtx *));
|
||||
extern rtx gen_reg_rtx PARAMS ((enum machine_mode));
|
||||
extern rtx gen_label_rtx PARAMS ((void));
|
||||
extern int subreg_hard_regno PARAMS ((rtx, int));
|
||||
extern rtx gen_lowpart_common PARAMS ((enum machine_mode, rtx));
|
||||
extern rtx gen_lowpart PARAMS ((enum machine_mode, rtx));
|
||||
|
||||
|
@ -1191,6 +1199,8 @@ extern rtx gen_realpart PARAMS ((enum machine_mode, rtx));
|
|||
extern rtx gen_imagpart PARAMS ((enum machine_mode, rtx));
|
||||
extern rtx operand_subword PARAMS ((rtx, unsigned int, int,
|
||||
enum machine_mode));
|
||||
extern rtx constant_subword PARAMS ((rtx, int,
|
||||
enum machine_mode));
|
||||
|
||||
/* In emit-rtl.c */
|
||||
extern rtx operand_subword_force PARAMS ((rtx, unsigned int,
|
||||
|
@ -1569,8 +1579,11 @@ extern rtx gen_rtx_CONST_DOUBLE PARAMS ((enum machine_mode, rtx,
|
|||
extern rtx gen_rtx_CONST_INT PARAMS ((enum machine_mode, HOST_WIDE_INT));
|
||||
extern rtx gen_raw_REG PARAMS ((enum machine_mode, int));
|
||||
extern rtx gen_rtx_REG PARAMS ((enum machine_mode, int));
|
||||
extern rtx gen_rtx_SUBREG PARAMS ((enum machine_mode, rtx, int));
|
||||
extern rtx gen_rtx_MEM PARAMS ((enum machine_mode, rtx));
|
||||
|
||||
extern rtx gen_lowpart_SUBREG PARAMS ((enum machine_mode, rtx));
|
||||
|
||||
/* We need the cast here to ensure that we get the same result both with
|
||||
and without prototypes. */
|
||||
#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (HOST_WIDE_INT) (N))
|
||||
|
|
21
gcc/rtl.texi
21
gcc/rtl.texi
|
@ -1166,16 +1166,16 @@ This virtual register is replaced by the sum of the register given by
|
|||
@end table
|
||||
|
||||
@findex subreg
|
||||
@item (subreg:@var{m} @var{reg} @var{wordnum})
|
||||
@item (subreg:@var{m} @var{reg} @var{bytenum})
|
||||
@code{subreg} expressions are used to refer to a register in a machine
|
||||
mode other than its natural one, or to refer to one register of
|
||||
a multi-word @code{reg} that actually refers to several registers.
|
||||
a multi-part @code{reg} that actually refers to several registers.
|
||||
|
||||
Each pseudo-register has a natural mode. If it is necessary to
|
||||
operate on it in a different mode---for example, to perform a fullword
|
||||
move instruction on a pseudo-register that contains a single
|
||||
byte---the pseudo-register must be enclosed in a @code{subreg}. In
|
||||
such a case, @var{wordnum} is zero.
|
||||
such a case, @var{bytenum} is zero.
|
||||
|
||||
Usually @var{m} is at least as narrow as the mode of @var{reg}, in which
|
||||
case it is restricting consideration to only the bits of @var{reg} that
|
||||
|
@ -1192,7 +1192,7 @@ a multi-register value. Machine modes such as @code{DImode} and
|
|||
@code{TImode} can indicate values longer than a word, values which
|
||||
usually require two or more consecutive registers. To access one of the
|
||||
registers, use a @code{subreg} with mode @code{SImode} and a
|
||||
@var{wordnum} that says which register.
|
||||
@var{bytenum} offset that says which register.
|
||||
|
||||
Storing in a non-paradoxical @code{subreg} has undefined results for
|
||||
bits belonging to the same word as the @code{subreg}. This laxity makes
|
||||
|
@ -1202,8 +1202,13 @@ the @code{subreg}, use @code{strict_low_part} around the @code{subreg}.
|
|||
|
||||
@cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
|
||||
The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
|
||||
that word number zero is the most significant part; otherwise, it is
|
||||
the least significant part.
|
||||
that byte number zero is part of the most significant word; otherwise,
|
||||
it is part of the least significant word.
|
||||
|
||||
@cindex @code{BYTES_BIG_ENDIAN}, effect on @code{subreg}
|
||||
The compilation parameter @code{BYTES_BIG_ENDIAN}, if set to 1, says
|
||||
that byte number zero is the most significant byte within a word;
|
||||
otherwise, it is the least significant byte within a word.
|
||||
|
||||
@cindex @code{FLOAT_WORDS_BIG_ENDIAN}, (lack of) effect on @code{subreg}
|
||||
On a few targets, @code{FLOAT_WORDS_BIG_ENDIAN} disagrees with
|
||||
|
@ -1239,10 +1244,10 @@ a single machine register. The reload pass prevents @code{subreg}
|
|||
expressions such as these from being formed.
|
||||
|
||||
@findex SUBREG_REG
|
||||
@findex SUBREG_WORD
|
||||
@findex SUBREG_BYTE
|
||||
The first operand of a @code{subreg} expression is customarily accessed
|
||||
with the @code{SUBREG_REG} macro and the second operand is customarily
|
||||
accessed with the @code{SUBREG_WORD} macro.
|
||||
accessed with the @code{SUBREG_BYTE} macro.
|
||||
|
||||
@findex scratch
|
||||
@cindex scratch operands
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
12
gcc/sdbout.c
12
gcc/sdbout.c
|
@ -776,19 +776,15 @@ sdbout_symbol (decl, local)
|
|||
else if (GET_CODE (value) == SUBREG)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
while (GET_CODE (value) == SUBREG)
|
||||
{
|
||||
offset += SUBREG_WORD (value);
|
||||
value = SUBREG_REG (value);
|
||||
}
|
||||
value = SUBREG_REG (value);
|
||||
if (GET_CODE (value) == REG)
|
||||
{
|
||||
regno = REGNO (value);
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
|
||||
return;
|
||||
regno += offset;
|
||||
}
|
||||
alter_subreg (DECL_RTL (decl));
|
||||
regno = REGNO (alter_subreg (DECL_RTL (decl)));
|
||||
value = DECL_RTL (decl);
|
||||
}
|
||||
/* Don't output anything if an auto variable
|
||||
|
|
|
@ -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 ();
|
||||
|
|
24
gcc/tm.texi
24
gcc/tm.texi
|
@ -1697,17 +1697,6 @@ definition of this macro is
|
|||
/ UNITS_PER_WORD)
|
||||
@end smallexample
|
||||
|
||||
@findex ALTER_HARD_SUBREG
|
||||
@item ALTER_HARD_SUBREG (@var{tgt_mode}, @var{word}, @var{src_mode}, @var{regno})
|
||||
A C expression that returns an adjusted hard register number for
|
||||
|
||||
@smallexample
|
||||
(subreg:@var{tgt_mode} (reg:@var{src_mode} @var{regno}) @var{word})
|
||||
@end smallexample
|
||||
|
||||
This may be needed if the target machine has mixed sized big-endian
|
||||
registers, like Sparc v9.
|
||||
|
||||
@findex HARD_REGNO_MODE_OK
|
||||
@item HARD_REGNO_MODE_OK (@var{regno}, @var{mode})
|
||||
A C expression that is nonzero if it is permissible to store a value
|
||||
|
@ -1790,6 +1779,19 @@ allocation.
|
|||
Define this macro if the compiler should avoid copies to/from @code{CCmode}
|
||||
registers. You should only define this macro if support for copying to/from
|
||||
@code{CCmode} is incomplete.
|
||||
|
||||
@findex SUBREG_REGNO_OFFSET
|
||||
@item SUBREG_REGNO_OFFSET
|
||||
Define this macro if the compiler needs to handle subregs in a non-standard
|
||||
way. The macro returns the correct regno offset for mode @code{YMODE} given
|
||||
a subreg of type @code{XMODE}.
|
||||
This macro takes 4 parameters:
|
||||
@code{XREGNO} - A regno of an inner hard subreg_reg (or what will become one).
|
||||
@code{XMODE} - The mode of xregno.
|
||||
@code{OFFSET} - The byte offset.
|
||||
@code{YMODE} - The mode of a top level SUBREG (or what may become one).
|
||||
The default function can be found in rtlanal.c, function
|
||||
@code{subreg_regno_offset}. Normally this does not need to be defined.
|
||||
@end table
|
||||
|
||||
@node Leaf Functions
|
||||
|
|
Loading…
Add table
Reference in a new issue