summaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.c')
-rw-r--r--gcc/config/i386/i386.c153
1 files changed, 151 insertions, 2 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 722d52e2d9b..0eb9d95303b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -247,7 +247,11 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
/* arg pointer */
NON_Q_REGS,
/* flags, fpsr, dirflag, frame */
- NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS
+ NO_REGS, NO_REGS, NO_REGS, NON_Q_REGS,
+ SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS, SSE_REGS,
+ SSE_REGS, SSE_REGS,
+ MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS, MMX_REGS,
+ MMX_REGS, MMX_REGS
};
/* The "default" register map. */
@@ -257,6 +261,8 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
0, 2, 1, 3, 6, 7, 4, 5, /* general regs */
12, 13, 14, 15, 16, 17, 18, 19, /* fp regs */
-1, -1, -1, -1, /* arg, flags, fpsr, dir */
+ 21, 22, 23, 24, 25, 26, 27, 28, /* SSE */
+ 29, 30, 31, 32, 33, 34, 35, 36, /* MMX */
};
/* Define the register numbers to be used in Dwarf debugging information.
@@ -318,6 +324,8 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
0, 2, 1, 3, 6, 7, 5, 4, /* general regs */
11, 12, 13, 14, 15, 16, 17, 18, /* fp regs */
-1, 9, -1, -1, /* arg, flags, fpsr, dir */
+ 21, 22, 23, 24, 25, 26, 27, 28, /* SSE registers */
+ 29, 30, 31, 32, 33, 34, 35, 36, /* MMX registers */
};
@@ -625,6 +633,11 @@ override_options ()
/* If we're planning on using `loop', use it. */
if (TARGET_USE_LOOP && optimize)
flag_branch_on_count_reg = 1;
+
+ /* It makes no sense to ask for just SSE builtins, so MMX is also turned
+ on by -msse. */
+ if (TARGET_SSE)
+ target_flags |= MASK_MMX;
}
/* A C statement (sans semicolon) to choose the order in which to
@@ -3092,11 +3105,16 @@ print_reg (x, code, file)
code = 3;
else if (code == 'h')
code = 0;
+ else if (code == 'm' || MMX_REG_P (x))
+ code = 5;
else
code = GET_MODE_SIZE (GET_MODE (x));
switch (code)
{
+ case 5:
+ fputs (hi_reg_name[REGNO (x)], file);
+ break;
case 3:
if (STACK_TOP_P (x))
{
@@ -3110,6 +3128,7 @@ print_reg (x, code, file)
if (! FP_REG_P (x))
putc ('e', file);
/* FALLTHRU */
+ case 16:
case 2:
fputs (hi_reg_name[REGNO (x)], file);
break;
@@ -3139,7 +3158,8 @@ print_reg (x, code, file)
w -- likewise, print the HImode name of the register.
k -- likewise, print the SImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
- y -- print "st(0)" instead of "st" as a register. */
+ y -- print "st(0)" instead of "st" as a register.
+ m -- print "st(n)" as an mmx register. */
void
print_operand (file, x, code)
@@ -3243,6 +3263,7 @@ print_operand (file, x, code)
case 'k':
case 'h':
case 'y':
+ case 'm':
case 'X':
case 'P':
break;
@@ -3297,6 +3318,7 @@ print_operand (file, x, code)
case 4: size = "DWORD"; break;
case 8: size = "QWORD"; break;
case 12: size = "XWORD"; break;
+ case 16: size = "XMMWORD"; break;
default:
abort ();
}
@@ -5440,6 +5462,8 @@ ix86_split_to_parts (operand, parts, mode)
{
int size = GET_MODE_SIZE (mode) / 4;
+ if (GET_CODE (operand) == REG && MMX_REGNO_P (REGNO (operand)))
+ abort ();
if (size < 2 || size > 3)
abort ();
@@ -6863,3 +6887,128 @@ ix86_variable_issue (dump, sched_verbose, insn, can_issue_more)
return --ix86_sched_data.ppro.issued_this_cycle;
}
}
+
+/* Compute the alignment given to a constant that is being placed in memory.
+ EXP is the constant and ALIGN is the alignment that the object would
+ ordinarily have.
+ The value of this function is used instead of that alignment to align
+ the object. */
+
+int
+ix86_constant_alignment (exp, align)
+ tree exp;
+ int align;
+{
+ if (TREE_CODE (exp) == REAL_CST)
+ {
+ if (TYPE_MODE (TREE_TYPE (exp)) == DFmode && align < 64)
+ return 64;
+ else if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (exp))) && align < 128)
+ return 128;
+ }
+ else if (TREE_CODE (exp) == STRING_CST && TREE_STRING_LENGTH (exp) >= 31
+ && align < 256)
+ return 256;
+
+ return align;
+}
+
+/* Compute the alignment for a static variable.
+ TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this function is used
+ instead of that alignment to align the object. */
+
+int
+ix86_data_alignment (type, align)
+ tree type;
+ int align;
+{
+ if (AGGREGATE_TYPE_P (type)
+ && TYPE_SIZE (type)
+ && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+ && (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 256
+ || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 256)
+ return 256;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
+ return 128;
+ }
+ else if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+
+ if (TYPE_MODE (type) == DCmode && align < 64)
+ return 64;
+ if (TYPE_MODE (type) == XCmode && align < 128)
+ return 128;
+ }
+ else if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
+ && TYPE_FIELDS (type))
+ {
+ if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
+ return 128;
+ }
+ else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
+ || TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (TYPE_MODE (type) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
+ return 128;
+ }
+
+ return align;
+}
+
+/* Compute the alignment for a local variable.
+ TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object. */
+
+int
+ix86_local_alignment (type, align)
+ tree type;
+ int align;
+{
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ if (TYPE_MODE (TREE_TYPE (type)) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (TYPE_MODE (TREE_TYPE (type))) && align < 128)
+ return 128;
+ }
+ else if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ if (TYPE_MODE (type) == DCmode && align < 64)
+ return 64;
+ if (TYPE_MODE (type) == XCmode && align < 128)
+ return 128;
+ }
+ else if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE)
+ && TYPE_FIELDS (type))
+ {
+ if (DECL_MODE (TYPE_FIELDS (type)) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (DECL_MODE (TYPE_FIELDS (type))) && align < 128)
+ return 128;
+ }
+ else if (TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == VECTOR_TYPE
+ || TREE_CODE (type) == INTEGER_TYPE)
+ {
+
+ if (TYPE_MODE (type) == DFmode && align < 64)
+ return 64;
+ if (ALIGN_MODE_128 (TYPE_MODE (type)) && align < 128)
+ return 128;
+ }
+ return align;
+}