]>
git.proxmox.com Git - mirror_qemu.git/blob - target/hexagon/conv_emu.c
2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "qemu/osdep.h"
19 #include "qemu/host-utils.h"
20 #include "fpu/softfloat.h"
24 #define LL_MAX_POS 0x7fffffffffffffffULL
25 #define MAX_POS 0x7fffffffU
27 static uint64_t conv_f64_to_8u_n(float64 in
, int will_negate
,
28 float_status
*fp_status
)
30 uint8_t sign
= float64_is_neg(in
);
31 if (float64_is_infinity(in
)) {
32 float_raise(float_flag_invalid
, fp_status
);
33 if (float64_is_neg(in
)) {
39 if (float64_is_any_nan(in
)) {
40 float_raise(float_flag_invalid
, fp_status
);
43 if (float64_is_zero(in
)) {
47 float_raise(float_flag_invalid
, fp_status
);
50 if (float64_lt(in
, float64_half
, fp_status
)) {
51 /* Near zero, captures large fracshifts, denorms, etc */
52 float_raise(float_flag_inexact
, fp_status
);
53 switch (get_float_rounding_mode(fp_status
)) {
54 case float_round_down
:
67 return 0; /* nearest or towards zero */
70 return float64_to_uint64(in
, fp_status
);
73 static void clr_float_exception_flags(uint8_t flag
, float_status
*fp_status
)
75 uint8_t flags
= fp_status
->float_exception_flags
;
77 set_float_exception_flags(flags
, fp_status
);
80 static uint32_t conv_df_to_4u_n(float64 fp64
, int will_negate
,
81 float_status
*fp_status
)
84 tmp
= conv_f64_to_8u_n(fp64
, will_negate
, fp_status
);
85 if (tmp
> 0x00000000ffffffffULL
) {
86 clr_float_exception_flags(float_flag_inexact
, fp_status
);
87 float_raise(float_flag_invalid
, fp_status
);
93 uint64_t conv_df_to_8u(float64 in
, float_status
*fp_status
)
95 return conv_f64_to_8u_n(in
, 0, fp_status
);
98 uint32_t conv_df_to_4u(float64 in
, float_status
*fp_status
)
100 return conv_df_to_4u_n(in
, 0, fp_status
);
103 int64_t conv_df_to_8s(float64 in
, float_status
*fp_status
)
105 uint8_t sign
= float64_is_neg(in
);
107 if (float64_is_any_nan(in
)) {
108 float_raise(float_flag_invalid
, fp_status
);
112 float64 minus_fp64
= float64_abs(in
);
113 tmp
= conv_f64_to_8u_n(minus_fp64
, 1, fp_status
);
115 tmp
= conv_f64_to_8u_n(in
, 0, fp_status
);
117 if (tmp
> (LL_MAX_POS
+ sign
)) {
118 clr_float_exception_flags(float_flag_inexact
, fp_status
);
119 float_raise(float_flag_invalid
, fp_status
);
120 tmp
= (LL_MAX_POS
+ sign
);
129 int32_t conv_df_to_4s(float64 in
, float_status
*fp_status
)
131 uint8_t sign
= float64_is_neg(in
);
133 if (float64_is_any_nan(in
)) {
134 float_raise(float_flag_invalid
, fp_status
);
138 float64 minus_fp64
= float64_abs(in
);
139 tmp
= conv_f64_to_8u_n(minus_fp64
, 1, fp_status
);
141 tmp
= conv_f64_to_8u_n(in
, 0, fp_status
);
143 if (tmp
> (MAX_POS
+ sign
)) {
144 clr_float_exception_flags(float_flag_inexact
, fp_status
);
145 float_raise(float_flag_invalid
, fp_status
);
146 tmp
= (MAX_POS
+ sign
);
155 uint64_t conv_sf_to_8u(float32 in
, float_status
*fp_status
)
157 float64 fp64
= float32_to_float64(in
, fp_status
);
158 return conv_df_to_8u(fp64
, fp_status
);
161 uint32_t conv_sf_to_4u(float32 in
, float_status
*fp_status
)
163 float64 fp64
= float32_to_float64(in
, fp_status
);
164 return conv_df_to_4u(fp64
, fp_status
);
167 int64_t conv_sf_to_8s(float32 in
, float_status
*fp_status
)
169 float64 fp64
= float32_to_float64(in
, fp_status
);
170 return conv_df_to_8s(fp64
, fp_status
);
173 int32_t conv_sf_to_4s(float32 in
, float_status
*fp_status
)
175 float64 fp64
= float32_to_float64(in
, fp_status
);
176 return conv_df_to_4s(fp64
, fp_status
);