eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 37
+#define FIRST_PSEUDO_REGISTER 53
/* Number of hardware registers that go into the DWARF-2 unwind info.
If not defined, equals FIRST_PSEUDO_REGISTER. */
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
- On the 80386, the stack pointer is such, as is the arg pointer. */
+ On the 80386, the stack pointer is such, as is the arg pointer.
+
+ The value is an mask - bit 1 is set for fixed registers
+ for 32bit target, while 2 is set for fixed registers for 64bit.
+ Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
+ */
#define FIXED_REGISTERS \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/ \
-{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
+{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, \
/*arg,flags,fpsr,dir,frame*/ \
- 1, 1, 1, 1, 1, \
+ 3, 3, 3, 3, 3, \
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
0, 0, 0, 0, 0, 0, 0, 0, \
/*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/ \
- 0, 0, 0, 0, 0, 0, 0, 0}
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* r8, r9, r10, r11, r12, r13, r14, r15*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1}
+
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
registers that can be used without being saved.
The latter must include the registers where values are returned
and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like. */
-
+ Aside from that, you can include as many other registers as you like.
+
+ The value is an mask - bit 1 is set for call used
+ for 32bit target, while 2 is set for call used for 64bit.
+ Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
+*/
#define CALL_USED_REGISTERS \
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/ \
-{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+{ 3, 3, 3, 0, 2, 2, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, \
/*arg,flags,fpsr,dir,frame*/ \
- 1, 1, 1, 1, 1, \
+ 3, 3, 3, 3, 3, \
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
- 1, 1, 1, 1, 1, 1, 1, 1, \
+ 3, 3, 3, 3, 3, 3, 3, 3, \
/*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/ \
- 1, 1, 1, 1, 1, 1, 1, 1}
+ 3, 3, 3, 3, 3, 3, 3, 3, \
+/* r8, r9, r10, r11, r12, r13, r14, r15*/ \
+ 3, 3, 3, 3, 1, 1, 1, 1, \
+/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
+ 3, 3, 3, 3, 3, 3, 3, 3} \
/* Order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. List frame pointer
generated by allocating edx first, so restore the 'natural' order of things. */
#define REG_ALLOC_ORDER \
-/*ax,dx,cx,bx,si,di,bp,sp*/ \
-{ 0, 1, 2, 3, 4, 5, 6, 7, \
-/*,arg,cc,fpsr,dir,frame*/ \
- 16,17, 18, 19, 20, \
+/*ax,dx,cx,*/ \
+{ 0, 1, 2, \
+/* bx,si,di,bp,sp,*/ \
+ 3, 4, 5, 6, 7, \
+/*r8,r9,r10,r11,*/ \
+ 37,38, 39, 40, \
+/*r12,r15,r14,r13*/ \
+ 41, 44, 43, 42, \
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
21, 22, 23, 24, 25, 26, 27, 28, \
+/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
+ 45, 46, 47, 48, 49, 50, 51, 52, \
/*st,st1,st2,st3,st4,st5,st6,st7*/ \
8, 9, 10, 11, 12, 13, 14, 15, \
+/*,arg,cc,fpsr,dir,frame*/ \
+ 16,17, 18, 19, 20, \
/*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/ \
29, 30, 31, 32, 33, 34, 35, 36 }
/* Macro to conditionally modify fixed_regs/call_used_regs. */
#define CONDITIONAL_REGISTER_USAGE \
{ \
+ int i; \
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) \
+ { \
+ fixed_regs[i] = (fixed_regs[i] & (TARGET_64BIT ? 2 : 1)) != 0; \
+ call_used_regs[i] = (call_used_regs[i] \
+ & (TARGET_64BIT ? 2 : 1)) != 0; \
+ } \
if (flag_pic) \
{ \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
#define FIRST_MMX_REG (LAST_SSE_REG + 1)
#define LAST_MMX_REG (FIRST_MMX_REG + 7)
+#define FIRST_REX_INT_REG (LAST_MMX_REG + 1)
+#define LAST_REX_INT_REG (FIRST_REX_INT_REG + 7)
+
+#define FIRST_REX_SSE_REG (LAST_REX_INT_REG + 1)
+#define LAST_REX_SSE_REG (FIRST_REX_SSE_REG + 7)
+
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms
may be accessed via the stack pointer) in functions that seem suitable.
Q_REGS, /* %eax %ebx %ecx %edx */
NON_Q_REGS, /* %esi %edi %ebp %esp */
INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */
- GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */
+ LEGACY_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */
+ GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp %r8 - %r15*/
FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */
FLOAT_REGS,
SSE_REGS,
"AD_REGS", \
"Q_REGS", "NON_Q_REGS", \
"INDEX_REGS", \
+ "LEGACY_REGS", \
"GENERAL_REGS", \
"FP_TOP_REG", "FP_SECOND_REG", \
"FLOAT_REGS", \
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
-{ { 0x00, 0x0 }, \
- { 0x01, 0x0 }, { 0x02, 0x0 }, /* AREG, DREG */ \
- { 0x04, 0x0 }, { 0x08, 0x0 }, /* CREG, BREG */ \
- { 0x10, 0x0 }, { 0x20, 0x0 }, /* SIREG, DIREG */ \
- { 0x03, 0x0 }, /* AD_REGS */ \
- { 0x0f, 0x0 }, /* Q_REGS */ \
- { 0x1100f0, 0x0 }, /* NON_Q_REGS */ \
- { 0x7f, 0x0 }, /* INDEX_REGS */ \
- { 0x1100ff, 0x0 }, /* GENERAL_REGS */ \
- { 0x100, 0x0 }, { 0x0200, 0x0 }, /* FP_TOP_REG, FP_SECOND_REG */ \
- { 0xff00, 0x0 }, /* FLOAT_REGS */ \
-{ 0x1fe00000, 0x0 }, /* SSE_REGS */ \
-{ 0xe0000000, 0x1f }, /* MMX_REGS */ \
-{ 0x1fe00100, 0x0 }, /* FP_TOP_SSE_REG */ \
-{ 0x1fe00200, 0x0 }, /* FP_SECOND_SSE_REG */ \
-{ 0x1fe0ff00, 0x0 }, /* FLOAT_SSE_REGS */ \
- { 0x1ffff, 0x0 }, /* FLOAT_INT_REGS */ \
-{ 0x1fe100ff, 0x0 }, /* INT_SSE_REGS */ \
-{ 0x1fe1ffff, 0x0 }, /* FLOAT_INT_SSE_REGS */ \
-{ 0xffffffff, 0x1f } \
+{ { 0x00, 0x0 }, \
+ { 0x01, 0x0 }, { 0x02, 0x0 }, /* AREG, DREG */ \
+ { 0x04, 0x0 }, { 0x08, 0x0 }, /* CREG, BREG */ \
+ { 0x10, 0x0 }, { 0x20, 0x0 }, /* SIREG, DIREG */ \
+ { 0x03, 0x0 }, /* AD_REGS */ \
+ { 0x0f, 0x0 }, /* Q_REGS */ \
+ { 0x1100f0, 0x1fe0 }, /* NON_Q_REGS */ \
+ { 0x7f, 0x1fe0 }, /* INDEX_REGS */ \
+ { 0x1100ff, 0x0 }, /* LEGACY_REGS */ \
+ { 0x1100ff, 0x1fe0 }, /* GENERAL_REGS */ \
+ { 0x100, 0x0 }, { 0x0200, 0x0 },/* FP_TOP_REG, FP_SECOND_REG */\
+ { 0xff00, 0x0 }, /* FLOAT_REGS */ \
+{ 0x1fe00000,0x1fe000 }, /* SSE_REGS */ \
+{ 0xe0000000, 0x1f }, /* MMX_REGS */ \
+{ 0x1fe00100,0x1fe000 }, /* FP_TOP_SSE_REG */ \
+{ 0x1fe00200,0x1fe000 }, /* FP_SECOND_SSE_REG */ \
+{ 0x1fe0ff00,0x1fe000 }, /* FLOAT_SSE_REGS */ \
+ { 0x1ffff, 0x1fe0 }, /* FLOAT_INT_REGS */ \
+{ 0x1fe100ff,0x1fffe0 }, /* INT_SSE_REGS */ \
+{ 0x1fe1ffff,0x1fffe0 }, /* FLOAT_INT_SSE_REGS */ \
+{ 0xffffffff,0x1fffff } \
}
/* The same information, inverted:
#define QI_REG_P(X) \
(REG_P (X) && REGNO (X) < 4)
+
+#define GENERAL_REGNO_P(n) \
+ ((n) < 8 || REX_INT_REGNO_P (n))
+
+#define GENERAL_REG_P(X) \
+ (REG_P (X) && GENERAL_REG_REGNO_P (X))
+
+#define ANY_QI_REG_P(X) (TARGET_64BIT ? GENERAL_REG_P(X) : QI_REG_P (X))
+
#define NON_QI_REG_P(X) \
(REG_P (X) && REGNO (X) >= 4 && REGNO (X) < FIRST_PSEUDO_REGISTER)
+#define REX_INT_REGNO_P(n) ((n) >= FIRST_REX_INT_REG && (n) <= LAST_REX_INT_REG)
+#define REX_INT_REG_P(X) (REG_P (X) && REX_INT_REGNO_P (REGNO (X)))
+
#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
#define FP_REGNO_P(n) ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG)
#define ANY_FP_REG_P(X) (REG_P (X) && ANY_FP_REGNO_P (REGNO (X)))
#define ANY_FP_REGNO_P(n) (FP_REGNO_P (n) || SSE_REGNO_P (n))
-#define SSE_REGNO_P(n) ((n) >= FIRST_SSE_REG && (n) <= LAST_SSE_REG)
+#define SSE_REGNO_P(n) \
+ (((n) >= FIRST_SSE_REG && (n) <= LAST_SSE_REG) \
+ || ((n) >= FIRST_REX_SSE_REG && (n) <= LAST_REX_SSE_REG))
+
+#define SSE_REGNO(n) \
+ ((n) < 8 ? FIRST_SSE_REG + (n) : FIRST_REX_SSE_REG + (n) - 8)
#define SSE_REG_P(n) (REG_P (n) && SSE_REGNO_P (REGNO (n)))
#define SSE_FLOAT_MODE_P(m) \
#define REG_CLASS_FROM_LETTER(C) \
((C) == 'r' ? GENERAL_REGS : \
- (C) == 'q' ? Q_REGS : \
+ (C) == 'R' ? LEGACY_REGS : \
+ (C) == 'q' ? TARGET_64BIT ? GENERAL_REGS : Q_REGS : \
+ (C) == 'Q' ? Q_REGS : \
(C) == 'f' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 \
? FLOAT_REGS \
: NO_REGS) : \
Since they use reg_renumber, they are safe only once reg_renumber
has been allocated, which happens in local-alloc.c. */
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < STACK_POINTER_REGNUM \
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ ((REGNO) < STACK_POINTER_REGNUM \
+ || (REGNO >= FIRST_REX_INT_REG \
+ && (REGNO) <= LAST_REX_INT_REG) \
+ || ((unsigned) reg_renumber[REGNO] >= FIRST_REX_INT_REG \
+ && (unsigned) reg_renumber[REGNO] <= LAST_REX_INT_REG) \
|| (unsigned) reg_renumber[REGNO] < STACK_POINTER_REGNUM)
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) <= STACK_POINTER_REGNUM \
- || (REGNO) == ARG_POINTER_REGNUM \
- || (REGNO) == FRAME_POINTER_REGNUM \
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ ((REGNO) <= STACK_POINTER_REGNUM \
+ || (REGNO) == ARG_POINTER_REGNUM \
+ || (REGNO) == FRAME_POINTER_REGNUM \
+ || (REGNO >= FIRST_REX_INT_REG \
+ && (REGNO) <= LAST_REX_INT_REG) \
+ || ((unsigned) reg_renumber[REGNO] >= FIRST_REX_INT_REG \
+ && (unsigned) reg_renumber[REGNO] <= LAST_REX_INT_REG) \
|| (unsigned) reg_renumber[REGNO] <= STACK_POINTER_REGNUM)
#define REGNO_OK_FOR_SIREG_P(REGNO) ((REGNO) == 4 || reg_renumber[REGNO] == 4)
/* Non strict versions, pseudos are ok */
#define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
(REGNO (X) < STACK_POINTER_REGNUM \
+ || (REGNO (X) >= FIRST_REX_INT_REG \
+ && REGNO (X) <= LAST_REX_INT_REG) \
|| REGNO (X) >= FIRST_PSEUDO_REGISTER)
#define REG_OK_FOR_BASE_NONSTRICT_P(X) \
(REGNO (X) <= STACK_POINTER_REGNUM \
|| REGNO (X) == ARG_POINTER_REGNUM \
- || REGNO (X) == FRAME_POINTER_REGNUM \
+ || REGNO (X) == FRAME_POINTER_REGNUM \
+ || (REGNO (X) >= FIRST_REX_INT_REG \
+ && REGNO (X) <= LAST_REX_INT_REG) \
|| REGNO (X) >= FIRST_PSEUDO_REGISTER)
-#define REG_OK_FOR_STRREG_NONSTRICT_P(X) \
- (REGNO (X) == 4 || REGNO (X) == 5 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
/* Strict versions, hard registers only */
#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_STRREG_STRICT_P(X) \
- (REGNO_OK_FOR_DIREG_P (REGNO (X)) || REGNO_OK_FOR_SIREG_P (REGNO (X)))
#ifndef REG_OK_STRICT
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
-#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_NONSTRICT_P(X)
#else
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
-#define REG_OK_FOR_STRREG_P(X) REG_OK_FOR_STRREG_STRICT_P(X)
#endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","", \
"flags","fpsr", "dirflag", "frame", \
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \
- "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" , \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}
#define REGISTER_NAMES HI_REGISTER_NAMES
#define ADDITIONAL_REGISTER_NAMES \
{ { "eax", 0 }, { "edx", 1 }, { "ecx", 2 }, { "ebx", 3 }, \
{ "esi", 4 }, { "edi", 5 }, { "ebp", 6 }, { "esp", 7 }, \
+ { "rax", 0 }, { "rdx", 1 }, { "rcx", 2 }, { "rbx", 3 }, \
+ { "rsi", 4 }, { "rdi", 5 }, { "rbp", 6 }, { "rsp", 7 }, \
{ "al", 0 }, { "dl", 1 }, { "cl", 2 }, { "bl", 3 }, \
{ "ah", 0 }, { "dh", 1 }, { "ch", 2 }, { "bh", 3 }, \
{ "mm0", 8}, { "mm1", 9}, { "mm2", 10}, { "mm3", 11}, \
number as al, and ax.
*/
-/* note the last four are not really qi_registers, but
- the md will have to never output movb into one of them
- only a movw . There is no movb into the last four regs */
-
#define QI_REGISTER_NAMES \
-{"al", "dl", "cl", "bl", "si", "di", "bp", "sp",}
+{"al", "dl", "cl", "bl", "sil", "dil", "bpl", "spl",}
/* These parallel the array above, and can be used to access bits 8:15
of regs 0 through 3. */
If CODE is 'w', pretend the mode is HImode.
If CODE is 'b', pretend the mode is QImode.
If CODE is 'k', pretend the mode is SImode.
+ If CODE is 'd', pretend the mode is DImode.
If CODE is 'h', pretend the reg is the `high' byte register.
If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
{ fputs ("st(0)", FILE); break; } \
if (FP_REG_P (X)) \
{ fputs (hi_name[REGNO(X)], FILE); break; } \
+ if (REX_INT_REG_P (X)) \
+ { \
+ switch (GET_MODE_SIZE (GET_MODE (X))) \
+ { \
+ default: \
+ case 8: \
+ fprintf (FILE, "r%i", REGNO (X) \
+ - FIRST_REX_INT_REG + 8); \
+ break; \
+ case 4: \
+ fprintf (FILE, "r%id", REGNO (X) \
+ - FIRST_REX_INT_REG + 8); \
+ break; \
+ case 2: \
+ fprintf (FILE, "r%iw", REGNO (X) \
+ - FIRST_REX_INT_REG + 8); \
+ break; \
+ case 1: \
+ fprintf (FILE, "r%ib", REGNO (X) \
+ - FIRST_REX_INT_REG + 8); \
+ break; \
+ } \
+ break; \
+ } \
switch (GET_MODE_SIZE (GET_MODE (X))) \
{ \
+ case 8: \
+ fputs ("r", FILE); \
+ fputs (hi_name[REGNO (X)], FILE); \
+ break; \
default: \
fputs ("e", FILE); \
case 2: \