summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartynas Venckus <martynas@cvs.openbsd.org>2008-08-27 00:31:02 +0000
committerMartynas Venckus <martynas@cvs.openbsd.org>2008-08-27 00:31:02 +0000
commit956619bc344de12d953fdca78c7ecc3086bf4f78 (patch)
treef4d96183629eac8cdca64dee3f0ed0aa3af07e39
parent93c807fc38f9d2792768aecf961cb07e1a8d0b26 (diff)
fix 128-bit division. gcc mangled arguments when passing to the
__udivti3, because MUST_PASS_IN_STACK always returned 1 on amd64; pr#5780 reported by Simon Kuhnle tested by Simon Kuhnle, sthen@, brad@ double-checked & tweak from miod@ ok sthen@, brad@
-rw-r--r--gnu/usr.bin/gcc/gcc/calls.c42
-rw-r--r--gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h1
-rw-r--r--gnu/usr.bin/gcc/gcc/config/i386/i386.c15
-rw-r--r--gnu/usr.bin/gcc/gcc/config/i386/i386.h56
-rw-r--r--gnu/usr.bin/gcc/gcc/expr.h31
5 files changed, 100 insertions, 45 deletions
diff --git a/gnu/usr.bin/gcc/gcc/calls.c b/gnu/usr.bin/gcc/gcc/calls.c
index 8c3ad6e837e..fb9d3a2d4b8 100644
--- a/gnu/usr.bin/gcc/gcc/calls.c
+++ b/gnu/usr.bin/gcc/gcc/calls.c
@@ -4694,3 +4694,45 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space)
return sibcall_failure;
}
+
+/* Nonzero if we do not know how to pass TYPE solely in registers.
+ We cannot do so in the following cases:
+
+ - if the type has variable size
+ - if the type is marked as addressable (it is required to be constructed
+ into the stack)
+ - if the padding and mode of the type is such that a copy into a register
+ would put it into the wrong part of the register.
+
+ Which padding can't be supported depends on the byte endianness.
+
+ A value in a register is implicitly padded at the most significant end.
+ On a big-endian machine, that is the lower end in memory.
+ So a value padded in memory at the upper end can't go in a register.
+ For a little-endian machine, the reverse is true. */
+
+bool
+default_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+ if (!type)
+ return false;
+
+ /* If the type has variable size... */
+ if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ return true;
+
+ /* If the type is marked as addressable (it is required
+ to be constructed into the stack)... */
+ if (TREE_ADDRESSABLE (type))
+ return true;
+
+ /* If the padding and mode of the type is such that a copy into
+ a register would put it into the wrong part of the register. */
+ if (mode == BLKmode
+ && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
+ && (FUNCTION_ARG_PADDING (mode, type)
+ == (BYTES_BIG_ENDIAN ? upward : downward)))
+ return true;
+
+ return false;
+}
diff --git a/gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h b/gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h
index b5ddb37bb2a..1c1d650a8cc 100644
--- a/gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h
+++ b/gnu/usr.bin/gcc/gcc/config/i386/i386-protos.h
@@ -221,6 +221,7 @@ extern int x86_field_alignment PARAMS ((tree, int));
extern rtx ix86_tls_get_addr PARAMS ((void));
extern void x86_machine_dependent_reorg PARAMS ((rtx));
+extern bool ix86_must_pass_in_stack PARAMS ((enum machine_mode mode, tree));
/* In winnt.c */
extern int i386_pe_dllexport_name_p PARAMS ((const char *));
diff --git a/gnu/usr.bin/gcc/gcc/config/i386/i386.c b/gnu/usr.bin/gcc/gcc/config/i386/i386.c
index ba0b78c822d..a94bc410f22 100644
--- a/gnu/usr.bin/gcc/gcc/config/i386/i386.c
+++ b/gnu/usr.bin/gcc/gcc/config/i386/i386.c
@@ -1727,6 +1727,10 @@ classify_argument (mode, type, classes, bit_offset)
if (bytes < 0)
return 0;
+ if (mode != VOIDmode
+ && MUST_PASS_IN_STACK (mode, type))
+ return 0;
+
if (type && AGGREGATE_TYPE_P (type))
{
int i;
@@ -14812,4 +14816,15 @@ x86_machine_dependent_reorg (first)
}
}
+/* Return if we do not know how to pass TYPE solely in registers. */
+bool
+ix86_must_pass_in_stack (mode, type)
+ enum machine_mode mode;
+ tree type;
+{
+ if (default_must_pass_in_stack (mode, type))
+ return true;
+ return (!TARGET_64BIT && type && mode == TImode);
+}
+
#include "gt-i386.h"
diff --git a/gnu/usr.bin/gcc/gcc/config/i386/i386.h b/gnu/usr.bin/gcc/gcc/config/i386/i386.h
index ead133bfb62..f8d521df5fd 100644
--- a/gnu/usr.bin/gcc/gcc/config/i386/i386.h
+++ b/gnu/usr.bin/gcc/gcc/config/i386/i386.h
@@ -114,10 +114,11 @@ extern int target_flags;
#define MASK_MMX 0x00002000 /* Support MMX regs/builtins */
#define MASK_SSE 0x00004000 /* Support SSE regs/builtins */
#define MASK_SSE2 0x00008000 /* Support SSE2 regs/builtins */
-#define MASK_3DNOW 0x00010000 /* Support 3Dnow builtins */
-#define MASK_3DNOW_A 0x00020000 /* Support Athlon 3Dnow builtins */
-#define MASK_128BIT_LONG_DOUBLE 0x00040000 /* long double size is 128bit */
-#define MASK_64BIT 0x00080000 /* Produce 64bit code */
+#define MASK_SSE3 0x00010000 /* Support SSE3 builtins */
+#define MASK_3DNOW 0x00020000 /* Support 3Dnow builtins */
+#define MASK_3DNOW_A 0x00040000 /* Support Athlon 3Dnow builtins */
+#define MASK_128BIT_LONG_DOUBLE 0x00080000 /* long double size is 128bit */
+#define MASK_64BIT 0x00100000 /* Produce 64bit code */
/* Unused: 0x03f0000 */
@@ -271,8 +272,9 @@ extern int x86_prefetch_sse;
#define ASSEMBLER_DIALECT (ix86_asm_dialect)
-#define TARGET_SSE ((target_flags & (MASK_SSE | MASK_SSE2)) != 0)
+#define TARGET_SSE ((target_flags & MASK_SSE) != 0)
#define TARGET_SSE2 ((target_flags & MASK_SSE2) != 0)
+#define TARGET_SSE3 ((target_flags & MASK_SSE3) != 0)
#define TARGET_SSE_MATH ((ix86_fpmath & FPMATH_SSE) != 0)
#define TARGET_MIX_SSE_I387 ((ix86_fpmath & FPMATH_SSE) \
&& (ix86_fpmath & FPMATH_387))
@@ -300,6 +302,8 @@ extern int x86_prefetch_sse;
{ "486", 0, "" /*Deprecated.*/}, \
{ "pentium", 0, "" /*Deprecated.*/}, \
{ "pentiumpro", 0, "" /*Deprecated.*/}, \
+ { "pni", 0, "" /*Deprecated.*/}, \
+ { "no-pni", 0, "" /*Deprecated.*/}, \
{ "intel-syntax", 0, "" /*Deprecated.*/}, \
{ "no-intel-syntax", 0, "" /*Deprecated.*/}, \
{ "rtd", MASK_RTD, \
@@ -366,6 +370,10 @@ extern int x86_prefetch_sse;
N_("Support MMX, SSE and SSE2 built-in functions and code generation") }, \
{ "no-sse2", -MASK_SSE2, \
N_("Do not support MMX, SSE and SSE2 built-in functions and code generation") }, \
+ { "sse3", MASK_SSE3, \
+ N_("Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation") }, \
+ { "no-sse3", -MASK_SSE3, \
+ N_("Do not support MMX, SSE, SSE2 and SSE3 built-in functions and code generation") }, \
{ "128bit-long-double", MASK_128BIT_LONG_DOUBLE, \
N_("sizeof(long double) is 16") }, \
{ "96bit-long-double", -MASK_128BIT_LONG_DOUBLE, \
@@ -469,6 +477,10 @@ extern int x86_prefetch_sse;
%n`-mpentium' is deprecated. Use `-march=pentium' or `-mcpu=pentium' instead.\n} \
%{mpentiumpro:-mcpu=pentiumpro \
%n`-mpentiumpro' is deprecated. Use `-march=pentiumpro' or `-mcpu=pentiumpro' instead.\n}} \
+%{mpni:-msse3 \
+%n`-mpni' is deprecated. Use `-msse3' instead.\n} \
+%{mno-pni:-mno-sse3 \
+%n`-mno-pni' is deprecated. Use `-mno-sse3' instead.\n} \
%{mintel-syntax:-masm=intel \
%n`-mintel-syntax' is deprecated. Use `-masm=intel' instead.\n} \
%{mno-intel-syntax:-masm=att \
@@ -554,6 +566,11 @@ extern int x86_prefetch_sse;
builtin_define ("__SSE__"); \
if (TARGET_SSE2) \
builtin_define ("__SSE2__"); \
+ if (TARGET_SSE3) \
+ { \
+ builtin_define ("__SSE3__"); \
+ builtin_define ("__PNI__"); \
+ } \
if (TARGET_SSE_MATH && TARGET_SSE) \
builtin_define ("__SSE_MATH__"); \
if (TARGET_SSE_MATH && TARGET_SSE2) \
@@ -1621,18 +1638,7 @@ enum reg_class
definition that is usually appropriate, refer to expr.h for additional
documentation. If `REG_PARM_STACK_SPACE' is defined, the argument will be
computed in the stack and then loaded into a register. */
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE) \
- || ((MODE) == TImode) \
- || ((MODE) == BLKmode \
- && ! ((TYPE) != 0 \
- && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
- && 0 == (int_size_in_bytes (TYPE) \
- % (PARM_BOUNDARY / BITS_PER_UNIT))) \
- && (FUNCTION_ARG_PADDING (MODE, TYPE) \
- == (BYTES_BIG_ENDIAN ? upward : downward)))))
+#define MUST_PASS_IN_STACK(MODE, TYPE) ix86_must_pass_in_stack ((MODE), (TYPE))
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
@@ -2480,6 +2486,22 @@ enum ix86_builtins
IX86_BUILTIN_MFENCE,
IX86_BUILTIN_LFENCE,
+ /* Prescott New Instructions. */
+ IX86_BUILTIN_ADDSUBPS,
+ IX86_BUILTIN_HADDPS,
+ IX86_BUILTIN_HSUBPS,
+ IX86_BUILTIN_MOVSHDUP,
+ IX86_BUILTIN_MOVSLDUP,
+ IX86_BUILTIN_ADDSUBPD,
+ IX86_BUILTIN_HADDPD,
+ IX86_BUILTIN_HSUBPD,
+ IX86_BUILTIN_LOADDDUP,
+ IX86_BUILTIN_MOVDDUP,
+ IX86_BUILTIN_LDDQU,
+
+ IX86_BUILTIN_MONITOR,
+ IX86_BUILTIN_MWAIT,
+
IX86_BUILTIN_MAX
};
diff --git a/gnu/usr.bin/gcc/gcc/expr.h b/gnu/usr.bin/gcc/gcc/expr.h
index c38cd9946c9..c6b1e2385ba 100644
--- a/gnu/usr.bin/gcc/gcc/expr.h
+++ b/gnu/usr.bin/gcc/gcc/expr.h
@@ -159,34 +159,9 @@ enum direction {none, upward, downward}; /* Value has this type. */
#define PRETEND_OUTGOING_VARARGS_NAMED 0
#endif
-/* Nonzero if we do not know how to pass TYPE solely in registers.
- We cannot do so in the following cases:
-
- - if the type has variable size
- - if the type is marked as addressable (it is required to be constructed
- into the stack)
- - if the padding and mode of the type is such that a copy into a register
- would put it into the wrong part of the register.
-
- Which padding can't be supported depends on the byte endianness.
-
- A value in a register is implicitly padded at the most significant end.
- On a big-endian machine, that is the lower end in memory.
- So a value padded in memory at the upper end can't go in a register.
- For a little-endian machine, the reverse is true. */
-
-#ifndef MUST_PASS_IN_STACK
-#define MUST_PASS_IN_STACK(MODE,TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE) \
- || ((MODE) == BLKmode \
- && ! ((TYPE) != 0 && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
- && 0 == (int_size_in_bytes (TYPE) \
- % (PARM_BOUNDARY / BITS_PER_UNIT))) \
- && (FUNCTION_ARG_PADDING (MODE, TYPE) \
- == (BYTES_BIG_ENDIAN ? upward : downward)))))
-#endif
+/* Nonzero if we do not know how to pass TYPE solely in registers. */
+extern bool default_must_pass_in_stack PARAMS((enum machine_mode, tree));
+#define MUST_PASS_IN_STACK(MODE,TYPE) default_must_pass_in_stack(MODE, TYPE)
/* Nonzero if type TYPE should be returned in memory.
Most machines can use the following default definition. */