This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: __intN patch 5/5: msp430-specific changes
- From: DJ Delorie <dj at redhat dot com>
- To: DJ Delorie <dj at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 14 Oct 2014 17:35:05 -0400
- Subject: Re: __intN patch 5/5: msp430-specific changes
- Authentication-results: sourceware.org; auth=none
- References: <201408132211 dot s7DMBqaQ016409 at greed dot delorie dot com>
> 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
>
>