summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/rs6000/eabi-ci.asm5
-rw-r--r--gcc/config/rs6000/eabi-cn.asm5
-rw-r--r--gcc/config/rs6000/eabi.asm27
-rw-r--r--gcc/config/rs6000/rs6000.c7
-rw-r--r--gcc/config/rs6000/rs6000.md47
-rw-r--r--gcc/ginclude/va-ppc.h13
6 files changed, 59 insertions, 45 deletions
diff --git a/gcc/config/rs6000/eabi-ci.asm b/gcc/config/rs6000/eabi-ci.asm
index 5d3d347a595..4c2872145c0 100644
--- a/gcc/config/rs6000/eabi-ci.asm
+++ b/gcc/config/rs6000/eabi-ci.asm
@@ -97,3 +97,8 @@ _SDA2_BASE_ = .+32768
.globl __SBSS2_START__
.type __SBSS2_START__,@object
__SBSS2_START__:
+
+ .section ".gcc_except_table","aw"
+ .globl __EXCEPT_START__
+ .type __EXCEPT_START__,@object
+__EXCEPT_START__:
diff --git a/gcc/config/rs6000/eabi-cn.asm b/gcc/config/rs6000/eabi-cn.asm
index f3ed0e638f0..e9ea7f62ff4 100644
--- a/gcc/config/rs6000/eabi-cn.asm
+++ b/gcc/config/rs6000/eabi-cn.asm
@@ -95,3 +95,8 @@ __SDATA2_END__:
.globl __SBSS2_END__
.type __SBSS2_END__,@object
__SBSS2_END__:
+
+ .section ".gcc_except_table","aw"
+ .globl __EXCEPT_END__
+ .type __EXCEPT_END__,@object
+__EXCEPT_END__:
diff --git a/gcc/config/rs6000/eabi.asm b/gcc/config/rs6000/eabi.asm
index e5483ed759a..c69dfefe424 100644
--- a/gcc/config/rs6000/eabi.asm
+++ b/gcc/config/rs6000/eabi.asm
@@ -90,6 +90,12 @@
.Ldtore = .-.LCTOC1
.long __DTOR_END__ /* end of .dtor section */
+.Lexcepts = .-.LCTOC1
+ .long __EXCEPT_START__ /* start of .gcc_except_table section */
+
+.Lexcepte = .-.LCTOC1
+ .long __EXCEPT_END__ /* end of .gcc_except_table section */
+
.Linit = .-.LCTOC1
.long .Linit_p /* address of variable to say we've been called */
@@ -182,7 +188,7 @@ FUNC_START(__eabi)
lwz 4,.Ldtore(11) /* destructors pointers end */
cmpw 1,3,4 /* any pointers to adjust */
- bc 12,6,.Lfix
+ bc 12,6,.Lexcept
.Ldloop:
lwz 5,0(3) /* next pointer */
@@ -192,6 +198,25 @@ FUNC_START(__eabi)
cmpw 1,3,4 /* more pointers to adjust? */
bc 4,6,.Ldloop
+/* Fixup the .gcc_except_table section for G++ exceptions */
+
+.Lexcept:
+ lwz 3,.Lexcepts(11) /* exception table pointers start */
+ lwz 4,.Lexcepte(11) /* exception table pointers end */
+
+ cmpw 1,3,4 /* any pointers to adjust */
+ bc 12,6,.Lfix
+
+.Leloop:
+ lwz 5,0(3) /* next pointer */
+ addi 3,3,4 /* bump to next word */
+ cmpi 1,5,0
+ beq 1,.Leloop /* if NULL pointer, don't adjust */
+ add 5,5,12 /* adjust */
+ stw 5,-4(3)
+ cmpw 1,3,4 /* more pointers to adjust? */
+ bc 4,6,.Leloop
+
/* Fixup any user initialized pointers now (the compiler drops pointers to */
/* each of the relocs that it does in the .fixup section). */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7e630828133..ae045450b71 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -900,13 +900,18 @@ init_cumulative_args (cum, fntype, libname, incoming)
of an argument with the specified mode and type. If it is not defined,
PARM_BOUNDARY is used for all arguments.
- Windows NT wants anything >= 8 bytes to be double word aligned. */
+ Windows NT wants anything >= 8 bytes to be double word aligned.
+
+ V.4 wants long longs to be double word aligned. */
int
function_arg_boundary (mode, type)
enum machine_mode mode;
tree type;
{
+ if (DEFAULT_ABI == ABI_V4 && mode == DImode)
+ return 64;
+
if (DEFAULT_ABI != ABI_NT || TARGET_64BIT)
return PARM_BOUNDARY;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 1be7f52e598..b2dec1a338e 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -3618,23 +3618,11 @@
;; (for example, having an input in 7,8 and an output in 6,7). We
;; also allow for the the output being the same as one of the inputs.
-(define_expand "adddi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" "")))]
- ""
- "
-{
- if (! TARGET_POWER && ! TARGET_POWERPC64
- && short_cint_operand (operands[2], DImode))
- FAIL;
-}")
-
-(define_insn ""
+(define_insn "adddi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r")
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,0,0")
(match_operand:DI 2 "reg_or_short_operand" "r,I,r,I")))]
- "TARGET_POWER && ! TARGET_POWERPC64"
+ "! TARGET_POWERPC64"
"@
{a|addc} %L0,%L1,%L2\;{ae|adde} %0,%1,%2
{ai|addic} %L0,%L1,%2\;{a%G2e|add%G2e} %0,%1
@@ -3642,32 +3630,7 @@
{ai|addic} %L0,%L1,%2\;{a%G2e|add%G2e} %0,%1"
[(set_attr "length" "8")])
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
- (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,0")
- (match_operand:DI 2 "gpc_reg_operand" "r,r")))]
- "! TARGET_POWER && ! TARGET_POWERPC64"
- "*
-{
- return (WORDS_BIG_ENDIAN)
- ? \"addc %L0,%L1,%L2\;adde %0,%1,%2\"
- : \"addc %0,%1,%2\;adde %L0,%L1,%L2\";
-}"
- [(set_attr "length" "8")])
-
-(define_expand "subdi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
- (match_operand:DI 2 "gpc_reg_operand" "")))]
- ""
- "
-{
- if (! TARGET_POWER && ! TARGET_POWERPC64
- && short_cint_operand (operands[1], DImode))
- FAIL;
-}")
-
-(define_insn ""
+(define_insn "subddi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
(minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I,0,r,I")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r,0,0")))]
@@ -5660,7 +5623,7 @@
(clobber (match_scratch:SI 5 "=&r"))
(clobber (match_scratch:SI 6 "=l"))]
"DEFAULT_ABI == ABI_NT"
- "{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%6 %5\;{brl|blrl}\;{l|lwz} %4,%a3"
+ "{st|stw} %4,%a3\;{l|lwz} %5,0(%0)\;{l|lwz} %4,4(%0)\;mt%6 %5\;{brl|blrl}\;{l|lwz} %4,%a3"
[(set_attr "length" "24")])
(define_insn "call_value_indirect_nt"
@@ -5673,7 +5636,7 @@
(clobber (match_scratch:SI 6 "=&r"))
(clobber (match_scratch:SI 7 "=l"))]
"DEFAULT_ABI == ABI_NT"
- "{st|stw} %5,%a4\;{l|lwz} %6,0(%1)\;{l|lwz} %5,4(%1);\;mt%7 %6\;{brl|blrl}\;{l|lwz} %5,%a4"
+ "{st|stw} %5,%a4\;{l|lwz} %6,0(%1)\;{l|lwz} %5,4(%1)\;mt%7 %6\;{brl|blrl}\;{l|lwz} %5,%a4"
[(set_attr "length" "24")])
;; A function pointer under System V is just a normal pointer
diff --git a/gcc/ginclude/va-ppc.h b/gcc/ginclude/va-ppc.h
index 09f11e0d298..4e7d8266636 100644
--- a/gcc/ginclude/va-ppc.h
+++ b/gcc/ginclude/va-ppc.h
@@ -91,6 +91,9 @@ __extension__ ({ \
#define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8)
#endif
+#define __va_longlong_p(TYPE) \
+ ((__builtin_classify_type(*(TYPE *)0) == 1) && (sizeof(TYPE) == 8))
+
#define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12)
#define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long))
@@ -111,8 +114,13 @@ __extension__ (*({ \
} \
\
else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \
- && (AP)->gpr + __va_size(TYPE) <= 8) \
+ && (AP)->gpr + __va_size(TYPE) <= 8 \
+ && (!__va_longlong_p(TYPE) \
+ || (AP)->gpr + __va_size(TYPE) <= 7)) \
{ \
+ if (__va_longlong_p(TYPE) && ((AP)->gpr & 1) != 0) \
+ (AP)->gpr++; \
+ \
__ptr = __VA_GP_REGSAVE (AP, TYPE); \
(AP)->gpr += __va_size (TYPE); \
} \
@@ -132,6 +140,9 @@ __extension__ (*({ \
} \
else \
{ \
+ if (__va_longlong_p(TYPE) && ((long)(AP)->overflow_arg_area & 4) != 0) \
+ (AP)->overflow_arg_area += 4; \
+ \
__ptr = (TYPE *) (void *) ((AP)->overflow_arg_area); \
(AP)->overflow_arg_area += __va_size (TYPE) * sizeof (long); \
} \