Conversions between 128-bit integer and floating point values.
The files fixkfti-sw.c and fixunskfti-sw.c are renamed versions of fixkfti.c and fixunskfti.c respectively to do the conversions in software. The function names in the files were updated with the rename as well as some white spaces fixes. The file float128-p10.c contains the functions for using the ISA 3.1 hardware instructions to perform the conversions. 2021-06-08 Carl Love <cel@us.ibm.com> gcc/ChangeLog * config/rs6000/rs6000.c (__fixkfti, __fixunskfti, __floattikf, __floatuntikf): Names changed to __fixkfti_sw, __fixunskfti_sw, __floattikf_sw, __floatuntikf_sw respectively. * config/rs6000/rs6000.md (floatti<mode>2, floatunsti<mode>2, fix_trunc<mode>ti2, fixuns_trunc<mode>ti2): Add define_insn for mode IEEE 128. gcc/testsuite/ChangeLog * gcc.target/powerpc/fp128_conversions.c: New file. * gcc.target/powerpc/int_128bit-runnable.c(vextsd2q, vcmpuq, vcmpsq, vcmpequq, vcmpequq., vcmpgtsq, vcmpgtsq. vcmpgtuq, vcmpgtuq.): Update scan-assembler-times. (ppc_native_128bit): Remove dg-require-effective-target. libgcc/ChangeLog * config.host: Add if test and set for libgcc_cv_powerpc_3_1_float128_hw. * config/rs6000/fixkfti.c: Renamed to fixkfti-sw.c. Change calls of __fixkfti to __fixkfti_sw. * config/rs6000/fixunskfti.c: Renamed to fixunskfti-sw.c. Change calls of __fixunskfti to __fixunskfti_sw. * config/rs6000/float128-p10.c (__floattikf_hw, __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw): New file. * config/rs6000/float128-ifunc.c (SW_OR_HW_ISA3_1): New macro. (__floattikf_resolve, __floatuntikf_resolve, __fixkfti_resolve, __fixunskfti_resolve): Add resolve functions. (__floattikf, __floatuntikf, __fixkfti, __fixunskfti): New functions. * config/rs6000/float128-sed (floattitf, __floatuntitf, __fixtfti, __fixunstfti): Add editor commands to change names. * config/rs6000/float128-sed-hw (__floattitf, __floatuntitf, __fixtfti, __fixunstfti): Add editor commands to change names. * config/rs6000/floattikf.c: Renamed to floattikf-sw.c. * config/rs6000/floatuntikf.c: Renamed to floatuntikf-sw.c. * config/rs6000/quad-float128.h (__floattikf_sw, __floatuntikf_sw, __fixkfti_sw, __fixunskfti_sw, __floattikf_hw, __floatuntikf_hw, __fixkfti_hw, __fixunskfti_hw, __floattikf, __floatuntikf, __fixkfti, __fixunskfti): New extern declarations. * config/rs6000/t-float128 (floattikf, floatuntikf, fixkfti, fixunskfti): Remove file names from fp128_ppc_funcs. (floattikf-sw, floatuntikf-sw, fixkfti-sw, fixunskfti-sw): Add file names to fp128_ppc_funcs. * config/rs6000/t-float128-hw(fp128_3_1_hw_funcs, fp128_3_1_hw_src, fp128_3_1_hw_static_obj, fp128_3_1_hw_shared_obj, fp128_3_1_hw_obj): Add variables for ISA 3.1 support. * config/rs6000/t-float128-p10-hw: New file. * configure: Update script for isa 3.1 128-bit float support. * configure.ac: Add check for 128-bit float hardware support.
This commit is contained in:
parent
f170186446
commit
9090f48071
19 changed files with 589 additions and 36 deletions
|
@ -11014,10 +11014,10 @@ init_float128_ieee (machine_mode mode)
|
|||
|
||||
if (TARGET_POWERPC64)
|
||||
{
|
||||
set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
|
||||
set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
|
||||
set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
|
||||
set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
|
||||
set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti_sw");
|
||||
set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti_sw");
|
||||
set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf_sw");
|
||||
set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf_sw");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6441,6 +6441,42 @@
|
|||
xscvsxddp %x0,%x1"
|
||||
[(set_attr "type" "fp")])
|
||||
|
||||
(define_insn "floatti<mode>2"
|
||||
[(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
|
||||
(float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
|
||||
"TARGET_POWER10"
|
||||
{
|
||||
return "xscvsqqp %0,%1";
|
||||
}
|
||||
[(set_attr "type" "fp")])
|
||||
|
||||
(define_insn "floatunsti<mode>2"
|
||||
[(set (match_operand:IEEE128 0 "vsx_register_operand" "=v")
|
||||
(unsigned_float:IEEE128 (match_operand:TI 1 "vsx_register_operand" "v")))]
|
||||
"TARGET_POWER10"
|
||||
{
|
||||
return "xscvuqqp %0,%1";
|
||||
}
|
||||
[(set_attr "type" "fp")])
|
||||
|
||||
(define_insn "fix_trunc<mode>ti2"
|
||||
[(set (match_operand:TI 0 "vsx_register_operand" "=v")
|
||||
(fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
|
||||
"TARGET_POWER10"
|
||||
{
|
||||
return "xscvqpsqz %0,%1";
|
||||
}
|
||||
[(set_attr "type" "fp")])
|
||||
|
||||
(define_insn "fixuns_trunc<mode>ti2"
|
||||
[(set (match_operand:TI 0 "vsx_register_operand" "=v")
|
||||
(unsigned_fix:TI (match_operand:IEEE128 1 "vsx_register_operand" "v")))]
|
||||
"TARGET_POWER10"
|
||||
{
|
||||
return "xscvqpuqz %0,%1";
|
||||
}
|
||||
[(set_attr "type" "fp")])
|
||||
|
||||
; Allow the combiner to merge source memory operands to the conversion so that
|
||||
; the optimizer/register allocator doesn't try to load the value too early in a
|
||||
; GPR and then use store/load to move it to a FPR and suffer from a store-load
|
||||
|
|
294
gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
Normal file
294
gcc/testsuite/gcc.target/powerpc/fp128_conversions.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target power10_hw } */
|
||||
/* { dg-options "-mdejagnu-cpu=power10 -save-temps" } */
|
||||
|
||||
/* Check that the expected 128-bit instructions are generated if the processor
|
||||
supports the 128-bit integer instructions. */
|
||||
/* { dg-final { scan-assembler-times {\mxscvsqqp\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mxscvuqqp\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mxscvqpsqz\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mxscvqpuqz\M} 1 } } */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <fenv.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
void
|
||||
abort (void);
|
||||
|
||||
float
|
||||
conv_i_2_fp( long long int a)
|
||||
{
|
||||
return (float) a;
|
||||
}
|
||||
|
||||
double
|
||||
conv_i_2_fpd( long long int a)
|
||||
{
|
||||
return (double) a;
|
||||
}
|
||||
|
||||
double
|
||||
conv_ui_2_fpd( unsigned long long int a)
|
||||
{
|
||||
return (double) a;
|
||||
}
|
||||
|
||||
__float128
|
||||
conv_i128_2_fp128 (__int128_t a)
|
||||
{
|
||||
// default, gen inst KF mode
|
||||
// -mabi=ibmlongdouble, gen inst floattiieee KF mode
|
||||
// -mabi=ieeelongdouble gen inst floattiieee TF mode
|
||||
return (__float128) a;
|
||||
}
|
||||
|
||||
__float128
|
||||
conv_ui128_2_fp128 (__uint128_t a)
|
||||
{
|
||||
// default, gen inst KF mode
|
||||
// -mabi=ibmlongdouble, gen inst floattiieee KF mode
|
||||
// -mabi=ieeelongdouble gen inst floattiieee TF mode
|
||||
return (__float128) a;
|
||||
}
|
||||
|
||||
__int128_t
|
||||
conv_fp128_2_i128 (__float128 a)
|
||||
{
|
||||
// default, gen inst KF mode
|
||||
// -mabi=ibmlongdouble, gen inst floattiieee KF mode
|
||||
// -mabi=ieeelongdouble gen inst floattiieee TF mode
|
||||
return (__int128_t) a;
|
||||
}
|
||||
|
||||
__uint128_t
|
||||
conv_fp128_2_ui128 (__float128 a)
|
||||
{
|
||||
// default, gen inst KF mode
|
||||
// -mabi=ibmlongdouble, gen inst floattiieee KF mode
|
||||
// -mabi=ieeelongdouble gen inst floattiieee TF mode
|
||||
return (__uint128_t) a;
|
||||
}
|
||||
|
||||
long double
|
||||
conv_i128_2_ld (__int128_t a)
|
||||
{
|
||||
// default, gen call __floattitf
|
||||
// -mabi=ibmlongdouble, gen call __floattitf
|
||||
// -mabi=ieeelongdouble gen inst floattiieee TF mode
|
||||
return (long double) a;
|
||||
}
|
||||
|
||||
__ibm128
|
||||
conv_i128_2_ibm128 (__int128_t a)
|
||||
{
|
||||
// default, gen call __floattitf
|
||||
// -mabi=ibmlongdouble, gen call __floattitf
|
||||
// -mabi=ieeelongdouble, message uses IBM long double, no binary output
|
||||
return (__ibm128) a;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
float a, expected_result_float;
|
||||
double b, expected_result_double;
|
||||
long long int c, expected_result_llint;
|
||||
unsigned long long int u;
|
||||
__int128_t d;
|
||||
__uint128_t u128;
|
||||
unsigned long long expected_result_uint128[2] ;
|
||||
__float128 e;
|
||||
long double ld; // another 128-bit float version
|
||||
|
||||
union conv_t {
|
||||
float a;
|
||||
double b;
|
||||
long long int c;
|
||||
long long int128[2] ;
|
||||
unsigned long long uint128[2] ;
|
||||
unsigned long long int u;
|
||||
__int128_t d;
|
||||
__uint128_t u128;
|
||||
__float128 e;
|
||||
long double ld; // another 128-bit float version
|
||||
} conv, conv_result;
|
||||
|
||||
c = 20;
|
||||
expected_result_llint = 20.00000;
|
||||
a = conv_i_2_fp (c);
|
||||
|
||||
if (a != expected_result_llint) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_i_2_fp(%lld) = %10.5f\n", c, a);
|
||||
printf("\n does not match expected_result = %10.5f\n\n",
|
||||
expected_result_llint);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
c = 20;
|
||||
expected_result_double = 20.00000;
|
||||
b = conv_i_2_fpd (c);
|
||||
|
||||
if (b != expected_result_double) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_i_2_fpd(%lld) = %10.5f\n", d, b);
|
||||
printf("\n does not match expected_result = %10.5f\n\n",
|
||||
expected_result_double);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
u = 20;
|
||||
expected_result_double = 20.00000;
|
||||
b = conv_ui_2_fpd (u);
|
||||
|
||||
if (b != expected_result_double) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_ui_2_fpd(%llu) = %10.5f\n", u, b);
|
||||
printf("\n does not match expected_result = %10.5f\n\n",
|
||||
expected_result_double);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
d = -3210;
|
||||
d = (d * 10000000000) + 9876543210;
|
||||
conv_result.e = conv_i128_2_fp128 (d);
|
||||
expected_result_uint128[1] = 0xc02bd2f9068d1160;
|
||||
expected_result_uint128[0] = 0x0;
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_i128_2_fp128(-32109876543210) = (result in hex) 0x%llx %llx\n",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
d = 123;
|
||||
d = (d * 10000000000) + 1234567890;
|
||||
conv_result.ld = conv_i128_2_fp128 (d);
|
||||
expected_result_uint128[1] = 0x0;
|
||||
expected_result_uint128[0] = 0x4271eab4c8ed2000;
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_i128_2_fp128(1231234567890) = (result in hex) 0x%llx %llx\n",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
u128 = 8760;
|
||||
u128 = (u128 * 10000000000) + 1234567890;
|
||||
conv_result.e = conv_ui128_2_fp128 (u128);
|
||||
expected_result_uint128[1] = 0x402d3eb101df8b48;
|
||||
expected_result_uint128[0] = 0x0;
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_ui128_2_fp128(87601234567890) = (result in hex) 0x%llx %llx\n",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
u128 = 3210;
|
||||
u128 = (u128 * 10000000000) + 9876543210;
|
||||
expected_result_uint128[1] = 0x402bd3429c8feea0;
|
||||
expected_result_uint128[0] = 0x0;
|
||||
conv_result.e = conv_ui128_2_fp128 (u128);
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_ui128_2_fp128(32109876543210) = (result in hex) 0x%llx %llx\n",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
conv.e = 12345.6789;
|
||||
expected_result_uint128[1] = 0x1407374883526960;
|
||||
expected_result_uint128[0] = 0x3039;
|
||||
|
||||
conv_result.d = conv_fp128_2_i128 (conv.e);
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
|
||||
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
conv.e = -6789.12345;
|
||||
expected_result_uint128[1] = 0x0;
|
||||
expected_result_uint128[0] = 0xffffffffffffe57b;
|
||||
conv_result.d = conv_fp128_2_i128 (conv.e);
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_fp128_2_i128(0x%llx %llx) = ",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
|
||||
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
conv.e = 6789.12345;
|
||||
expected_result_uint128[1] = 0x0;
|
||||
expected_result_uint128[0] = 0x1a85;
|
||||
conv_result.d = conv_fp128_2_ui128 (conv.e);
|
||||
|
||||
if ((conv_result.uint128[1] != expected_result_uint128[1])
|
||||
&& (conv_result.uint128[0] != expected_result_uint128[0])) {
|
||||
#if DEBUG
|
||||
printf("ERROR: conv_fp128_2_ui128(0x%llx %llx) = ",
|
||||
conv.uint128[1], conv.uint128[0]);
|
||||
printf("0x%llx %llx\n", conv_result.uint128[1], conv_result.uint128[0]);
|
||||
|
||||
printf("\n does not match expected_result = (result in hex) 0x%llx %llx\n\n",
|
||||
expected_result_uint128[1], expected_result_uint128[0]);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -4,21 +4,16 @@
|
|||
|
||||
/* Check that the expected 128-bit instructions are generated if the processor
|
||||
supports the 128-bit integer instructions. */
|
||||
/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvslq\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvsrq\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvsraq\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvrlq\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvrlqnm\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvrlqmi\M} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpuq\M} 0 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpsq\M} 0 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpequq\M} 0 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpequq.\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 0 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtsq.\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 0 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtuq.\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvmuleud\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpequq\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtsq\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvcmpgtuq\M} 16 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvmuloud\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvmulesd\M} 1 } } */
|
||||
/* { dg-final { scan-assembler-times {\mvmulosd\M} 1 } } */
|
||||
|
|
|
@ -1224,6 +1224,10 @@ powerpc*-*-linux*)
|
|||
tmake_file="${tmake_file} rs6000/t-float128-hw"
|
||||
fi
|
||||
|
||||
if test $libgcc_cv_powerpc_3_1_float128_hw = yes; then
|
||||
tmake_file="${tmake_file} rs6000/t-float128-p10-hw"
|
||||
fi
|
||||
|
||||
extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
|
||||
md_unwind_header=rs6000/linux-unwind.h
|
||||
;;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
This file is part of the GNU C Library.
|
||||
Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
|
||||
Code is based on the main soft-fp library written by:
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "quad-float128.h"
|
||||
|
||||
TItype
|
||||
__fixkfti (TFtype a)
|
||||
__fixkfti_sw (TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q (A);
|
|
@ -5,7 +5,7 @@
|
|||
This file is part of the GNU C Library.
|
||||
Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
|
||||
Code is based on the main soft-fp library written by:
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "quad-float128.h"
|
||||
|
||||
UTItype
|
||||
__fixunskfti (TFtype a)
|
||||
__fixunskfti_sw (TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q (A);
|
|
@ -46,14 +46,9 @@
|
|||
#endif
|
||||
|
||||
#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
|
||||
#define SW_OR_HW_ISA3_1(SW, HW) (__builtin_cpu_supports ("arch_3_1") ? HW : SW)
|
||||
|
||||
/* Resolvers. */
|
||||
|
||||
/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
|
||||
and __floatuntikf. There is no ISA 3.0 instruction that converts between
|
||||
128-bit integer types and 128-bit IEEE floating point, or vice versa. So
|
||||
use the emulator functions for these conversions. */
|
||||
|
||||
static __typeof__ (__addkf3_sw) *
|
||||
__addkf3_resolve (void)
|
||||
{
|
||||
|
@ -102,6 +97,18 @@ __floatdikf_resolve (void)
|
|||
return SW_OR_HW (__floatdikf_sw, __floatdikf_hw);
|
||||
}
|
||||
|
||||
static __typeof__ (__floattikf_sw) *
|
||||
__floattikf_resolve (void)
|
||||
{
|
||||
return SW_OR_HW_ISA3_1 (__floattikf_sw, __floattikf_hw);
|
||||
}
|
||||
|
||||
static __typeof__ (__floatuntikf_sw) *
|
||||
__floatuntikf_resolve (void)
|
||||
{
|
||||
return SW_OR_HW_ISA3_1 (__floatuntikf_sw, __floatuntikf_hw);
|
||||
}
|
||||
|
||||
static __typeof__ (__floatunsikf_sw) *
|
||||
__floatunsikf_resolve (void)
|
||||
{
|
||||
|
@ -114,6 +121,19 @@ __floatundikf_resolve (void)
|
|||
return SW_OR_HW (__floatundikf_sw, __floatundikf_hw);
|
||||
}
|
||||
|
||||
|
||||
static __typeof__ (__fixkfti_sw) *
|
||||
__fixkfti_resolve (void)
|
||||
{
|
||||
return SW_OR_HW_ISA3_1 (__fixkfti_sw, __fixkfti_hw);
|
||||
}
|
||||
|
||||
static __typeof__ (__fixunskfti_sw) *
|
||||
__fixunskfti_resolve (void)
|
||||
{
|
||||
return SW_OR_HW_ISA3_1 (__fixunskfti_sw, __fixunskfti_hw);
|
||||
}
|
||||
|
||||
static __typeof__ (__fixkfsi_sw) *
|
||||
__fixkfsi_resolve (void)
|
||||
{
|
||||
|
@ -303,6 +323,18 @@ TFtype __floatsikf (SItype_ppc)
|
|||
TFtype __floatdikf (DItype_ppc)
|
||||
__attribute__ ((__ifunc__ ("__floatdikf_resolve")));
|
||||
|
||||
TFtype __floattikf (TItype_ppc)
|
||||
__attribute__ ((__ifunc__ ("__floattikf_resolve")));
|
||||
|
||||
TFtype __floatuntikf (UTItype_ppc)
|
||||
__attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
|
||||
|
||||
TItype_ppc __fixkfti (TFtype)
|
||||
__attribute__ ((__ifunc__ ("__fixkfti_resolve")));
|
||||
|
||||
UTItype_ppc __fixunskfti (TFtype)
|
||||
__attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
|
||||
|
||||
TFtype __floatunsikf (USItype_ppc)
|
||||
__attribute__ ((__ifunc__ ("__floatunsikf_resolve")));
|
||||
|
||||
|
|
71
libgcc/config/rs6000/float128-p10.c
Normal file
71
libgcc/config/rs6000/float128-p10.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/* Automatic switching between software and hardware IEEE 128-bit
|
||||
ISA 3.1 floating-point emulation for PowerPC.
|
||||
|
||||
Copyright (C) 2016-2020 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Carl Love (cel@us.ibm.com)
|
||||
Code is based on the main soft-fp library written by:
|
||||
Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Note, the hardware conversion instructions for 128-bit integers are
|
||||
supported for ISA 3.1 and later. Only compile this file with -mcpu=power10
|
||||
or newer support. */
|
||||
|
||||
#include <soft-fp.h>
|
||||
#include <quad-float128.h>
|
||||
|
||||
#ifndef __FLOAT128_HARDWARE__
|
||||
#error "This module must be compiled with IEEE 128-bit hardware support"
|
||||
#endif
|
||||
|
||||
#ifndef _ARCH_PWR10
|
||||
#error "This module must be compiled for Power 10 support"
|
||||
#endif
|
||||
|
||||
TFtype
|
||||
__floattikf_hw (TItype_ppc a)
|
||||
{
|
||||
return (TFtype) a;
|
||||
}
|
||||
|
||||
TFtype
|
||||
__floatuntikf_hw (UTItype_ppc a)
|
||||
{
|
||||
return (TFtype) a;
|
||||
}
|
||||
|
||||
TItype_ppc
|
||||
__fixkfti_hw (TFtype a)
|
||||
{
|
||||
return (TItype_ppc) a;
|
||||
}
|
||||
|
||||
UTItype_ppc
|
||||
__fixunskfti_hw (TFtype a)
|
||||
{
|
||||
return (UTItype_ppc) a;
|
||||
}
|
|
@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi/g
|
|||
s/__fixunstfdi/__fixunskfdi/g
|
||||
s/__fixunstfsi/__fixunskfsi/g
|
||||
s/__floatditf/__floatdikf/g
|
||||
s/__floattitf/__floattikf/g
|
||||
s/__floatuntitf/__floatuntikf/g
|
||||
s/__fixtfti/__fixkfti/g
|
||||
s/__fixunstfti/__fixunskfti/g
|
||||
s/__floatsitf/__floatsikf/g
|
||||
s/__floatunditf/__floatundikf/g
|
||||
s/__floatunsitf/__floatunsikf/g
|
||||
|
|
|
@ -8,6 +8,10 @@ s/__fixtfsi/__fixkfsi_sw/g
|
|||
s/__fixunstfdi/__fixunskfdi_sw/g
|
||||
s/__fixunstfsi/__fixunskfsi_sw/g
|
||||
s/__floatditf/__floatdikf_sw/g
|
||||
s/__floattitf/__floattikf_sw/g
|
||||
s/__floatuntitf/__floatuntikf_sw/g
|
||||
s/__fixtfti/__fixkfti_sw/g
|
||||
s/__fixunstfti/__fixunskfti_sw/g
|
||||
s/__floatsitf/__floatsikf_sw/g
|
||||
s/__floatunditf/__floatundikf_sw/g
|
||||
s/__floatunsitf/__floatunsikf_sw/g
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
This file is part of the GNU C Library.
|
||||
Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
|
||||
Code is based on the main soft-fp library written by:
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "quad-float128.h"
|
||||
|
||||
TFtype
|
||||
__floattikf (TItype i)
|
||||
__floattikf_sw (TItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q (A);
|
|
@ -5,7 +5,7 @@
|
|||
This file is part of the GNU C Library.
|
||||
Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
|
||||
Code is based on the main soft-fp library written by:
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
Uros Bizjak (ubizjak@gmail.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -35,7 +35,7 @@
|
|||
#include "quad-float128.h"
|
||||
|
||||
TFtype
|
||||
__floatuntikf (UTItype i)
|
||||
__floatuntikf_sw (UTItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q (A);
|
|
@ -88,19 +88,18 @@ extern USItype_ppc __fixunskfsi_sw (TFtype);
|
|||
extern UDItype_ppc __fixunskfdi_sw (TFtype);
|
||||
extern TFtype __floatsikf_sw (SItype_ppc);
|
||||
extern TFtype __floatdikf_sw (DItype_ppc);
|
||||
extern TFtype __floattikf_sw (TItype_ppc);
|
||||
extern TFtype __floatunsikf_sw (USItype_ppc);
|
||||
extern TFtype __floatundikf_sw (UDItype_ppc);
|
||||
extern TFtype __floatuntikf_sw (UTItype_ppc);
|
||||
extern TItype_ppc __fixkfti_sw (TFtype);
|
||||
extern UTItype_ppc __fixunskfti_sw (TFtype);
|
||||
extern IBM128_TYPE __extendkftf2_sw (TFtype);
|
||||
extern TFtype __trunctfkf2_sw (IBM128_TYPE);
|
||||
extern TCtype __mulkc3_sw (TFtype, TFtype, TFtype, TFtype);
|
||||
extern TCtype __divkc3_sw (TFtype, TFtype, TFtype, TFtype);
|
||||
|
||||
#ifdef _ARCH_PPC64
|
||||
/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
|
||||
and __floatuntikf. There is no ISA 3.0 instruction that converts between
|
||||
128-bit integer types and 128-bit IEEE floating point, or vice versa. So
|
||||
use the emulator functions for these conversions. */
|
||||
|
||||
extern TItype_ppc __fixkfti (TFtype);
|
||||
extern UTItype_ppc __fixunskfti (TFtype);
|
||||
extern TFtype __floattikf (TItype_ppc);
|
||||
|
@ -131,8 +130,12 @@ extern USItype_ppc __fixunskfsi_hw (TFtype);
|
|||
extern UDItype_ppc __fixunskfdi_hw (TFtype);
|
||||
extern TFtype __floatsikf_hw (SItype_ppc);
|
||||
extern TFtype __floatdikf_hw (DItype_ppc);
|
||||
extern TFtype __floattikf_hw (TItype_ppc);
|
||||
extern TFtype __floatunsikf_hw (USItype_ppc);
|
||||
extern TFtype __floatundikf_hw (UDItype_ppc);
|
||||
extern TFtype __floatuntikf_hw (UTItype_ppc);
|
||||
extern TItype_ppc __fixkfti_hw (TFtype);
|
||||
extern UTItype_ppc __fixunskfti_hw (TFtype);
|
||||
extern IBM128_TYPE __extendkftf2_hw (TFtype);
|
||||
extern TFtype __trunctfkf2_hw (IBM128_TYPE);
|
||||
extern TCtype __mulkc3_hw (TFtype, TFtype, TFtype, TFtype);
|
||||
|
@ -163,8 +166,12 @@ extern USItype_ppc __fixunskfsi (TFtype);
|
|||
extern UDItype_ppc __fixunskfdi (TFtype);
|
||||
extern TFtype __floatsikf (SItype_ppc);
|
||||
extern TFtype __floatdikf (DItype_ppc);
|
||||
extern TFtype __floattikf (TItype_ppc);
|
||||
extern TFtype __floatunsikf (USItype_ppc);
|
||||
extern TFtype __floatundikf (UDItype_ppc);
|
||||
extern TFtype __floatuntikf (UTItype_ppc);
|
||||
extern TItype_ppc __fixkfti (TFtype);
|
||||
extern UTItype_ppc __fixunskfti (TFtype);
|
||||
extern IBM128_TYPE __extendkftf2 (TFtype);
|
||||
extern TFtype __trunctfkf2 (IBM128_TYPE);
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ ibm128_dec_funcs = _tf_to_sd _tf_to_dd _tf_to_td \
|
|||
_sd_to_tf _dd_to_tf _td_to_tf
|
||||
|
||||
# New functions for software emulation
|
||||
fp128_ppc_funcs = floattikf floatuntikf fixkfti fixunskfti \
|
||||
fp128_ppc_funcs = floattikf-sw floatuntikf-sw \
|
||||
fixkfti-sw fixunskfti-sw \
|
||||
extendkftf2-sw trunctfkf2-sw \
|
||||
sfp-exceptions _mulkc3 _divkc3 _powikf2
|
||||
|
||||
|
@ -47,13 +48,16 @@ fp128_ppc_obj = $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
|
|||
|
||||
# All functions
|
||||
fp128_funcs = $(fp128_softfp_funcs) $(fp128_ppc_funcs) \
|
||||
$(fp128_hw_funcs) $(fp128_ifunc_funcs)
|
||||
$(fp128_hw_funcs) $(fp128_ifunc_funcs) \
|
||||
$(fp128_3_1_hw_funcs)
|
||||
|
||||
fp128_src = $(fp128_softfp_src) $(fp128_ppc_src) \
|
||||
$(fp128_hw_src) $(fp128_ifunc_src)
|
||||
$(fp128_hw_src) $(fp128_ifunc_src) \
|
||||
$(fp128_3_1_hw_src)
|
||||
|
||||
fp128_obj = $(fp128_softfp_obj) $(fp128_ppc_obj) \
|
||||
$(fp128_hw_obj) $(fp128_ifunc_obj)
|
||||
$(fp128_hw_obj) $(fp128_ifunc_obj) \
|
||||
$(fp128_3_1_hw_obj)
|
||||
|
||||
fp128_sed = $(srcdir)/config/rs6000/float128-sed$(fp128_sed_hw)
|
||||
fp128_dep = $(fp128_sed) $(srcdir)/config/rs6000/t-float128
|
||||
|
|
|
@ -13,6 +13,13 @@ fp128_hw_static_obj = $(addsuffix $(objext),$(fp128_hw_funcs))
|
|||
fp128_hw_shared_obj = $(addsuffix _s$(objext),$(fp128_hw_funcs))
|
||||
fp128_hw_obj = $(fp128_hw_static_obj) $(fp128_hw_shared_obj)
|
||||
|
||||
# New functions for ISA 3.1 hardware support
|
||||
fp128_3_1_hw_funcs = float128-p10
|
||||
fp128_3_1_hw_src = $(srcdir)/config/rs6000/float128-p10.c
|
||||
fp128_3_1_hw_static_obj = $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
|
||||
fp128_3_1_hw_shared_obj = $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
|
||||
fp128_3_1_hw_obj = $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
|
||||
|
||||
fp128_ifunc_funcs = float128-ifunc
|
||||
fp128_ifunc_src = $(srcdir)/config/rs6000/float128-ifunc.c
|
||||
fp128_ifunc_static_obj = float128-ifunc$(objext)
|
||||
|
@ -30,9 +37,18 @@ FP128_CFLAGS_HW = -Wno-type-limits -mvsx -mfloat128 \
|
|||
-I$(srcdir)/config/rs6000 \
|
||||
$(FLOAT128_HW_INSNS)
|
||||
|
||||
FP128_3_1_CFLAGS_HW = -Wno-type-limits -mvsx -mcpu=power10 \
|
||||
-mfloat128-hardware -mno-gnu-attribute \
|
||||
-I$(srcdir)/soft-fp \
|
||||
-I$(srcdir)/config/rs6000 \
|
||||
$(FLOAT128_HW_INSNS)
|
||||
|
||||
$(fp128_hw_obj) : INTERNAL_CFLAGS += $(FP128_CFLAGS_HW)
|
||||
$(fp128_hw_obj) : $(srcdir)/config/rs6000/t-float128-hw
|
||||
|
||||
$(fp128_3_1_hw_obj) : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
|
||||
$(fp128_3_1_hw_obj) : $(srcdir)/config/rs6000/t-float128-p10-hw
|
||||
|
||||
$(fp128_ifunc_obj) : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
|
||||
$(fp128_ifunc_obj) : $(srcdir)/config/rs6000/t-float128-hw
|
||||
|
||||
|
|
24
libgcc/config/rs6000/t-float128-p10-hw
Normal file
24
libgcc/config/rs6000/t-float128-p10-hw
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Support for adding __float128 hardware support to the powerpc.
|
||||
# Tell the float128 functions that the ISA 3.1 hardware support can
|
||||
# be compiled it to be selected via IFUNC functions.
|
||||
|
||||
FLOAT128_HW_INSNS = -DFLOAT128_HW_INSNS
|
||||
|
||||
# New functions for hardware support
|
||||
|
||||
fp128_3_1_hw_funcs = float128-p10
|
||||
fp128_3_1_hw_src = $(srcdir)/config/rs6000/float128-p10.c
|
||||
fp128_3_1_hw_static_obj = $(addsuffix $(objext),$(fp128_3_1_hw_funcs))
|
||||
fp128_3_1_hw_shared_obj = $(addsuffix _s$(objext),$(fp128_3_1_hw_funcs))
|
||||
fp128_3_1_hw_obj = $(fp128_3_1_hw_static_obj) $(fp128_3_1_hw_shared_obj)
|
||||
|
||||
# Build the hardware support functions with appropriate hardware support
|
||||
FP128_3_1_CFLAGS_HW = -Wno-type-limits -mvsx -mfloat128 \
|
||||
-mpower10 \
|
||||
-mfloat128-hardware -mno-gnu-attribute \
|
||||
-I$(srcdir)/soft-fp \
|
||||
-I$(srcdir)/config/rs6000 \
|
||||
$(FLOAT128_HW_INSNS)
|
||||
|
||||
$(fp128_3_1_hw_obj) : INTERNAL_CFLAGS += $(FP128_3_1_CFLAGS_HW)
|
||||
$(fp128_3_1_hw_obj) : $(srcdir)/config/rs6000/t-float128-p10-hw
|
37
libgcc/configure
vendored
37
libgcc/configure
vendored
|
@ -5263,6 +5263,43 @@ fi
|
|||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
|
||||
$as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 3.1 to build hardware __float128 libraries" >&5
|
||||
$as_echo_n "checking for PowerPC ISA 3.1 to build hardware __float128 libraries... " >&6; }
|
||||
if ${libgcc_cv_powerpc_float128_hw+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <sys/auxv.h>
|
||||
#ifndef AT_PLATFORM
|
||||
#error "AT_PLATFORM is not defined"
|
||||
#endif
|
||||
#ifndef __BUILTIN_CPU_SUPPORTS__
|
||||
#error "__builtin_cpu_supports is not available"
|
||||
#endif
|
||||
vector unsigned char add (vector unsigned char a, vector unsigned char b)
|
||||
{
|
||||
vector unsigned char ret;
|
||||
__asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
|
||||
return ret;
|
||||
}
|
||||
void *add_resolver (void) { return (void *) add; }
|
||||
__float128 add_ifunc (__float128, __float128)
|
||||
__attribute__ ((__ifunc__ ("add_resolver")));
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
libgcc_cv_powerpc_3_1_float128_hw=yes
|
||||
else
|
||||
libgcc_cv_powerpc_3_1_float128_hw=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5
|
||||
$as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
esac
|
||||
|
||||
# Collect host-machine-specific information.
|
||||
|
|
|
@ -458,6 +458,31 @@ powerpc*-*-linux*)
|
|||
[libgcc_cv_powerpc_float128_hw=yes],
|
||||
[libgcc_cv_powerpc_float128_hw=no])])
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -mpower10 -mfloat128-hardware"
|
||||
AC_CACHE_CHECK([for PowerPC ISA 3.1 to build hardware __float128 libraries],
|
||||
[libgcc_cv_powerpc_float128_hw],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE([#include <sys/auxv.h>
|
||||
#ifndef AT_PLATFORM
|
||||
#error "AT_PLATFORM is not defined"
|
||||
#endif
|
||||
#ifndef __BUILTIN_CPU_SUPPORTS__
|
||||
#error "__builtin_cpu_supports is not available"
|
||||
#endif
|
||||
vector unsigned char add (vector unsigned char a, vector unsigned char b)
|
||||
{
|
||||
vector unsigned char ret;
|
||||
__asm__ ("xscvsqqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
|
||||
return ret;
|
||||
}
|
||||
void *add_resolver (void) { return (void *) add; }
|
||||
__float128 add_ifunc (__float128, __float128)
|
||||
__attribute__ ((__ifunc__ ("add_resolver")));])],
|
||||
[libgcc_cv_powerpc_3_1_float128_hw=yes],
|
||||
[libgcc_cv_powerpc_3_1_float128_hw=no])])
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
esac
|
||||
|
||||
# Collect host-machine-specific information.
|
||||
|
|
Loading…
Add table
Reference in a new issue