Message ID | 201408132211.s7DMBqaQ016409@greed.delorie.com |
---|---|
State | New |
Headers | show |
> This is the MSP430-specific use of the new intN framework to enable > true 20-bit pointers. Since I'm one of the MSP430 maintainers, this > patch is being posted for reference, not for approval. Now that the other parts are committed, I'm checking this one in too. > gcc/config/msp430 > * config/msp430/msp430-modes.def (PSI): Add. > > * config/msp430/msp430-protos.h (msp430_hard_regno_nregs_has_padding): New. > (msp430_hard_regno_nregs_with_padding): New. > * config/msp430/msp430.c (msp430_scalar_mode_supported_p): New. > (msp430_hard_regno_nregs_has_padding): New. > (msp430_hard_regno_nregs_with_padding): New. > (msp430_unwind_word_mode): Use PSImode instead of SImode. > (msp430_addr_space_legitimate_address_p): New. > (msp430_asm_integer): New. > (msp430_init_dwarf_reg_sizes_extra): New. > (msp430_print_operand): Use X suffix for PSImode even in small model. > * config/msp430/msp430.h (POINTER_SIZE): Use 20 bits, not 32. > (PTR_SIZE): ...but 4 bytes for EH. > (SIZE_TYPE): Use __int20. > (PTRDIFF_TYPE): Likewise. > (INCOMING_FRAME_SP_OFFSET): Adjust. > * config/msp430/msp430.md (movqi_topbyte): New. > (movpsi): Use fixed suffixes. > (movsipsi2): Enable for 430X, not large model. > (extendhipsi2): Likewise. > (zero_extendhisi2): Likewise. > (zero_extendhisipsi2): Likewise. > (extend_and_shift1_hipsi2): Likewise. > (extendpsisi2): Likewise. > (*bitbranch<mode>4_z): Fix suffix logic. > > > Index: gcc/config/msp430/msp430-protos.h > =================================================================== > --- gcc/config/msp430/msp430-protos.h (revision 213886) > +++ gcc/config/msp430/msp430-protos.h (working copy) > @@ -27,12 +27,15 @@ void msp430_expand_epilogue (int); > void msp430_expand_helper (rtx *operands, const char *, bool); > void msp430_expand_prologue (void); > const char * msp430x_extendhisi (rtx *); > void msp430_fixup_compare_operands (enum machine_mode, rtx *); > int msp430_hard_regno_mode_ok (int, enum machine_mode); > int msp430_hard_regno_nregs (int, enum machine_mode); > +int msp430_hard_regno_nregs_has_padding (int, enum machine_mode); > +int msp430_hard_regno_nregs_with_padding (int, enum machine_mode); > +bool msp430_hwmult_enabled (void); > rtx msp430_incoming_return_addr_rtx (void); > void msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); > int msp430_initial_elimination_offset (int, int); > bool msp430_is_interrupt_func (void); > const char * msp430x_logical_shift_right (rtx); > const char * msp430_mcu_name (void); > Index: gcc/config/msp430/msp430.md > =================================================================== > --- gcc/config/msp430/msp430.md (revision 213886) > +++ gcc/config/msp430/msp430.md (working copy) > @@ -176,12 +176,19 @@ > "" > "@ > MOV.B\t%1, %0 > MOV%X1.B\t%1, %0" > ) > > +(define_insn "movqi_topbyte" > + [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r") > + (subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))] > + "msp430x" > + "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" > +) > + > (define_insn "movqi" > [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm") > (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))] > "" > "@ > MOV.B\t%1, %0 > @@ -220,27 +227,27 @@ > ;; Some MOVX.A cases can be done with MOVA, this is only a few of them. > (define_insn "movpsi" > [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,Ya,rm") > (match_operand:PSI 1 "msp_general_operand" "riYa,r,rmi"))] > "" > "@ > - MOV%Q0\t%1, %0 > - MOV%Q0\t%1, %0 > - MOV%X0.%Q0\t%1, %0") > + MOVA\t%1, %0 > + MOVA\t%1, %0 > + MOVX.A\t%1, %0") > > ; This pattern is identical to the truncsipsi2 pattern except > ; that it uses a SUBREG instead of a TRUNC. It is needed in > ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI))) > ; into (SET:PSI (PSI)). > ; > ; Note: using POPM.A #1 is two bytes smaller than using POPX.A.... > > (define_insn "movsipsi2" > [(set (match_operand:PSI 0 "register_operand" "=r") > (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] > - "TARGET_LARGE" > + "msp430x" > "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" > ) > > ;;------------------------------------------------------------ > ;; Math > > @@ -564,49 +571,49 @@ > { return msp430x_extendhisi (operands); } > ) > > (define_insn "extendhipsi2" > [(set (match_operand:PSI 0 "nonimmediate_operand" "=r") > (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))] > - "TARGET_LARGE" > + "msp430x" > "RLAM #4, %0 { RRAM #4, %0" > ) > > ;; Look for cases where integer/pointer conversions are suboptimal due > ;; to missing patterns, despite us not having opcodes for these > ;; patterns. Doing these manually allows for alternate optimization > ;; paths. > (define_insn "zero_extendhisi2" > [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") > (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))] > - "TARGET_LARGE" > + "msp430x" > "MOV.W\t#0,%H0" > ) > > (define_insn "zero_extendhisipsi2" > [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r") > (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))] > - "TARGET_LARGE" > + "msp430x" > "@ > AND.W\t#-1,%0 > MOV.W\t%1,%0" > ) > > (define_insn "extend_and_shift1_hipsi2" > [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) > (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) > (const_int 1)))] > - "TARGET_LARGE" > + "msp430x" > "RLAM #4, %0 { RRAM #3, %0" > ) > > (define_insn "extend_and_shift2_hipsi2" > [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) > (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) > (const_int 2)))] > - "TARGET_LARGE" > + "msp430x" > "RLAM #4, %0 { RRAM #2, %0" > ) > > ; Nasty - we are sign-extending a 20-bit PSI value in one register into > ; two adjacent 16-bit registers to make an SI value. There is no MSP430X > ; instruction that will do this, so we push the 20-bit value onto the stack > @@ -645,13 +652,13 @@ > ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends > ;; it, we use a different method here. > > (define_insn "extendpsisi2" > [(set (match_operand:SI 0 "register_operand" "=r") > (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))] > - "TARGET_LARGE" > + "msp430x" > "* > /* The intention here is that we copy the bottom 16-bits of > %1 into %L0 (zeroing the top four bits). Then we copy the > entire 20-bits of %1 into %H0 and then arithmetically shift > it right by 16 bits, to get the top four bits of the pointer > sign-extended in %H0. */ > @@ -1174,13 +1181,13 @@ > (const_int 0)) > (label_ref (match_operand 2 "" "")) > (pc))) > (clobber (reg:BI CARRY)) > ] > "" > - "BIT%x0%X0%b0\t%1, %0 { JEQ\t%l2" > + "BIT%x0%b0\t%1, %0 { JEQ\t%l2" > ) > > (define_insn "*bitbranch<mode>4" > [(set (pc) (if_then_else > (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") > (match_operand:QHI 1 "msp_general_operand" "rmi")) > Index: gcc/config/msp430/msp430.c > =================================================================== > --- gcc/config/msp430/msp430.c (revision 213886) > +++ gcc/config/msp430/msp430.c (working copy) > @@ -225,12 +225,27 @@ msp430_option_override (void) > command line and always sets -O2 in CFLAGS. Thus it is not > possible to build newlib with -Os enabled. Until now... */ > if (TARGET_OPT_SPACE && optimize < 3) > optimize_size = 1; > } > > +#undef TARGET_SCALAR_MODE_SUPPORTED_P > +#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p > + > +static bool > +msp430_scalar_mode_supported_p (enum machine_mode m) > +{ > + if (m == PSImode && msp430x) > + return true; > +#if 0 > + if (m == TImode) > + return true; > +#endif > + return default_scalar_mode_supported_p (m); > +} > + > > > /* Storage Layout */ > > #undef TARGET_MS_BITFIELD_LAYOUT_P > #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p > @@ -254,12 +269,33 @@ msp430_hard_regno_nregs (int regno ATTRI > if (mode == PSImode && msp430x) > return 1; > return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) > / UNITS_PER_WORD); > } > > +/* Implements HARD_REGNO_NREGS_HAS_PADDING. */ > +int > +msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED, > + enum machine_mode mode) > +{ > + if (mode == PSImode && msp430x) > + return 1; > + return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) > + / UNITS_PER_WORD); > +} > + > +/* Implements HARD_REGNO_NREGS_WITH_PADDING. */ > +int > +msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED, > + enum machine_mode mode) > +{ > + if (mode == PSImode) > + return 2; > + return msp430_hard_regno_nregs (regno, mode); > +} > + > /* Implements HARD_REGNO_MODE_OK. */ > int > msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED, > enum machine_mode mode) > { > return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode)); > @@ -367,13 +403,13 @@ msp430_addr_space_pointer_mode (addr_spa > #undef TARGET_UNWIND_WORD_MODE > #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode > > static enum machine_mode > msp430_unwind_word_mode (void) > { > - return TARGET_LARGE ? SImode : HImode; > + return TARGET_LARGE ? PSImode : HImode; > } > > /* Determine if one named address space is a subset of another. */ > #undef TARGET_ADDR_SPACE_SUBSET_P > #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p > static bool > @@ -882,12 +918,58 @@ msp430_legitimate_address_p (enum machin > > default: > return false; > } > } > > +#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P > +#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p > + > +bool > +msp430_addr_space_legitimate_address_p (enum machine_mode mode, > + rtx x, > + bool strict, > + addr_space_t as ATTRIBUTE_UNUSED) > +{ > + return msp430_legitimate_address_p (mode, x, strict); > +} > + > +#undef TARGET_ASM_INTEGER > +#define TARGET_ASM_INTEGER msp430_asm_integer > +static bool > +msp430_asm_integer (rtx x, unsigned int size, int aligned_p) > +{ > + int c = GET_CODE (x); > + > + if (size == 3 && GET_MODE (x) == PSImode) > + size = 4; > + > + switch (size) > + { > + case 4: > + if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT) > + { > + fprintf (asm_out_file, "\t.long\t"); > + output_addr_const (asm_out_file, x); > + fputc ('\n', asm_out_file); > + return true; > + } > + break; > + } > + return default_assemble_integer (x, size, aligned_p); > +} > + > +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA > +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra > +static bool > +msp430_asm_output_addr_const_extra (FILE *file, rtx x) > +{ > + debug_rtx(x); > + return false; > +} > + > #undef TARGET_LEGITIMATE_CONSTANT_P > #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant > > static bool > msp430_legitimate_constant (enum machine_mode mode, rtx x) > { > @@ -1740,12 +1822,39 @@ msp430_expand_eh_return (rtx eh_handler) > tmp = gen_rtx_PLUS (Pmode, ap, sa); > tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2); > tmp = gen_rtx_MEM (Pmode, tmp); > emit_move_insn (tmp, ra); > } > > +#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA > +#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra > +void > +msp430_init_dwarf_reg_sizes_extra (tree address) > +{ > + int i; > + rtx addr = expand_normal (address); > + rtx mem = gen_rtx_MEM (BLKmode, addr); > + > + if (!msp430x) > + return; > + > + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) > + { > + unsigned int dnum = DWARF_FRAME_REGNUM (i); > + unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1); > + > + if (rnum < DWARF_FRAME_REGISTERS) > + { > + HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode); > + > + emit_move_insn (adjust_address (mem, QImode, offset), > + gen_int_mode (4, QImode)); > + } > + } > +} > + > /* This is a list of MD patterns that implement fixed-count shifts. */ > static struct > { > const char *name; > int count; > int need_430x; > @@ -2350,13 +2459,13 @@ msp430_print_operand (FILE * file, rtx o > } > break; > > case 'X': > /* This is used to turn, for example, an ADD opcode into an ADDX > opcode when we're using 20-bit addresses. */ > - if (TARGET_LARGE) > + if (TARGET_LARGE || GET_MODE (op) == PSImode) > fprintf (file, "X"); > /* We don't care which operand we use, but we want 'X' in the MD > file, so we do it this way. */ > return; > > case 'x': > Index: gcc/config/msp430/msp430.h > =================================================================== > --- gcc/config/msp430/msp430.h (revision 213886) > +++ gcc/config/msp430/msp430.h (working copy) > @@ -128,16 +128,15 @@ extern bool msp430x; > #define FRAME_GROWS_DOWNWARD 1 > #define FIRST_PARM_OFFSET(FNDECL) 0 > > #define MAX_REGS_PER_ADDRESS 1 > > #define Pmode (TARGET_LARGE ? PSImode : HImode) > -/* Note: 32 is a lie. Large pointers are actually 20-bits wide. But gcc > - thinks that any non-power-of-2 pointer size equates to BLKmode, which > - causes all kinds of problems... */ > -#define POINTER_SIZE (TARGET_LARGE ? 32 : 16) > +#define POINTER_SIZE (TARGET_LARGE ? 20 : 16) > +/* This is just for .eh_frame, to match bfd. */ > +#define PTR_SIZE (TARGET_LARGE ? 4 : 2) > #define POINTERS_EXTEND_UNSIGNED 1 > > #define ADDR_SPACE_NEAR 1 > #define ADDR_SPACE_FAR 2 > > #define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas() > @@ -155,15 +154,15 @@ extern bool msp430x; > (MODE) = HImode; > #endif > > /* Layout of Source Language Data Types */ > > #undef SIZE_TYPE > -#define SIZE_TYPE (TARGET_LARGE ? "long unsigned int" : "unsigned int") > +#define SIZE_TYPE (TARGET_LARGE ? "__int20 unsigned" : "unsigned int") > #undef PTRDIFF_TYPE > -#define PTRDIFF_TYPE (TARGET_LARGE ? "long int" : "int") > +#define PTRDIFF_TYPE (TARGET_LARGE ? "__int20" : "int") > #undef WCHAR_TYPE > #define WCHAR_TYPE "long int" > #undef WCHAR_TYPE_SIZE > #define WCHAR_TYPE_SIZE BITS_PER_WORD > #define FUNCTION_MODE HImode > #define CASE_VECTOR_MODE Pmode > @@ -379,13 +378,13 @@ typedef struct > > #define JUMP_TABLES_IN_TEXT_SECTION 1 > > #undef DWARF2_ADDR_SIZE > #define DWARF2_ADDR_SIZE 4 > > -#define INCOMING_FRAME_SP_OFFSET (POINTER_SIZE / BITS_PER_UNIT) > +#define INCOMING_FRAME_SP_OFFSET (TARGET_LARGE ? 4 : 2) > > #undef PREFERRED_DEBUGGING_TYPE > #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG > > #define DWARF2_ASM_LINE_DEBUG_INFO 1 > >
Index: gcc/config/msp430/msp430-protos.h =================================================================== --- gcc/config/msp430/msp430-protos.h (revision 213886) +++ gcc/config/msp430/msp430-protos.h (working copy) @@ -27,12 +27,15 @@ void msp430_expand_epilogue (int); void msp430_expand_helper (rtx *operands, const char *, bool); void msp430_expand_prologue (void); const char * msp430x_extendhisi (rtx *); void msp430_fixup_compare_operands (enum machine_mode, rtx *); int msp430_hard_regno_mode_ok (int, enum machine_mode); int msp430_hard_regno_nregs (int, enum machine_mode); +int msp430_hard_regno_nregs_has_padding (int, enum machine_mode); +int msp430_hard_regno_nregs_with_padding (int, enum machine_mode); +bool msp430_hwmult_enabled (void); rtx msp430_incoming_return_addr_rtx (void); void msp430_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); int msp430_initial_elimination_offset (int, int); bool msp430_is_interrupt_func (void); const char * msp430x_logical_shift_right (rtx); const char * msp430_mcu_name (void); Index: gcc/config/msp430/msp430.md =================================================================== --- gcc/config/msp430/msp430.md (revision 213886) +++ gcc/config/msp430/msp430.md (working copy) @@ -176,12 +176,19 @@ "" "@ MOV.B\t%1, %0 MOV%X1.B\t%1, %0" ) +(define_insn "movqi_topbyte" + [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=r") + (subreg:QI (match_operand:PSI 1 "msp_general_operand" "r") 2))] + "msp430x" + "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" +) + (define_insn "movqi" [(set (match_operand:QI 0 "msp_nonimmediate_operand" "=rYs,rm") (match_operand:QI 1 "msp_general_operand" "riYs,rmi"))] "" "@ MOV.B\t%1, %0 @@ -220,27 +227,27 @@ ;; Some MOVX.A cases can be done with MOVA, this is only a few of them. (define_insn "movpsi" [(set (match_operand:PSI 0 "msp_nonimmediate_operand" "=r,Ya,rm") (match_operand:PSI 1 "msp_general_operand" "riYa,r,rmi"))] "" "@ - MOV%Q0\t%1, %0 - MOV%Q0\t%1, %0 - MOV%X0.%Q0\t%1, %0") + MOVA\t%1, %0 + MOVA\t%1, %0 + MOVX.A\t%1, %0") ; This pattern is identical to the truncsipsi2 pattern except ; that it uses a SUBREG instead of a TRUNC. It is needed in ; order to prevent reload from converting (set:SI (SUBREG:PSI (SI))) ; into (SET:PSI (PSI)). ; ; Note: using POPM.A #1 is two bytes smaller than using POPX.A.... (define_insn "movsipsi2" [(set (match_operand:PSI 0 "register_operand" "=r") (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] - "TARGET_LARGE" + "msp430x" "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" ) ;;------------------------------------------------------------ ;; Math @@ -564,49 +571,49 @@ { return msp430x_extendhisi (operands); } ) (define_insn "extendhipsi2" [(set (match_operand:PSI 0 "nonimmediate_operand" "=r") (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))] - "TARGET_LARGE" + "msp430x" "RLAM #4, %0 { RRAM #4, %0" ) ;; Look for cases where integer/pointer conversions are suboptimal due ;; to missing patterns, despite us not having opcodes for these ;; patterns. Doing these manually allows for alternate optimization ;; paths. (define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")))] - "TARGET_LARGE" + "msp430x" "MOV.W\t#0,%H0" ) (define_insn "zero_extendhisipsi2" [(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r") (subreg:PSI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r")) 0))] - "TARGET_LARGE" + "msp430x" "@ AND.W\t#-1,%0 MOV.W\t%1,%0" ) (define_insn "extend_and_shift1_hipsi2" [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 1)))] - "TARGET_LARGE" + "msp430x" "RLAM #4, %0 { RRAM #3, %0" ) (define_insn "extend_and_shift2_hipsi2" [(set (subreg:SI (match_operand:PSI 0 "nonimmediate_operand" "=r") 0) (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 2)))] - "TARGET_LARGE" + "msp430x" "RLAM #4, %0 { RRAM #2, %0" ) ; Nasty - we are sign-extending a 20-bit PSI value in one register into ; two adjacent 16-bit registers to make an SI value. There is no MSP430X ; instruction that will do this, so we push the 20-bit value onto the stack @@ -645,13 +652,13 @@ ;; Since (we assume) pushing a 20-bit value onto the stack zero-extends ;; it, we use a different method here. (define_insn "extendpsisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))] - "TARGET_LARGE" + "msp430x" "* /* The intention here is that we copy the bottom 16-bits of %1 into %L0 (zeroing the top four bits). Then we copy the entire 20-bits of %1 into %H0 and then arithmetically shift it right by 16 bits, to get the top four bits of the pointer sign-extended in %H0. */ @@ -1174,13 +1181,13 @@ (const_int 0)) (label_ref (match_operand 2 "" "")) (pc))) (clobber (reg:BI CARRY)) ] "" - "BIT%x0%X0%b0\t%1, %0 { JEQ\t%l2" + "BIT%x0%b0\t%1, %0 { JEQ\t%l2" ) (define_insn "*bitbranch<mode>4" [(set (pc) (if_then_else (eq (and:QHI (match_operand:QHI 0 "msp_nonimmediate_operand" "rm") (match_operand:QHI 1 "msp_general_operand" "rmi")) Index: gcc/config/msp430/msp430.c =================================================================== --- gcc/config/msp430/msp430.c (revision 213886) +++ gcc/config/msp430/msp430.c (working copy) @@ -225,12 +225,27 @@ msp430_option_override (void) command line and always sets -O2 in CFLAGS. Thus it is not possible to build newlib with -Os enabled. Until now... */ if (TARGET_OPT_SPACE && optimize < 3) optimize_size = 1; } +#undef TARGET_SCALAR_MODE_SUPPORTED_P +#define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p + +static bool +msp430_scalar_mode_supported_p (enum machine_mode m) +{ + if (m == PSImode && msp430x) + return true; +#if 0 + if (m == TImode) + return true; +#endif + return default_scalar_mode_supported_p (m); +} + /* Storage Layout */ #undef TARGET_MS_BITFIELD_LAYOUT_P #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p @@ -254,12 +269,33 @@ msp430_hard_regno_nregs (int regno ATTRI if (mode == PSImode && msp430x) return 1; return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); } +/* Implements HARD_REGNO_NREGS_HAS_PADDING. */ +int +msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + if (mode == PSImode && msp430x) + return 1; + return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) + / UNITS_PER_WORD); +} + +/* Implements HARD_REGNO_NREGS_WITH_PADDING. */ +int +msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + if (mode == PSImode) + return 2; + return msp430_hard_regno_nregs (regno, mode); +} + /* Implements HARD_REGNO_MODE_OK. */ int msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED, enum machine_mode mode) { return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode)); @@ -367,13 +403,13 @@ msp430_addr_space_pointer_mode (addr_spa #undef TARGET_UNWIND_WORD_MODE #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode static enum machine_mode msp430_unwind_word_mode (void) { - return TARGET_LARGE ? SImode : HImode; + return TARGET_LARGE ? PSImode : HImode; } /* Determine if one named address space is a subset of another. */ #undef TARGET_ADDR_SPACE_SUBSET_P #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p static bool @@ -882,12 +918,58 @@ msp430_legitimate_address_p (enum machin default: return false; } } +#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P +#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p + +bool +msp430_addr_space_legitimate_address_p (enum machine_mode mode, + rtx x, + bool strict, + addr_space_t as ATTRIBUTE_UNUSED) +{ + return msp430_legitimate_address_p (mode, x, strict); +} + +#undef TARGET_ASM_INTEGER +#define TARGET_ASM_INTEGER msp430_asm_integer +static bool +msp430_asm_integer (rtx x, unsigned int size, int aligned_p) +{ + int c = GET_CODE (x); + + if (size == 3 && GET_MODE (x) == PSImode) + size = 4; + + switch (size) + { + case 4: + if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT) + { + fprintf (asm_out_file, "\t.long\t"); + output_addr_const (asm_out_file, x); + fputc ('\n', asm_out_file); + return true; + } + break; + } + return default_assemble_integer (x, size, aligned_p); +} + +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra +static bool +msp430_asm_output_addr_const_extra (FILE *file, rtx x) +{ + debug_rtx(x); + return false; +} + #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant static bool msp430_legitimate_constant (enum machine_mode mode, rtx x) { @@ -1740,12 +1822,39 @@ msp430_expand_eh_return (rtx eh_handler) tmp = gen_rtx_PLUS (Pmode, ap, sa); tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2); tmp = gen_rtx_MEM (Pmode, tmp); emit_move_insn (tmp, ra); } +#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA +#define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra +void +msp430_init_dwarf_reg_sizes_extra (tree address) +{ + int i; + rtx addr = expand_normal (address); + rtx mem = gen_rtx_MEM (BLKmode, addr); + + if (!msp430x) + return; + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + unsigned int dnum = DWARF_FRAME_REGNUM (i); + unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1); + + if (rnum < DWARF_FRAME_REGISTERS) + { + HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode); + + emit_move_insn (adjust_address (mem, QImode, offset), + gen_int_mode (4, QImode)); + } + } +} + /* This is a list of MD patterns that implement fixed-count shifts. */ static struct { const char *name; int count; int need_430x; @@ -2350,13 +2459,13 @@ msp430_print_operand (FILE * file, rtx o } break; case 'X': /* This is used to turn, for example, an ADD opcode into an ADDX opcode when we're using 20-bit addresses. */ - if (TARGET_LARGE) + if (TARGET_LARGE || GET_MODE (op) == PSImode) fprintf (file, "X"); /* We don't care which operand we use, but we want 'X' in the MD file, so we do it this way. */ return; case 'x': Index: gcc/config/msp430/msp430.h =================================================================== --- gcc/config/msp430/msp430.h (revision 213886) +++ gcc/config/msp430/msp430.h (working copy) @@ -128,16 +128,15 @@ extern bool msp430x; #define FRAME_GROWS_DOWNWARD 1 #define FIRST_PARM_OFFSET(FNDECL) 0 #define MAX_REGS_PER_ADDRESS 1 #define Pmode (TARGET_LARGE ? PSImode : HImode) -/* Note: 32 is a lie. Large pointers are actually 20-bits wide. But gcc - thinks that any non-power-of-2 pointer size equates to BLKmode, which - causes all kinds of problems... */ -#define POINTER_SIZE (TARGET_LARGE ? 32 : 16) +#define POINTER_SIZE (TARGET_LARGE ? 20 : 16) +/* This is just for .eh_frame, to match bfd. */ +#define PTR_SIZE (TARGET_LARGE ? 4 : 2) #define POINTERS_EXTEND_UNSIGNED 1 #define ADDR_SPACE_NEAR 1 #define ADDR_SPACE_FAR 2 #define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas() @@ -155,15 +154,15 @@ extern bool msp430x; (MODE) = HImode; #endif /* Layout of Source Language Data Types */ #undef SIZE_TYPE -#define SIZE_TYPE (TARGET_LARGE ? "long unsigned int" : "unsigned int") +#define SIZE_TYPE (TARGET_LARGE ? "__int20 unsigned" : "unsigned int") #undef PTRDIFF_TYPE -#define PTRDIFF_TYPE (TARGET_LARGE ? "long int" : "int") +#define PTRDIFF_TYPE (TARGET_LARGE ? "__int20" : "int") #undef WCHAR_TYPE #define WCHAR_TYPE "long int" #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE BITS_PER_WORD #define FUNCTION_MODE HImode #define CASE_VECTOR_MODE Pmode @@ -379,13 +378,13 @@ typedef struct #define JUMP_TABLES_IN_TEXT_SECTION 1 #undef DWARF2_ADDR_SIZE #define DWARF2_ADDR_SIZE 4 -#define INCOMING_FRAME_SP_OFFSET (POINTER_SIZE / BITS_PER_UNIT) +#define INCOMING_FRAME_SP_OFFSET (TARGET_LARGE ? 4 : 2) #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG #define DWARF2_ASM_LINE_DEBUG_INFO 1