This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] msp430 support for intN patch
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 14 Apr 2014 19:13:49 -0400
- Subject: [patch] msp430 support for intN patch
- Authentication-results: sourceware.org; auth=none
Third patch. This one adds support for the new __intN
framework in my first patch:
http://gcc.gnu.org/ml/gcc-patches/2014-04/msg00723.html
I'll apply this after the __intN patch is approved, but I'm providing
it here to assist with testing and/or understanding the __intN patch.
* config/msp430/msp430-protos.h (msp430_hard_regno_nregs_has_padding):
Declare.
(msp430_hard_regno_nregs_with_padding): Declare.
* config/msp430/msp430.md (movpsi): Adjust pattern to allow for
psi-mode moves in small model.
(movsipsi2): Likewise.
(extendhipsi2): Likewise.
(zero_extendhisi2): Likewise.
(extend_and_shift1_hipsi2): Likewise.
(extend_and_shift2_hipsi2): Likewise.
(extendpsisi2): Likewise.
(*bitbranch<mode>4): Likewise.
* config/msp430/msp430.c (TARGET_SCALAR_MODE_SUPPORTED_P): Define.
(msp430_scalar_mode_supported_p): New.
(msp430_hard_regno_nregs_has_padding): New.
(msp430_hard_regno_nregs_with_padding): New.
(TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P): Define.
(msp430_addr_space_legitimate_address_p): New.
(TARGET_ASM_INTEGER): Define.
(msp430_asm_integer): New.
(msp430_print_operand): Fix 'X' suffix printing.
* config/msp430/msp430-modes.def (PSI): Add INT_N for 20-bit
modes.
* config/msp430/msp430.h (POINTER_SIZE): Change from 32 to 20 bits.
(SIZE_TYPE): Use unsigned __int20 type.
(PTRDIFF_TYPE): Use __int20 type.
Index: config/msp430/msp430-protos.h
===================================================================
--- config/msp430/msp430-protos.h (revision 209391)
+++ config/msp430/msp430-protos.h (working copy)
@@ -27,12 +27,14 @@ 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_f5_mcu (void);
bool msp430_is_interrupt_func (void);
Index: config/msp430/msp430.md
===================================================================
--- config/msp430/msp430.md (revision 209391)
+++ config/msp430/msp430.md (working copy)
@@ -211,27 +211,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
@@ -555,49 +555,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
@@ -630,13 +630,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. */
@@ -1159,13 +1159,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: config/msp430/msp430.c
===================================================================
--- config/msp430/msp430.c (revision 209391)
+++ config/msp430/msp430.c (working copy)
@@ -254,12 +254,23 @@ 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;
+ 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
@@ -283,12 +294,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));
@@ -820,12 +852,46 @@ 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);
+
+ 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_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
static bool
msp430_legitimate_constant (enum machine_mode mode, rtx x)
{
@@ -2176,13 +2242,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: config/msp430/msp430-modes.def
===================================================================
--- config/msp430/msp430-modes.def (revision 209391)
+++ config/msp430/msp430-modes.def (working copy)
@@ -1,3 +1,4 @@
/* 20-bit address */
PARTIAL_INT_MODE (SI, 20, PSI);
+INT_N (PSI, 20);
Index: config/msp430/msp430.h
===================================================================
--- config/msp430/msp430.h (revision 209391)
+++ config/msp430/msp430.h (working copy)
@@ -131,13 +131,13 @@ extern bool msp430x;
#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)
#define POINTERS_EXTEND_UNSIGNED 1
#define ADDR_SPACE_NEAR 1
#define ADDR_SPACE_FAR 2
#define REGISTER_TARGET_PRAGMAS() msp430_register_pragmas()
@@ -155,15 +155,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