Symbols are normally PSImode, and the MSP430 has PSImode registers and PSImode moves to reg/mem. But sometimes gcc uses an SImode move instead, if the result will later be used in SImode (as in getP() in gcc/testsuite/gcc.dg/torture/pr65077.c). Committed.
* config/msp430/msp430.md (movsi_s): New. Special case for storing a 20-bit symbol into a 32-bit register. * config/msp430/msp430.c (msp430_subreg): Add support for it. * config/msp430/predicates.md (msp430_symbol_operand): New. Index: gcc/config/msp430/predicates.md =================================================================== --- gcc/config/msp430/predicates.md (revision 224143) +++ gcc/config/msp430/predicates.md (working copy) @@ -79,6 +79,10 @@ ; TRUE for constants which are bit positions for zero_extract (define_predicate "msp430_bitpos" (and (match_code "const_int") (match_test (" INTVAL (op) >= 0 && INTVAL (op) <= 15 ")))) + +(define_predicate "msp430_symbol_operand" + (match_code "symbol_ref") +) Index: gcc/config/msp430/msp430.md =================================================================== --- gcc/config/msp430/msp430.md (revision 224143) +++ gcc/config/msp430/msp430.md (working copy) @@ -211,12 +211,25 @@ [(set (match_operand:SI 0 "nonimmediate_operand") (match_operand:SI 1 "general_operand"))] "" "" ) +(define_insn_and_split "movsi_s" + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (subreg:SI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] + "" + "" + "reload_completed" + [(set (match_operand:HI 2 "nonimmediate_operand") + (match_operand:HI 4 "general_operand")) + (set (match_operand:HI 3 "nonimmediate_operand") + (match_operand:HI 5 "general_operand"))] + "msp430_split_movsi (operands);" + ) + (define_insn_and_split "movsi_x" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (match_operand:SI 1 "general_operand" "rmi"))] "" "#" "reload_completed" Index: gcc/config/msp430/msp430.c =================================================================== --- gcc/config/msp430/msp430.c (revision 224143) +++ gcc/config/msp430/msp430.c (working copy) @@ -2371,12 +2371,19 @@ msp430_subreg (machine_mode mode, rtx r, rv = gen_rtx_SUBREG (mode, ireg, byte); else rv = simplify_gen_subreg (mode, ireg, imode, byte); } else if (GET_CODE (r) == MEM) rv = adjust_address (r, mode, byte); + else if (GET_CODE (r) == SYMBOL_REF + && (byte == 0 || byte == 2) + && mode == HImode) + { + rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte)); + rv = gen_rtx_CONST (HImode, r); + } else rv = simplify_gen_subreg (mode, r, omode, byte); if (!rv) gcc_unreachable ();