1 # Copyright
(C
) 2005-2023 Free Software Foundation
, Inc.
3 # This
program is free software
; you can redistribute it and
/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation
; either version
3 of the License
, or
6 #
(at your option
) any later version.
8 # This
program is distributed in the hope that it will be useful
,
9 # but WITHOUT
ANY WARRANTY
; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License
for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with GCC
; see the file COPYING3.
If not see
15 #
<http
://www.gnu.org
/licenses
/>.
17 # DejaGnu test driver around Mike Cowlishaw
's testsuite for decimal
18 # decimal arithmetic ("decTest"). See:
19 # <http://www2.hursley.ibm.com/decimal/dectest.html>.
21 # Contributed by Ben Elliston <bje@au.ibm.com>.
23 set DEC_TORTURE_OPTIONS [list {} -O1 -O2 -O3 -Os -msoft-float]
25 proc target-specific-flags {} {
26 set result "-frounding-math "
30 # Load support procs (borrow these from c-torture).
31 load_lib c-torture.exp
32 load_lib target-supports.exp
33 load_lib torture-options.exp
35 # Skip these tests for targets that don't support this extension.
36 if { ![check_effective_target_dfp
] } {
40 # The list format is
[coefficient
, max-exponent
, min-exponent
].
41 set properties
(_Decimal32
) [list
7 96 -95]
42 set properties
(_Decimal64
) [list
16 384 -383]
43 set properties
(_Decimal128
) [list
34 6144 -6143]
45 # Operations implemented by the compiler.
46 set operators
(add
) {+}
47 set operators
(compare
) {==}
48 set operators
(divide
) {/}
49 set operators
(multiply
) {*}
50 set operators
(subtract
) {-}
51 set operators
(minus
) {-}
52 set operators
(plus
) {+}
53 set operators
(apply
) {}
55 # Operations imlemented by the library.
56 set libfuncs
(abs) fabsl
57 set libfuncs
(squareroot
) sqrtl
58 set libfuncs
(max) fmaxl
59 set libfuncs
(min) fminl
60 set libfuncs
(quantize
) quantize
61 set libfuncs
(samequantum
) samequantum
62 set libfuncs
(power
) powl
63 set libfuncs
(toSci
) unknown
64 set libfuncs
(tosci
) unknown
65 set libfuncs
(toEng
) unknown
66 set libfuncs
(toeng
) unknown
67 set libfuncs
(divideint
) unknown
68 set libfuncs
(rescale
) unknown
69 set libfuncs
(remainder
) unknown
70 set libfuncs
(remaindernear
) unknown
71 set libfuncs
(normalize
) unknown
72 set libfuncs
(tointegral
) unknown
73 set libfuncs
(trim
) unknown
75 # Run all of the tests listed in TESTCASES by invoking df
-run
-test
on
76 # each. Skip tests that not included by the user invoking runtest
77 # with the foo.exp
=test.c syntax.
79 proc dfp
-run
-tests
{ testcases
} {
81 foreach test $testcases
{
82 #
If we
're only testing specific files and this isn't one of
84 if ![runtest_file_p $runtests $test
] continue
89 # Run a single test case named by TESTCASE.
90 # Called
for each test by dfp
-run
-tests.
92 proc dfp
-run
-test
{ testcase
} {
93 set fd
[open $testcase r
]
94 while {[gets $fd line
] != -1} {
95 switch -regexp
-- $line
{
100 # Ignore
blank lines.
102 {^
[ \t]*[^
:]*:[^
:]*} {
103 regsub
-- {[ \t]*--.
*$
} $line
{} line
104 process
-directive $line
107 process
-test
-case $testcase $line
114 #
Return the appropriate constant from
<fenv.h
> for MODE.
116 proc c
-rounding
-mode { mode } {
117 switch [string tolower $
mode] {
118 "floor" { return 0 } # FE_DEC_DOWNWARD
119 "half_even" { return 1 } # FE_DEC_TONEARESTFROMZERO
120 "half_up" { return 2 } # FE_DEC_TONEAREST
121 "down" { return 3 } # FE_DEC_TOWARDZERO
122 "ceiling" { return 4 } # FE_DEC_UPWARD
124 error
"unsupported rounding mode ($mode)"
127 #
Return a string of C code that forms the preamble to perform the
130 proc c
-test
-preamble
{ id
} {
131 append result
"/* Machine generated test case for $id */\n"
133 append result
"\#include <assert.h>\n"
134 append result
"\#include <fenv.h>\n"
135 append result
"\#include <math.h>\n"
137 append result
"int main ()\n"
142 #
Return a string of C code that forms the postable to the test named ID.
144 proc c
-test
-postamble
{ id
} {
148 # Generate a C unary expression that applies OPERATION to OP.
150 proc c
-unary
-expression
{operation op
} {
153 if [catch
{set result
"$operators($operation) $op"}] {
154 #
If operation isn
't in the operators or libfuncs arrays,
155 # we'll throw an error. That
's what we want.
156 # FIXME: append d32, etc. here.
157 set result "$libfuncs($operation) ($op)"
162 # Generate a C binary expression that applies OPERATION to OP1 and OP2.
164 proc c-binary-expression {operation op1 op2} {
167 if [catch {set result "$op1 $operators($operation) $op2"}] {
168 # If operation isn't in the operators or libfuncs arrays
,
169 # we
'll throw an error. That's what we want.
170 set result
"$libfuncs($operation) ($op1, $op2)"
175 #
Return the most appropriate C type
(_Decimal32
, etc
) for this test.
177 proc c
-decimal
-type
{ } {
179 if [catch
{set precision $directives
(precision
)}] {
180 set precision
"_Decimal128"
182 if { $precision
== 7 } {
183 set result
"_Decimal32"
184 } elseif
{$precision
== 16} {
185 set result
"_Decimal64"
186 } elseif
{$precision
== 34} {
187 set result
"_Decimal128"
189 error
"Unsupported precision"
194 #
Return the size of the most appropriate C type
, in bytes.
196 proc c
-sizeof
-decimal
-type
{ } {
197 switch [c
-decimal
-type
] {
198 "_Decimal32" { return 4 }
199 "_Decimal64" { return 8 }
200 "_Decimal128" { return 16 }
202 error
"Unsupported precision"
205 #
Return the right literal suffix
for CTYPE.
207 proc c
-type
-suffix
{ ctype
} {
209 "_Decimal32" { return "df" }
210 "_Decimal64" { return "dd" }
211 "_Decimal128" { return "dl" }
212 "float" { return "f" }
213 "long double" { return "l" }
218 proc nan
-p
{ operand
} {
219 if {[string match
"NaN*" $operand] || [string match "-NaN*" $operand]} {
226 proc infinity
-p
{ operand
} {
227 if {[string match
"Inf*" $operand] || [string match "-Inf*" $operand]} {
234 proc isnan
-builtin
-name { } {
235 set bits
[expr
[c
-sizeof
-decimal
-type
] * 8]
236 return "__builtin_isnand$bits"
239 proc isinf
-builtin
-name { } {
240 set bits
[expr
[c
-sizeof
-decimal
-type
] * 8]
241 return "__builtin_isinfd$bits"
244 #
Return a string that declares a C union containing the decimal type
245 # and an unsigned char array of the right size.
247 proc c
-union
-decl
{ } {
248 append result
" union {\n"
249 append result
" [c-decimal-type] d;\n"
250 append result
" unsigned char bytes\[[c-sizeof-decimal-type]\];\n"
251 append result
" } u;"
255 proc transform
-hex
-constant
{value
} {
256 regsub \# $value
{} value
257 regsub
-all
(\.\.
) $value
{0x\
1, } bytes
261 # Create a C
program file
(named using ID
) containing a test
for a
262 # binary OPERATION
on OP1 and OP2 that expects RESULT and CONDITIONS.
264 proc make
-c
-test
{testcase id operation result conditions op1
{op2
"NONE"}} {
267 set outfd
[open $filename w
]
269 puts $outfd
[c
-test
-preamble $id
]
270 puts $outfd
[c
-union
-decl
]
271 if {[string compare $result ?
] != 0} {
272 if {[string index $result
0] == "\#"} {
273 puts $outfd
" static unsigned char compare\[[c-sizeof-decimal-type]\] = [transform-hex-constant $result];"
276 if {[string compare $op2
NONE] == 0} {
277 if {[string index $op1
0] == "\#"} {
278 puts $outfd
" static unsigned char fill\[[c-sizeof-decimal-type]\] = [transform-hex-constant $op1];"
283 puts $outfd
" /* FIXME: Set rounding mode with fesetround() once in libc. */"
284 puts $outfd
" __dfp_set_round ([c-rounding-mode $directives(rounding)]);"
287 # Build the expression to be tested.
288 if {[string compare $op2
NONE] == 0} {
289 if {[string index $op1
0] == "\#"} {
290 puts $outfd
" memcpy (u.bytes, fill, [c-sizeof-decimal-type]);"
292 puts $outfd
" u.d = [c-unary-expression $operation [c-operand $op1]];"
295 puts $outfd
" u.d = [c-binary-expression $operation [c-operand $op1] [c-operand $op2]];"
299 if {[string compare $result ?
] != 0} {
300 # Not an undefined result ..
301 if {[string index $result
0] == "\#"} {
302 # Handle hex comparisons.
303 puts $outfd
" return memcmp (u.bytes, compare, [c-sizeof-decimal-type]);"
304 } elseif
{[nan
-p $result
]} {
305 puts $outfd
" return ![isnan-builtin-name] (u.d);"
306 } elseif
{[infinity
-p $result
]} {
307 puts $outfd
" return ![isinf-builtin-name] (u.d);"
310 puts $outfd
" return !(u.d == [c-operand $result]);"
313 puts $outfd
" return 0;"
316 puts $outfd
[c
-test
-postamble $id
]
321 # Is the test supported
for this target?
323 proc supported
-p
{ id op
} {
327 # Ops that are unsupported. Many of these tests fail because they
328 #
do not tolerate the C front
-end rounding the value of floating
329 # point literals to suit the type of the constant. Otherwise
, by
330 # treating the `apply
' operator like C assignment, some of them do
336 # Ditto for the following miscellaneous tests.
338 addx1130 { return 0 }
339 addx1131 { return 0 }
340 addx1132 { return 0 }
341 addx1133 { return 0 }
342 addx1134 { return 0 }
343 addx1135 { return 0 }
344 addx1136 { return 0 }
345 addx1138 { return 0 }
346 addx1139 { return 0 }
347 addx1140 { return 0 }
348 addx1141 { return 0 }
349 addx1142 { return 0 }
350 addx1151 { return 0 }
351 addx1152 { return 0 }
352 addx1153 { return 0 }
353 addx1154 { return 0 }
354 addx1160 { return 0 }
360 if [info exist libfuncs($op)] {
361 # No library support for now.
364 if [catch {c-rounding-mode $directives(rounding)}] {
365 # Unsupported rounding mode.
368 if [catch {c-decimal-type}] {
369 # Unsupported precision.
375 # Break LINE into a list of tokens. Be sensitive to quoting.
376 # There has to be a better way to do this :-|
378 proc tokenize { line } {
382 foreach char [split $line {}] {
384 if { [info exists token] && $char == " " } {
385 if {[string compare "$token" "--"] == 0} {
386 # Only comments remain.
389 lappend tokens $token
392 if {![info exists token] && $char == "'" } {
395 if { $char
!= " " } {
402 if { $char
== "'" } {
404 if [info exists token
] {
405 lappend tokens $token
415 # Flush
any residual token.
416 if {[info exists token
] && [string compare $token
"--"]} {
417 lappend tokens $token
422 # Process a directive in LINE.
424 proc process
-directive
{ line
} {
426 set keyword
[string tolower
[string trim
[lindex
[split $line
:] 0]]]
427 set value
[string tolower
[string trim
[lindex
[split $line
:] 1]]]
428 set directives
($keyword
) $value
431 # Produce a C99
-valid floating point literal.
433 proc c
-operand
{operand
} {
434 set bits
[expr
8 * [c
-sizeof
-decimal
-type
]]
436 switch -glob
-- $operand
{
437 "Inf*" { return "__builtin_infd${bits} ()" }
438 "-Inf*" { return "- __builtin_infd${bits} ()" }
439 "NaN*" { return "__builtin_nand${bits} (\"\")" }
440 "-NaN*" { return "- __builtin_nand${bits} (\"\")" }
441 "sNaN*" { return "__builtin_nand${bits} (\"\")" }
442 "-sNaN*" { return "- __builtin_nand${bits} (\"\")" }
445 if {[string first . $operand
] < 0 && \
446 [string first E $operand
] < 0 && \
447 [string first e $operand
] < 0} {
450 set suffix
[c
-type
-suffix
[c
-decimal
-type
]]
451 return [append operand $suffix
]
454 # Process an arithmetic test in LINE from TESTCASE.
456 proc process
-test
-case
{ testcase line
} {
457 set testfile
[file tail $testcase
]
459 # Compress multiple spaces down to one.
460 regsub
-all
{ *} $line
{ } line
462 set args [tokenize $line
]
463 if {[llength $
args] < 5} {
464 error
"Skipping invalid test: $line"
468 set id
[string trim
[lindex $
args 0]]
469 set operation
[string trim
[lindex $
args 1]]
470 set operand1
[string trim
[lindex $
args 2]]
472 if { [string compare
[lindex $
args 3] -> ] == 0 } {
479 set operand2
[string trim
[lindex $
args 3]]
480 if { [string compare
[lindex $
args 4] -> ] != 0 } {
481 warning
"Skipping invalid test: $line"
488 set result
[string trim
[lindex $
args $result_index
]]
489 set conditions
[list
]
490 for { set i $cond_index
} { $i
< [llength $
args] } { incr i
} {
491 lappend conditions
[string tolower
[lindex $
args $i
]]
494 #
If this test is unsupported
, say so.
495 if ![supported
-p $id $operation
] {
496 unsupported
"$testfile ($id)"
500 if {[string compare $operand1 \#
] == 0 || \
501 [string compare $operand2 \#
] == 0} {
502 unsupported
"$testfile ($id), null reference"
506 # Construct a C
program and
then compile/execute it
on the target.
507 # Grab some stuff from the c
-torture.exp test driver
for this.
509 set cprog
[make
-c
-test $testfile $id $operation $result $conditions $operand1 $operand2
]
510 c
-torture
-execute $cprog
[target
-specific
-flags
]
515 if [catch
{set testdir $env
(DECTEST
)}] {
516 #
If $DECTEST is unset
, skip this test driver altogether.
521 set-torture
-options $DEC_TORTURE_OPTIONS
523 note
"Using tests in $testdir"
524 dfp
-run
-tests
[lsort
[glob
-nocomplain $testdir
/*.decTest
]]