aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn David Anglin <danglin@gcc.gnu.org>2021-11-05 16:07:35 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2021-11-05 16:07:35 +0000
commitdb89d474ad812e57895cb8866ebaeedad0cc3e3f (patch)
tree19a626b97100d137525c01f398c19dcfa158e8ca /gcc
parent858d7ee1a0cd97c01d844ea73ab81918da738344 (diff)
downloadgcc-db89d474ad812e57895cb8866ebaeedad0cc3e3f.zip
gcc-db89d474ad812e57895cb8866ebaeedad0cc3e3f.tar.gz
gcc-db89d474ad812e57895cb8866ebaeedad0cc3e3f.tar.bz2
Support TI mode and soft float on PA64
This change implements TI mode on PA64. Various new patterns are added to pa.md. The libgcc build needed modification to build both DI and TI routines. We also need various softfp routines to convert to and from TImode. I added full softfp for the -msoft-float option. At the moment, this doesn't completely eliminate all use of the floating-point co-processor. For this, libgcc needs to be built with -msoft-mult. The floating-point exception support also needs a soft option. 2021-11-05 John David Anglin <danglin@gcc.gnu.org> PR libgomp/96661 gcc/ChangeLog: * config/pa/pa-modes.def: Add OImode integer type. * config/pa/pa.c (pa_scalar_mode_supported_p): Allow TImode for TARGET_64BIT. * config/pa/pa.h (MIN_UNITS_PER_WORD) Define to MIN_UNITS_PER_WORD to UNITS_PER_WORD if IN_LIBGCC2. * config/pa/pa.md (addti3, addvti3, subti3, subvti3, negti2, negvti2, ashlti3, shrpd_internal): New patterns. Change some multi instruction types to multi. libgcc/ChangeLog: * config.host (hppa*64*-*-linux*): Revise tmake_file. (hppa*64*-*-hpux11*): Likewise. * config/pa/sfp-exceptions.c: New. * config/pa/sfp-machine.h: New. * config/pa/t-dimode: New. * config/pa/t-softfp-sfdftf: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa-modes.def3
-rw-r--r--gcc/config/pa/pa.c10
-rw-r--r--gcc/config/pa/pa.h16
-rw-r--r--gcc/config/pa/pa.md164
4 files changed, 180 insertions, 13 deletions
diff --git a/gcc/config/pa/pa-modes.def b/gcc/config/pa/pa-modes.def
index 769de66..6020233 100644
--- a/gcc/config/pa/pa-modes.def
+++ b/gcc/config/pa/pa-modes.def
@@ -30,3 +30,6 @@ FLOAT_MODE (TF, 16, mips_quad_format);
/* HPPA floating comparisons produce distinct condition codes. */
CC_MODE (CCFP);
+
+/* Mode used for signed overflow checking of TImode. */
+INT_MODE (OI, 32);
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 21b812e..f22d25a 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -6550,18 +6550,16 @@ hppa_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
/* True if MODE is valid for the target. By "valid", we mean able to
be manipulated in non-trivial ways. In particular, this means all
- the arithmetic is supported.
-
- Currently, TImode is not valid as the HP 64-bit runtime documentation
- doesn't document the alignment and calling conventions for this type.
- Thus, we return false when PRECISION is 2 * BITS_PER_WORD and
- 2 * BITS_PER_WORD isn't equal LONG_LONG_TYPE_SIZE. */
+ the arithmetic is supported. */
static bool
pa_scalar_mode_supported_p (scalar_mode mode)
{
int precision = GET_MODE_PRECISION (mode);
+ if (TARGET_64BIT && mode == TImode)
+ return true;
+
switch (GET_MODE_CLASS (mode))
{
case MODE_PARTIAL_INT:
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 0fe3fd6..96815ec 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -258,11 +258,17 @@ typedef struct GTY(()) machine_function
is UNITS_PER_WORD. Otherwise, it is the constant value that is the
smallest value that UNITS_PER_WORD can have at run-time.
- FIXME: This needs to be 4 when TARGET_64BIT is true to suppress the
- building of various TImode routines in libgcc. The HP runtime
- specification doesn't provide the alignment requirements and calling
- conventions for TImode variables. */
-#define MIN_UNITS_PER_WORD 4
+ This needs to be 8 when TARGET_64BIT is true to allow building various
+ TImode routines in libgcc. However, we also need the DImode DIVMOD
+ routines because they are not currently implemented in pa.md.
+
+ The HP runtime specification doesn't provide the alignment requirements
+ and calling conventions for TImode variables. */
+#ifdef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#else
+#define MIN_UNITS_PER_WORD 4
+#endif
/* The widest floating point format supported by the hardware. Note that
setting this influences some Ada floating point type sizes, currently
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index ea6da45..f124c30 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -5357,6 +5357,88 @@
[(set_attr "type" "binary,binary")
(set_attr "length" "4,4")])
+(define_insn "addti3"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (plus:TI (match_operand:TI 1 "register_operand" "r")
+ (match_operand:TI 2 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[3] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_lowpart (DImode, operands[1]);
+ operands[5] = gen_lowpart (DImode, operands[2]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ operands[2] = gen_highpart (DImode, operands[2]);
+ return \"add %4,%5,%3\;add,dc %1,%2,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "addvti3"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (plus:TI (match_operand:TI 1 "register_operand" "r")
+ (match_operand:TI 2 "register_operand" "r")))
+ (trap_if (ne (plus:OI (sign_extend:OI (match_dup 1))
+ (sign_extend:OI (match_dup 2)))
+ (sign_extend:OI (plus:TI (match_dup 1)
+ (match_dup 2))))
+ (const_int 0))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[3] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_lowpart (DImode, operands[1]);
+ operands[5] = gen_lowpart (DImode, operands[2]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ operands[2] = gen_highpart (DImode, operands[2]);
+ return \"add %4,%5,%3\;add,dc,tsv %1,%2,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "subti3"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (minus:TI (match_operand:TI 1 "register_operand" "r")
+ (match_operand:TI 2 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[3] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_lowpart (DImode, operands[1]);
+ operands[5] = gen_lowpart (DImode, operands[2]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ operands[2] = gen_highpart (DImode, operands[2]);
+ return \"sub %4,%5,%3\;sub,db %1,%2,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_insn "subvti3"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (minus:TI (match_operand:TI 1 "register_operand" "r")
+ (match_operand:TI 2 "register_operand" "r")))
+ (trap_if (ne (minus:OI (sign_extend:OI (match_dup 1))
+ (sign_extend:OI (match_dup 2)))
+ (sign_extend:OI (minus:TI (match_dup 1)
+ (match_dup 2))))
+ (const_int 0))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[3] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_lowpart (DImode, operands[1]);
+ operands[5] = gen_lowpart (DImode, operands[2]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ operands[2] = gen_highpart (DImode, operands[2]);
+ return \"sub %4,%5,%3\;sub,db,tsv %1,%2,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
;; Trap instructions.
(define_insn "trap"
@@ -5897,7 +5979,7 @@
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
"!TARGET_64BIT"
"sub %%r0,%R1,%R0\;{subb|sub,b} %%r0,%1,%0"
- [(set_attr "type" "unary")
+ [(set_attr "type" "multi")
(set_attr "length" "8")])
(define_insn ""
@@ -5908,6 +5990,21 @@
[(set_attr "type" "unary")
(set_attr "length" "4")])
+(define_insn "negti2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (neg:TI (match_operand:TI 1 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = gen_lowpart (DImode, operands[1]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ return \"sub %%r0,%3,%2\;sub,db %%r0,%1,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
(define_expand "negvdi2"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(neg:DI (match_operand:DI 1 "register_operand" "")))
@@ -5925,7 +6022,7 @@
(const_int 0))]
"!TARGET_64BIT"
"sub %%r0,%R1,%R0\;{subbo|sub,b,tsv} %%r0,%1,%0"
- [(set_attr "type" "unary")
+ [(set_attr "type" "multi")
(set_attr "length" "8")])
(define_insn ""
@@ -5939,6 +6036,24 @@
[(set_attr "type" "unary")
(set_attr "length" "4")])
+(define_insn "negvti2"
+ [(set (match_operand:TI 0 "register_operand" "=r")
+ (neg:TI (match_operand:TI 1 "register_operand" "r")))
+ (trap_if (ne (neg:OI (sign_extend:OI (match_dup 1)))
+ (sign_extend:OI (neg:TI (match_dup 1))))
+ (const_int 0))]
+ "TARGET_64BIT"
+ "*
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = gen_lowpart (DImode, operands[1]);
+ operands[0] = gen_highpart (DImode, operands[0]);
+ operands[1] = gen_highpart (DImode, operands[1]);
+ return \"sub %%r0,%3,%2\;sub,db,tsv %%r0,%1,%0\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "register_operand" "r")))]
@@ -6566,6 +6681,42 @@
operands[1] = force_reg (DImode, operands[1]);
}")
+(define_expand "ashlti3"
+ [(set (match_operand:TI 0 "register_operand" "")
+ (ashift:TI (match_operand:TI 1 "lhs_lshift_operand" "")
+ (match_operand:TI 2 "arith32_operand" "")))]
+ "TARGET_64BIT"
+{
+ if (REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]);
+ rtx dst = operands[0];
+ rtx src = force_reg (TImode, operands[1]);
+ if (shift >= 1 && shift <= 63)
+ {
+ emit_insn (gen_shrpd_internal (gen_highpart (DImode, dst),
+ gen_lowpart (DImode, src),
+ GEN_INT (64-shift),
+ gen_highpart (DImode, src),
+ GEN_INT (shift)));
+ emit_insn (gen_ashldi3 (gen_lowpart (DImode, dst),
+ gen_lowpart (DImode, src),
+ GEN_INT (shift)));
+ DONE;
+ }
+ else if (shift >= 64 && shift <= 127)
+ {
+ emit_insn (gen_ashldi3 (gen_highpart (DImode, dst),
+ gen_lowpart (DImode, src),
+ GEN_INT (shift - 64)));
+ emit_move_insn (gen_lowpart (DImode, dst), GEN_INT (0));
+ DONE;
+ }
+ }
+ /* Fallback to using optabs.c's expand_doubleword_shift. */
+ FAIL;
+})
+
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
@@ -6944,6 +7095,15 @@
(match_operand:SI 4 "const_int_operand"))))]
"")
+(define_expand "shrpd_internal"
+ [(set (match_operand:DI 0 "register_operand")
+ (ior:DI
+ (lshiftrt:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "const_int_operand"))
+ (ashift:DI (match_operand:DI 3 "register_operand")
+ (match_operand:DI 4 "const_int_operand"))))]
+ "TARGET_64BIT")
+
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")