diff options
author | Peter Maydell | 2021-02-18 17:33:36 +0100 |
---|---|---|
committer | Peter Maydell | 2021-02-18 17:33:36 +0100 |
commit | c79f01c9450bcf90c08a77f13fbf67bdba59a316 (patch) | |
tree | aed02be84b9b5caffdaa4ad28655e814724eafd7 /target/hexagon/conv_emu.c | |
parent | Merge remote-tracking branch 'remotes/kraxel/tags/usb-20210218-pull-request' ... (diff) | |
parent | Hexagon build infrastructure (diff) | |
download | qemu-c79f01c9450bcf90c08a77f13fbf67bdba59a316.tar.gz qemu-c79f01c9450bcf90c08a77f13fbf67bdba59a316.tar.xz qemu-c79f01c9450bcf90c08a77f13fbf67bdba59a316.zip |
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-hex-20210218' into staging
Initial commit for the Qualcomm Hexagon processor.
# gpg: Signature made Thu 18 Feb 2021 16:26:52 GMT
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* remotes/rth-gitlab/tags/pull-hex-20210218: (35 commits)
Hexagon build infrastructure
Hexagon (tests/tcg/hexagon) TCG tests - floating point
Hexagon (tests/tcg/hexagon) TCG tests - atomics/load/store/misc
Hexagon (tests/tcg/hexagon) TCG tests - multiarch
Hexagon (linux-user/hexagon) Linux user emulation
Hexagon (target/hexagon) translation
Hexagon (target/hexagon) TCG for floating point instructions
Hexagon (target/hexagon) TCG for instructions with multiple definitions
Hexagon (target/hexagon) TCG generation
Hexagon (target/hexagon) instruction classes
Hexagon (target/hexagon) macros
Hexagon (target/hexagon) opcode data structures
Hexagon (target/hexagon) generater phase 4 - decode tree
Hexagon (target/hexagon) generator phase 3 - C preprocessor for decode tree
Hexagon (target/hexagon) generator phase 2 - generate header files
Hexagon (target/hexagon) generator phase 1 - C preprocessor for semantics
Hexagon (target/hexagon/imported) arch import
Hexagon (target/hexagon/fma_emu.[ch]) utility functions
Hexagon (target/hexagon/conv_emu.[ch]) utility functions
Hexagon (target/hexagon/arch.[ch]) utility functions
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/hexagon/conv_emu.c')
-rw-r--r-- | target/hexagon/conv_emu.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/target/hexagon/conv_emu.c b/target/hexagon/conv_emu.c new file mode 100644 index 0000000000..3985b1032a --- /dev/null +++ b/target/hexagon/conv_emu.c @@ -0,0 +1,177 @@ +/* + * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "fpu/softfloat.h" +#include "macros.h" +#include "conv_emu.h" + +#define LL_MAX_POS 0x7fffffffffffffffULL +#define MAX_POS 0x7fffffffU + +static uint64_t conv_f64_to_8u_n(float64 in, int will_negate, + float_status *fp_status) +{ + uint8_t sign = float64_is_neg(in); + if (float64_is_infinity(in)) { + float_raise(float_flag_invalid, fp_status); + if (float64_is_neg(in)) { + return 0ULL; + } else { + return ~0ULL; + } + } + if (float64_is_any_nan(in)) { + float_raise(float_flag_invalid, fp_status); + return ~0ULL; + } + if (float64_is_zero(in)) { + return 0; + } + if (sign) { + float_raise(float_flag_invalid, fp_status); + return 0; + } + if (float64_lt(in, float64_half, fp_status)) { + /* Near zero, captures large fracshifts, denorms, etc */ + float_raise(float_flag_inexact, fp_status); + switch (get_float_rounding_mode(fp_status)) { + case float_round_down: + if (will_negate) { + return 1; + } else { + return 0; + } + case float_round_up: + if (!will_negate) { + return 1; + } else { + return 0; + } + default: + return 0; /* nearest or towards zero */ + } + } + return float64_to_uint64(in, fp_status); +} + +static void clr_float_exception_flags(uint8_t flag, float_status *fp_status) +{ + uint8_t flags = fp_status->float_exception_flags; + flags &= ~flag; + set_float_exception_flags(flags, fp_status); +} + +static uint32_t conv_df_to_4u_n(float64 fp64, int will_negate, + float_status *fp_status) +{ + uint64_t tmp; + tmp = conv_f64_to_8u_n(fp64, will_negate, fp_status); + if (tmp > 0x00000000ffffffffULL) { + clr_float_exception_flags(float_flag_inexact, fp_status); + float_raise(float_flag_invalid, fp_status); + return ~0U; + } + return (uint32_t)tmp; +} + +uint64_t conv_df_to_8u(float64 in, float_status *fp_status) +{ + return conv_f64_to_8u_n(in, 0, fp_status); +} + +uint32_t conv_df_to_4u(float64 in, float_status *fp_status) +{ + return conv_df_to_4u_n(in, 0, fp_status); +} + +int64_t conv_df_to_8s(float64 in, float_status *fp_status) +{ + uint8_t sign = float64_is_neg(in); + uint64_t tmp; + if (float64_is_any_nan(in)) { + float_raise(float_flag_invalid, fp_status); + return -1; + } + if (sign) { + float64 minus_fp64 = float64_abs(in); + tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status); + } else { + tmp = conv_f64_to_8u_n(in, 0, fp_status); + } + if (tmp > (LL_MAX_POS + sign)) { + clr_float_exception_flags(float_flag_inexact, fp_status); + float_raise(float_flag_invalid, fp_status); + tmp = (LL_MAX_POS + sign); + } + if (sign) { + return -tmp; + } else { + return tmp; + } +} + +int32_t conv_df_to_4s(float64 in, float_status *fp_status) +{ + uint8_t sign = float64_is_neg(in); + uint64_t tmp; + if (float64_is_any_nan(in)) { + float_raise(float_flag_invalid, fp_status); + return -1; + } + if (sign) { + float64 minus_fp64 = float64_abs(in); + tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status); + } else { + tmp = conv_f64_to_8u_n(in, 0, fp_status); + } + if (tmp > (MAX_POS + sign)) { + clr_float_exception_flags(float_flag_inexact, fp_status); + float_raise(float_flag_invalid, fp_status); + tmp = (MAX_POS + sign); + } + if (sign) { + return -tmp; + } else { + return tmp; + } +} + +uint64_t conv_sf_to_8u(float32 in, float_status *fp_status) +{ + float64 fp64 = float32_to_float64(in, fp_status); + return conv_df_to_8u(fp64, fp_status); +} + +uint32_t conv_sf_to_4u(float32 in, float_status *fp_status) +{ + float64 fp64 = float32_to_float64(in, fp_status); + return conv_df_to_4u(fp64, fp_status); +} + +int64_t conv_sf_to_8s(float32 in, float_status *fp_status) +{ + float64 fp64 = float32_to_float64(in, fp_status); + return conv_df_to_8s(fp64, fp_status); +} + +int32_t conv_sf_to_4s(float32 in, float_status *fp_status) +{ + float64 fp64 = float32_to_float64(in, fp_status); + return conv_df_to_4s(fp64, fp_status); +} |