aboutsummaryrefslogtreecommitdiff
path: root/target/unicore32/ucf64_helper.c
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2016-10-11 08:56:52 +0200
committerThomas Huth <thuth@redhat.com>2016-12-20 21:52:12 +0100
commitfcf5ef2ab52c621a4617ebbef36bf43b4003f4c0 (patch)
tree2b450d96b01455df8ed908bf8f26ddc388a03380 /target/unicore32/ucf64_helper.c
parent82ecffa8c050bf5bbc13329e9b65eac1caa5b55c (diff)
Move target-* CPU file into a target/ folder
We've currently got 18 architectures in QEMU, and thus 18 target-xxx folders in the root folder of the QEMU source tree. More architectures (e.g. RISC-V, AVR) are likely to be included soon, too, so the main folder of the QEMU sources slowly gets quite overcrowded with the target-xxx folders. To disburden the main folder a little bit, let's move the target-xxx folders into a dedicated target/ folder, so that target-xxx/ simply becomes target/xxx/ instead. Acked-by: Laurent Vivier <laurent@vivier.eu> [m68k part] Acked-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> [tricore part] Acked-by: Michael Walle <michael@walle.cc> [lm32 part] Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> [s390x part] Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> [s390x part] Acked-by: Eduardo Habkost <ehabkost@redhat.com> [i386 part] Acked-by: Artyom Tarasenko <atar4qemu@gmail.com> [sparc part] Acked-by: Richard Henderson <rth@twiddle.net> [alpha part] Acked-by: Max Filippov <jcmvbkbc@gmail.com> [xtensa part] Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ppc part] Acked-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> [cris&microblaze part] Acked-by: Guan Xuetao <gxt@mprc.pku.edu.cn> [unicore32 part] Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'target/unicore32/ucf64_helper.c')
-rw-r--r--target/unicore32/ucf64_helper.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/target/unicore32/ucf64_helper.c b/target/unicore32/ucf64_helper.c
new file mode 100644
index 0000000000..6c919010c3
--- /dev/null
+++ b/target/unicore32/ucf64_helper.c
@@ -0,0 +1,325 @@
+/*
+ * UniCore-F64 simulation helpers for QEMU.
+ *
+ * Copyright (C) 2010-2012 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or any later version.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+
+/*
+ * The convention used for UniCore-F64 instructions:
+ * Single precition routines have a "s" suffix
+ * Double precision routines have a "d" suffix.
+ */
+
+/* Convert host exception flags to f64 form. */
+static inline int ucf64_exceptbits_from_host(int host_bits)
+{
+ int target_bits = 0;
+
+ if (host_bits & float_flag_invalid) {
+ target_bits |= UCF64_FPSCR_FLAG_INVALID;
+ }
+ if (host_bits & float_flag_divbyzero) {
+ target_bits |= UCF64_FPSCR_FLAG_DIVZERO;
+ }
+ if (host_bits & float_flag_overflow) {
+ target_bits |= UCF64_FPSCR_FLAG_OVERFLOW;
+ }
+ if (host_bits & float_flag_underflow) {
+ target_bits |= UCF64_FPSCR_FLAG_UNDERFLOW;
+ }
+ if (host_bits & float_flag_inexact) {
+ target_bits |= UCF64_FPSCR_FLAG_INEXACT;
+ }
+ return target_bits;
+}
+
+uint32_t HELPER(ucf64_get_fpscr)(CPUUniCore32State *env)
+{
+ int i;
+ uint32_t fpscr;
+
+ fpscr = (env->ucf64.xregs[UC32_UCF64_FPSCR] & UCF64_FPSCR_MASK);
+ i = get_float_exception_flags(&env->ucf64.fp_status);
+ fpscr |= ucf64_exceptbits_from_host(i);
+ return fpscr;
+}
+
+/* Convert ucf64 exception flags to target form. */
+static inline int ucf64_exceptbits_to_host(int target_bits)
+{
+ int host_bits = 0;
+
+ if (target_bits & UCF64_FPSCR_FLAG_INVALID) {
+ host_bits |= float_flag_invalid;
+ }
+ if (target_bits & UCF64_FPSCR_FLAG_DIVZERO) {
+ host_bits |= float_flag_divbyzero;
+ }
+ if (target_bits & UCF64_FPSCR_FLAG_OVERFLOW) {
+ host_bits |= float_flag_overflow;
+ }
+ if (target_bits & UCF64_FPSCR_FLAG_UNDERFLOW) {
+ host_bits |= float_flag_underflow;
+ }
+ if (target_bits & UCF64_FPSCR_FLAG_INEXACT) {
+ host_bits |= float_flag_inexact;
+ }
+ return host_bits;
+}
+
+void HELPER(ucf64_set_fpscr)(CPUUniCore32State *env, uint32_t val)
+{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
+ int i;
+ uint32_t changed;
+
+ changed = env->ucf64.xregs[UC32_UCF64_FPSCR];
+ env->ucf64.xregs[UC32_UCF64_FPSCR] = (val & UCF64_FPSCR_MASK);
+
+ changed ^= val;
+ if (changed & (UCF64_FPSCR_RND_MASK)) {
+ i = UCF64_FPSCR_RND(val);
+ switch (i) {
+ case 0:
+ i = float_round_nearest_even;
+ break;
+ case 1:
+ i = float_round_to_zero;
+ break;
+ case 2:
+ i = float_round_up;
+ break;
+ case 3:
+ i = float_round_down;
+ break;
+ default: /* 100 and 101 not implement */
+ cpu_abort(CPU(cpu), "Unsupported UniCore-F64 round mode");
+ }
+ set_float_rounding_mode(i, &env->ucf64.fp_status);
+ }
+
+ i = ucf64_exceptbits_to_host(UCF64_FPSCR_TRAPEN(val));
+ set_float_exception_flags(i, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_adds)(float32 a, float32 b, CPUUniCore32State *env)
+{
+ return float32_add(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_addd)(float64 a, float64 b, CPUUniCore32State *env)
+{
+ return float64_add(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_subs)(float32 a, float32 b, CPUUniCore32State *env)
+{
+ return float32_sub(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_subd)(float64 a, float64 b, CPUUniCore32State *env)
+{
+ return float64_sub(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_muls)(float32 a, float32 b, CPUUniCore32State *env)
+{
+ return float32_mul(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_muld)(float64 a, float64 b, CPUUniCore32State *env)
+{
+ return float64_mul(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_divs)(float32 a, float32 b, CPUUniCore32State *env)
+{
+ return float32_div(a, b, &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_divd)(float64 a, float64 b, CPUUniCore32State *env)
+{
+ return float64_div(a, b, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_negs)(float32 a)
+{
+ return float32_chs(a);
+}
+
+float64 HELPER(ucf64_negd)(float64 a)
+{
+ return float64_chs(a);
+}
+
+float32 HELPER(ucf64_abss)(float32 a)
+{
+ return float32_abs(a);
+}
+
+float64 HELPER(ucf64_absd)(float64 a)
+{
+ return float64_abs(a);
+}
+
+void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c,
+ CPUUniCore32State *env)
+{
+ int flag;
+ flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
+ env->CF = 0;
+ switch (c & 0x7) {
+ case 0: /* F */
+ break;
+ case 1: /* UN */
+ if (flag == 2) {
+ env->CF = 1;
+ }
+ break;
+ case 2: /* EQ */
+ if (flag == 0) {
+ env->CF = 1;
+ }
+ break;
+ case 3: /* UEQ */
+ if ((flag == 0) || (flag == 2)) {
+ env->CF = 1;
+ }
+ break;
+ case 4: /* OLT */
+ if (flag == -1) {
+ env->CF = 1;
+ }
+ break;
+ case 5: /* ULT */
+ if ((flag == -1) || (flag == 2)) {
+ env->CF = 1;
+ }
+ break;
+ case 6: /* OLE */
+ if ((flag == -1) || (flag == 0)) {
+ env->CF = 1;
+ }
+ break;
+ case 7: /* ULE */
+ if (flag != 1) {
+ env->CF = 1;
+ }
+ break;
+ }
+ env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
+ | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
+}
+
+void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c,
+ CPUUniCore32State *env)
+{
+ int flag;
+ flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
+ env->CF = 0;
+ switch (c & 0x7) {
+ case 0: /* F */
+ break;
+ case 1: /* UN */
+ if (flag == 2) {
+ env->CF = 1;
+ }
+ break;
+ case 2: /* EQ */
+ if (flag == 0) {
+ env->CF = 1;
+ }
+ break;
+ case 3: /* UEQ */
+ if ((flag == 0) || (flag == 2)) {
+ env->CF = 1;
+ }
+ break;
+ case 4: /* OLT */
+ if (flag == -1) {
+ env->CF = 1;
+ }
+ break;
+ case 5: /* ULT */
+ if ((flag == -1) || (flag == 2)) {
+ env->CF = 1;
+ }
+ break;
+ case 6: /* OLE */
+ if ((flag == -1) || (flag == 0)) {
+ env->CF = 1;
+ }
+ break;
+ case 7: /* ULE */
+ if (flag != 1) {
+ env->CF = 1;
+ }
+ break;
+ }
+ env->ucf64.xregs[UC32_UCF64_FPSCR] = (env->CF << 29)
+ | (env->ucf64.xregs[UC32_UCF64_FPSCR] & 0x0fffffff);
+}
+
+/* Helper routines to perform bitwise copies between float and int. */
+static inline float32 ucf64_itos(uint32_t i)
+{
+ union {
+ uint32_t i;
+ float32 s;
+ } v;
+
+ v.i = i;
+ return v.s;
+}
+
+static inline uint32_t ucf64_stoi(float32 s)
+{
+ union {
+ uint32_t i;
+ float32 s;
+ } v;
+
+ v.s = s;
+ return v.i;
+}
+
+/* Integer to float conversion. */
+float32 HELPER(ucf64_si2sf)(float32 x, CPUUniCore32State *env)
+{
+ return int32_to_float32(ucf64_stoi(x), &env->ucf64.fp_status);
+}
+
+float64 HELPER(ucf64_si2df)(float32 x, CPUUniCore32State *env)
+{
+ return int32_to_float64(ucf64_stoi(x), &env->ucf64.fp_status);
+}
+
+/* Float to integer conversion. */
+float32 HELPER(ucf64_sf2si)(float32 x, CPUUniCore32State *env)
+{
+ return ucf64_itos(float32_to_int32(x, &env->ucf64.fp_status));
+}
+
+float32 HELPER(ucf64_df2si)(float64 x, CPUUniCore32State *env)
+{
+ return ucf64_itos(float64_to_int32(x, &env->ucf64.fp_status));
+}
+
+/* floating point conversion */
+float64 HELPER(ucf64_sf2df)(float32 x, CPUUniCore32State *env)
+{
+ return float32_to_float64(x, &env->ucf64.fp_status);
+}
+
+float32 HELPER(ucf64_df2sf)(float64 x, CPUUniCore32State *env)
+{
+ return float64_to_float32(x, &env->ucf64.fp_status);
+}