Skip to content

Commit 245cfbb

Browse files
add int <-> float conversions
1 parent 5382fe9 commit 245cfbb

20 files changed

+9365
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: LGPL-2.1-or-later
3+
# See Notices.txt for copyright information
4+
set -e
5+
6+
if [[ -z "$SOFTFLOAT_VERIFY" ]] && ! SOFTFLOAT_VERIFY="`which softfloat-verify`"; then
7+
echo "can't find softfloat-verify in PATH" >&2
8+
echo "get it from https://salsa.debian.org/Kazan-team/softfloat-verify" >&2
9+
echo "then put built executable in PATH or set" >&2
10+
echo "SOFTFLOAT_VERIFY to path of executable" >&2
11+
exit 1
12+
fi
13+
14+
function fail() {
15+
echo "$*">&2
16+
exit 1
17+
}
18+
19+
function write_test_case() {
20+
local value="$1"
21+
local op="$2"
22+
local exact="$3"
23+
local rounding_mode="$4"
24+
local src_width
25+
local dest_width
26+
local sf_op
27+
local dest_sign_mask=0
28+
case "$op" in
29+
f16_to_u32)
30+
src_width=16
31+
dest_width=32
32+
sf_op=f16_to_ui32
33+
;;
34+
f16_to_i32)
35+
src_width=16
36+
dest_width=32
37+
sf_op=f16_to_i32
38+
dest_sign_mask=0x80000000
39+
;;
40+
f16_to_u64)
41+
src_width=16
42+
dest_width=64
43+
sf_op=f16_to_ui64
44+
;;
45+
f16_to_i64)
46+
src_width=16
47+
dest_width=64
48+
sf_op=f16_to_i64
49+
dest_sign_mask=0x8000000000000000
50+
;;
51+
f32_to_u32)
52+
src_width=32
53+
dest_width=32
54+
sf_op=f32_to_ui32
55+
;;
56+
f32_to_i32)
57+
src_width=32
58+
dest_width=32
59+
sf_op=f32_to_i32
60+
dest_sign_mask=0x80000000
61+
;;
62+
f32_to_u64)
63+
src_width=32
64+
dest_width=64
65+
sf_op=f32_to_ui64
66+
;;
67+
f32_to_i64)
68+
src_width=32
69+
dest_width=64
70+
sf_op=f32_to_i64
71+
dest_sign_mask=0x8000000000000000
72+
;;
73+
*)
74+
fail "op not implemented: $op"
75+
;;
76+
esac
77+
printf -v value "0x%0*X" $((src_width / 4)) $((value))
78+
local sf_rounding_mode
79+
case "$rounding_mode" in
80+
TiesToEven)
81+
sf_rounding_mode=near_even
82+
;;
83+
TowardZero)
84+
sf_rounding_mode=minMag
85+
;;
86+
TowardNegative)
87+
sf_rounding_mode=min
88+
;;
89+
TowardPositive)
90+
sf_rounding_mode=max
91+
;;
92+
TiesToAway)
93+
sf_rounding_mode=near_maxMag
94+
;;
95+
*)
96+
fail "invalid rounding mode: $rounding_mode"
97+
;;
98+
esac
99+
local sf_exact
100+
case "$exact" in
101+
false)
102+
sf_exact=0
103+
;;
104+
true)
105+
sf_exact=1
106+
;;
107+
*)
108+
fail "invalid exact flag: $exact"
109+
;;
110+
esac
111+
local input="softfloat_round_$sf_rounding_mode softfloat_roundingMode_write_helper"
112+
input+=" 0 softfloat_exceptionFlags_write_helper"
113+
input+=" $value softfloat_round_$sf_rounding_mode $sf_exact $sf_op"
114+
input+=" softfloat_exceptionFlags_read_helper"
115+
input+=" softfloat_flag_inexact"
116+
input+=" softfloat_flag_underflow"
117+
input+=" softfloat_flag_overflow"
118+
input+=" softfloat_flag_infinite"
119+
input+=" softfloat_flag_invalid"
120+
local output
121+
output=(`echo "$input" | "$SOFTFLOAT_VERIFY"`) || fail $'softfloat-verify failed. input:\n'"$input"
122+
((${#output[@]} == 7)) || fail $'softfloat-verify returned invalid number of outputs. input:\n'"$input"
123+
local result="${output[0]}"
124+
local flags="${output[1]}"
125+
local flag_inexact="${output[2]}"
126+
local flag_underflow="${output[3]}"
127+
local flag_overflow="${output[4]}"
128+
local flag_infinite="${output[5]}"
129+
local flag_invalid="${output[6]}"
130+
local decoded_flags=()
131+
((flags & flag_inexact)) && decoded_flags+=("INEXACT")
132+
((flags & flag_underflow)) && decoded_flags+=("UNDERFLOW")
133+
((flags & flag_overflow)) && decoded_flags+=("OVERFLOW")
134+
((flags & flag_infinite)) && decoded_flags+=("DIVISION_BY_ZERO")
135+
((flags & flag_invalid)) && decoded_flags+=("INVALID_OPERATION")
136+
if ((flags & flag_invalid)); then
137+
result="None"
138+
elif ((result & dest_sign_mask)); then
139+
printf -v result "%s0x%X" '-' $((-result))
140+
else
141+
printf -v result "0x%X" $((result))
142+
fi
143+
if (( ${#decoded_flags[@]} )); then
144+
printf -v flags "%s|" "${decoded_flags[@]}"
145+
flags="${flags%%|}"
146+
else
147+
flags="(empty)"
148+
fi
149+
echo "$value $exact $rounding_mode $result $flags"
150+
}
151+
152+
f16_test_case_list=(0x0000 0x0001 0x03FF 0x0400 0x3C00 0x3C01 0x7BFF 0x7C00 0x7C01 0x7DFF 0x7E00 0x7FFF)
153+
f16_test_case_list+=(0x8000 0x8001 0x83FF 0x8400 0xBC00 0xBC01 0xFBFF 0xFC00 0xFC01 0xFDFF 0xFE00 0xFFFF)
154+
f16_test_case_list+=(0x3400 0x3800 0x3A00 0x3C00 0x3D00 0x3E00 0x3F00 0x4000 0x4080 0x4100 0x4180 0x4200)
155+
f16_test_case_list+=(0xB400 0xB800 0xBA00 0xBC00 0xBD00 0xBE00 0xBF00 0xC000 0xC080 0xC100 0xC180 0xC200)
156+
f32_test_case_list=(0x00000000 0x00000001 0x007FFFFF 0x00800000 0x3F800000 0x3F800001 0x7F7FFFFF 0x7F800000 0x7F800001 0x7FBFFFFF 0x7FC00000 0x7FFFFFFF)
157+
f32_test_case_list+=(0x80000000 0x80000001 0x807FFFFF 0x80800000 0xBF800000 0xBF800001 0xFF7FFFFF 0xFF800000 0xFF800001 0xFFBFFFFF 0xFFC00000 0xFFFFFFFF)
158+
f32_test_case_list+=(0x3E800000 0x3F000000 0x3F400000 0x3F800000 0x3FA00000 0x3FC00000 0x3FE00000 0x40000000 0x40100000 0x40200000 0x40300000 0x40400000)
159+
f32_test_case_list+=(0xBE800000 0xBF000000 0xBF400000 0xBF800000 0xBFA00000 0xBFC00000 0xBFE00000 0xC0000000 0xC0100000 0xC0200000 0xC0300000 0xC0400000)
160+
f32_test_case_list+=(0x33800000 0x387FC000 0x38800000 0x3F800000 0x3F802000 0x477FE000 0x47800000)
161+
f32_test_case_list+=(0xB3800000 0xB87FC000 0xB8800000 0xBF800000 0xBF802000 0xC77FE000 0xC7800000)
162+
f32_test_case_list+=(0x4EFFFFFF 0x4F000000 0x4F000001 0x4F7FFFFF 0x4F800000 0x4F800001 0x5EFFFFFF 0x5F000000 0x5F000001 0x5F7FFFFF 0x5F800000 0x5F800001)
163+
f32_test_case_list+=(0xCEFFFFFF 0xCF000000 0xCF000001 0xCF7FFFFF 0xCF800000 0xCF800001 0xDEFFFFFF 0xDF000000 0xDF000001 0xDF7FFFFF 0xDF800000 0xDF800001)
164+
ops=(f16_to_u32 f16_to_i32 f16_to_u64 f16_to_i64)
165+
ops+=(f32_to_u32 f32_to_i32 f32_to_u64 f32_to_i64)
166+
rounding_modes=(TiesToEven TowardZero TowardNegative TowardPositive TiesToAway)
167+
168+
for op in "${ops[@]}"; do
169+
exec > "test_data/$op.txt"
170+
first=1
171+
for rounding_mode in "${rounding_modes[@]}"; do
172+
for exact in false true; do
173+
if ((first)); then
174+
first=0
175+
else
176+
echo
177+
fi
178+
echo "# testing $op with exact=$exact $rounding_mode"
179+
case "$op" in
180+
f16_to_*)
181+
test_case_list=("${f16_test_case_list[@]}")
182+
;;
183+
f32_to_*)
184+
test_case_list=("${f32_test_case_list[@]}")
185+
;;
186+
*)
187+
fail "op not implemented: $op"
188+
;;
189+
esac
190+
for value in "${test_case_list[@]}"; do
191+
write_test_case $value $op $exact $rounding_mode
192+
done
193+
printf "." >&2
194+
done
195+
done &
196+
done
197+
wait
198+
echo >&2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: LGPL-2.1-or-later
3+
# See Notices.txt for copyright information
4+
set -e
5+
6+
if [[ -z "$SOFTFLOAT_VERIFY" ]] && ! SOFTFLOAT_VERIFY="`which softfloat-verify`"; then
7+
echo "can't find softfloat-verify in PATH" >&2
8+
echo "get it from https://salsa.debian.org/Kazan-team/softfloat-verify" >&2
9+
echo "then put built executable in PATH or set" >&2
10+
echo "SOFTFLOAT_VERIFY to path of executable" >&2
11+
exit 1
12+
fi
13+
14+
function fail() {
15+
echo "$*">&2
16+
exit 1
17+
}
18+
19+
function write_test_case() {
20+
local value="$1"
21+
local op="$2"
22+
local rounding_mode="$3"
23+
local tininess_detection_mode="$4"
24+
local src_width
25+
local dest_width
26+
local src_sign_mask=0
27+
local sf_op="$op"
28+
case "$op" in
29+
i32_to_f16)
30+
src_width=32
31+
dest_width=16
32+
src_sign_mask=0x80000000
33+
;;
34+
u32_to_f16)
35+
src_width=32
36+
dest_width=16
37+
sf_op=ui32_to_f16
38+
;;
39+
i64_to_f16)
40+
src_width=64
41+
dest_width=16
42+
src_sign_mask=0x8000000000000000
43+
;;
44+
u64_to_f16)
45+
src_width=64
46+
dest_width=16
47+
sf_op=ui64_to_f16
48+
;;
49+
i32_to_f32)
50+
src_width=32
51+
dest_width=32
52+
src_sign_mask=0x80000000
53+
;;
54+
u32_to_f32)
55+
src_width=32
56+
dest_width=32
57+
sf_op=ui32_to_f32
58+
;;
59+
i64_to_f32)
60+
src_width=64
61+
dest_width=32
62+
src_sign_mask=0x8000000000000000
63+
;;
64+
u64_to_f32)
65+
src_width=64
66+
dest_width=32
67+
sf_op=ui64_to_f32
68+
;;
69+
*)
70+
fail "op not implemented: $op"
71+
;;
72+
esac
73+
local src_mask
74+
case "$src_width" in
75+
32)
76+
src_mask=0xFFFFFFFF
77+
;;
78+
64)
79+
src_mask=0xFFFFFFFFFFFFFFFF
80+
;;
81+
*)
82+
fail "src_width not implemented: $src_width"
83+
;;
84+
esac
85+
local hex_value
86+
printf -v hex_value "0x%X" $((value & src_mask))
87+
if ((value & src_sign_mask)); then
88+
printf -v value "%s0x%X" '-' $((-value & src_mask))
89+
else
90+
printf -v value "0x%X" $((value & src_mask))
91+
fi
92+
local sf_rounding_mode
93+
case "$rounding_mode" in
94+
TiesToEven)
95+
sf_rounding_mode=near_even
96+
;;
97+
TowardZero)
98+
sf_rounding_mode=minMag
99+
;;
100+
TowardNegative)
101+
sf_rounding_mode=min
102+
;;
103+
TowardPositive)
104+
sf_rounding_mode=max
105+
;;
106+
TiesToAway)
107+
sf_rounding_mode=near_maxMag
108+
;;
109+
*)
110+
fail "invalid rounding mode: $rounding_mode"
111+
;;
112+
esac
113+
local input="softfloat_round_$sf_rounding_mode softfloat_roundingMode_write_helper"
114+
input+=" 0 softfloat_exceptionFlags_write_helper"
115+
input+=" softfloat_tininess_${tininess_detection_mode,} softfloat_detectTininess_write_helper"
116+
input+=" $hex_value"
117+
input+=" $sf_op"
118+
input+=" softfloat_exceptionFlags_read_helper"
119+
input+=" softfloat_flag_inexact"
120+
input+=" softfloat_flag_underflow"
121+
input+=" softfloat_flag_overflow"
122+
input+=" softfloat_flag_infinite"
123+
input+=" softfloat_flag_invalid"
124+
local output
125+
output=(`echo "$input" | "$SOFTFLOAT_VERIFY"`) || fail $'softfloat-verify failed. input:\n'"$input"
126+
((${#output[@]} == 7)) || fail $'softfloat-verify returned invalid number of outputs. input:\n'"$input"
127+
local result="${output[0]}"
128+
local flags="${output[1]}"
129+
local flag_inexact="${output[2]}"
130+
local flag_underflow="${output[3]}"
131+
local flag_overflow="${output[4]}"
132+
local flag_infinite="${output[5]}"
133+
local flag_invalid="${output[6]}"
134+
local decoded_flags=()
135+
((flags & flag_inexact)) && decoded_flags+=("INEXACT")
136+
((flags & flag_underflow)) && decoded_flags+=("UNDERFLOW")
137+
((flags & flag_overflow)) && decoded_flags+=("OVERFLOW")
138+
((flags & flag_infinite)) && decoded_flags+=("DIVISION_BY_ZERO")
139+
((flags & flag_invalid)) && decoded_flags+=("INVALID_OPERATION")
140+
if (( ${#decoded_flags[@]} )); then
141+
printf -v flags "%s|" "${decoded_flags[@]}"
142+
flags="${flags%%|}"
143+
else
144+
flags="(empty)"
145+
fi
146+
case "$dest_width" in
147+
16)
148+
if (((result & 0x7C00) == 0x7C00 && (result & 0x3FF) != 0)); then
149+
result=0x7E00
150+
fi
151+
;;
152+
32)
153+
if (((result & 0x7F800000) == 0x7F800000 && (result & 0x7FFFFF) != 0)); then
154+
result=0x7FC00000
155+
fi
156+
;;
157+
*)
158+
fail "dest_width not implemented: $dest_width"
159+
;;
160+
esac
161+
printf -v result "0x%0*X" $((dest_width / 4)) $((result))
162+
echo "$value $rounding_mode $tininess_detection_mode $result $flags"
163+
}
164+
165+
test_case_list=(0x0)
166+
test_case_list+=(0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x7FF 0x800 0x801 0xFFE0 0xFFE1 0xFFEF 0xFFF0 0xFFF1)
167+
test_case_list+=(0x7FFFFFFF 0x80000000 0x7FFFFFFFFFFFFFFF 0x8000000000000000)
168+
test_case_list+=(-0x1 -0x2 -0x3 -0x4 -0x5 -0x6 -0x7 -0x7FF -0x800 -0x801 -0xFFE0 -0xFFE1 -0xFFEF -0xFFF0 -0xFFF1)
169+
test_case_list+=(-0x7FFFFFFF -0x80000000 -0x7FFFFFFFFFFFFFFF -0x8000000000000000)
170+
ops=(i32_to_f16 u32_to_f16 i64_to_f16 u64_to_f16 i32_to_f32 u32_to_f32 i64_to_f32 u64_to_f32)
171+
rounding_modes=(TiesToEven TowardZero TowardNegative TowardPositive TiesToAway)
172+
tininess_detection_modes=(BeforeRounding AfterRounding)
173+
174+
for op in "${ops[@]}"; do
175+
exec > "test_data/$op.txt"
176+
first=1
177+
for rounding_mode in "${rounding_modes[@]}"; do
178+
for tininess_detection_mode in "${tininess_detection_modes[@]}"; do
179+
if ((first)); then
180+
first=0
181+
else
182+
echo
183+
fi
184+
echo "# testing $op with $rounding_mode $tininess_detection_mode"
185+
for value in "${test_case_list[@]}"; do
186+
write_test_case $value $op $rounding_mode $tininess_detection_mode
187+
done
188+
printf "." >&2
189+
done
190+
done &
191+
done
192+
wait
193+
echo >&2

0 commit comments

Comments
 (0)