scsi: move host_status handling into SCSI drivers
[qemu/ar7.git] / target / hexagon / conv_emu.c
blob3985b1032a49686ba75ed0a0c0f6ee2dbe8eb8d1
1 /*
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"
21 #include "macros.h"
22 #include "conv_emu.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)) {
34 return 0ULL;
35 } else {
36 return ~0ULL;
39 if (float64_is_any_nan(in)) {
40 float_raise(float_flag_invalid, fp_status);
41 return ~0ULL;
43 if (float64_is_zero(in)) {
44 return 0;
46 if (sign) {
47 float_raise(float_flag_invalid, fp_status);
48 return 0;
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:
55 if (will_negate) {
56 return 1;
57 } else {
58 return 0;
60 case float_round_up:
61 if (!will_negate) {
62 return 1;
63 } else {
64 return 0;
66 default:
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;
76 flags &= ~flag;
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)
83 uint64_t tmp;
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);
88 return ~0U;
90 return (uint32_t)tmp;
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);
106 uint64_t tmp;
107 if (float64_is_any_nan(in)) {
108 float_raise(float_flag_invalid, fp_status);
109 return -1;
111 if (sign) {
112 float64 minus_fp64 = float64_abs(in);
113 tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status);
114 } else {
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);
122 if (sign) {
123 return -tmp;
124 } else {
125 return tmp;
129 int32_t conv_df_to_4s(float64 in, float_status *fp_status)
131 uint8_t sign = float64_is_neg(in);
132 uint64_t tmp;
133 if (float64_is_any_nan(in)) {
134 float_raise(float_flag_invalid, fp_status);
135 return -1;
137 if (sign) {
138 float64 minus_fp64 = float64_abs(in);
139 tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status);
140 } else {
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);
148 if (sign) {
149 return -tmp;
150 } else {
151 return tmp;
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);