aboutsummaryrefslogtreecommitdiff
path: root/target-tricore
diff options
context:
space:
mode:
Diffstat (limited to 'target-tricore')
-rw-r--r--target-tricore/Makefile.objs2
-rw-r--r--target-tricore/cpu.h6
-rw-r--r--target-tricore/fpu_helper.c81
-rw-r--r--target-tricore/helper.c10
-rw-r--r--target-tricore/translate.c1
-rw-r--r--target-tricore/tricore-opcodes.h18
6 files changed, 115 insertions, 3 deletions
diff --git a/target-tricore/Makefile.objs b/target-tricore/Makefile.objs
index 21e820d8f9..7a05670718 100644
--- a/target-tricore/Makefile.objs
+++ b/target-tricore/Makefile.objs
@@ -1 +1 @@
-obj-y += translate.o helper.o cpu.o op_helper.o
+obj-y += translate.o helper.o cpu.o op_helper.o fpu_helper.o
diff --git a/target-tricore/cpu.h b/target-tricore/cpu.h
index 5fee376674..90045a93d2 100644
--- a/target-tricore/cpu.h
+++ b/target-tricore/cpu.h
@@ -183,8 +183,7 @@ struct CPUTriCoreState {
uint32_t M2CNT;
uint32_t M3CNT;
/* Floating Point Registers */
- /* XXX: */
-
+ float_status fp_status;
/* QEMU */
int error_code;
uint32_t hflags; /* CPU State */
@@ -217,6 +216,7 @@ struct CPUTriCoreState {
#define MASK_PSW_GW 0x00000100
#define MASK_PSW_CDE 0x00000080
#define MASK_PSW_CDC 0x0000007f
+#define MASK_PSW_FPU_RM 0x3000000
#define MASK_SYSCON_PRO_TEN 0x2
#define MASK_SYSCON_FCD_SF 0x1
@@ -339,6 +339,8 @@ enum {
uint32_t psw_read(CPUTriCoreState *env);
void psw_write(CPUTriCoreState *env, uint32_t val);
+void fpu_set_state(CPUTriCoreState *env);
+
#include "cpu-qom.h"
#define MMU_USER_IDX 2
diff --git a/target-tricore/fpu_helper.c b/target-tricore/fpu_helper.c
new file mode 100644
index 0000000000..7c79c9c6df
--- /dev/null
+++ b/target-tricore/fpu_helper.c
@@ -0,0 +1,81 @@
+/*
+ * TriCore emulation for qemu: fpu helper.
+ *
+ * Copyright (c) 2016 Bastian Koppelmann University of Paderborn
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+
+#define ADD_NAN 0x7cf00001
+#define DIV_NAN 0x7fc00008
+#define MUL_NAN 0x7fc00002
+#define FPU_FS PSW_USB_C
+#define FPU_FI PSW_USB_V
+#define FPU_FV PSW_USB_SV
+#define FPU_FZ PSW_USB_AV
+#define FPU_FU PSW_USB_SAV
+
+/* we don't care about input_denormal */
+static inline uint8_t f_get_excp_flags(CPUTriCoreState *env)
+{
+ return get_float_exception_flags(&env->fp_status)
+ & (float_flag_invalid
+ | float_flag_overflow
+ | float_flag_underflow
+ | float_flag_output_denormal
+ | float_flag_divbyzero
+ | float_flag_inexact);
+}
+
+static inline bool f_is_denormal(float32 arg)
+{
+ return float32_is_zero_or_denormal(arg) && !float32_is_zero(arg);
+}
+
+static inline void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags)
+{
+ uint8_t some_excp = 0;
+ set_float_exception_flags(0, &env->fp_status);
+
+ if (flags & float_flag_invalid) {
+ env->FPU_FI = 1 << 31;
+ some_excp = 1;
+ }
+
+ if (flags & float_flag_overflow) {
+ env->FPU_FV = 1 << 31;
+ some_excp = 1;
+ }
+
+ if (flags & float_flag_underflow || flags & float_flag_output_denormal) {
+ env->FPU_FU = 1 << 31;
+ some_excp = 1;
+ }
+
+ if (flags & float_flag_divbyzero) {
+ env->FPU_FZ = 1 << 31;
+ some_excp = 1;
+ }
+
+ if (flags & float_flag_inexact || flags & float_flag_output_denormal) {
+ env->PSW |= 1 << 26;
+ some_excp = 1;
+ }
+
+ env->FPU_FS = some_excp;
+}
diff --git a/target-tricore/helper.c b/target-tricore/helper.c
index adbb6db10d..71b31cdb9b 100644
--- a/target-tricore/helper.c
+++ b/target-tricore/helper.c
@@ -110,6 +110,14 @@ void tricore_cpu_list(FILE *f, fprintf_function cpu_fprintf)
g_slist_free(list);
}
+void fpu_set_state(CPUTriCoreState *env)
+{
+ set_float_rounding_mode(env->PSW & MASK_PSW_FPU_RM, &env->fp_status);
+ set_flush_inputs_to_zero(1, &env->fp_status);
+ set_flush_to_zero(1, &env->fp_status);
+ set_default_nan_mode(1, &env->fp_status);
+}
+
uint32_t psw_read(CPUTriCoreState *env)
{
/* clear all USB bits */
@@ -132,4 +140,6 @@ void psw_write(CPUTriCoreState *env, uint32_t val)
env->PSW_USB_AV = (val & MASK_USB_AV) << 3;
env->PSW_USB_SAV = (val & MASK_USB_SAV) << 4;
env->PSW = val;
+
+ fpu_set_state(env);
}
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 66f798a9b9..8c429c5387 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -8773,6 +8773,7 @@ void cpu_state_reset(CPUTriCoreState *env)
{
/* Reset Regs to Default Value */
env->PSW = 0xb80;
+ fpu_set_state(env);
}
static void tricore_tcg_init_csfr(void)
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 1bfed0ce48..df666b081f 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -1126,6 +1126,20 @@ enum {
OPC2_32_RR_CRC32 = 0x03,
OPC2_32_RR_DIV = 0x20,
OPC2_32_RR_DIV_U = 0x21,
+ OPC2_32_RR_MUL_F = 0x04,
+ OPC2_32_RR_DIV_F = 0x05,
+ OPC2_32_RR_FTOI = 0x10,
+ OPC2_32_RR_ITOF = 0x14,
+ OPC2_32_RR_CMP_F = 0x00,
+ OPC2_32_RR_FTOIZ = 0x13,
+ OPC2_32_RR_FTOQ31 = 0x11,
+ OPC2_32_RR_FTOQ31Z = 0x18,
+ OPC2_32_RR_FTOU = 0x12,
+ OPC2_32_RR_FTOUZ = 0x17,
+ OPC2_32_RR_Q31TOF = 0x15,
+ OPC2_32_RR_QSEED_F = 0x19,
+ OPC2_32_RR_UPDFL = 0x0c,
+ OPC2_32_RR_UTOF = 0x16,
};
/* OPCM_32_RR_IDIRECT */
enum {
@@ -1209,6 +1223,10 @@ enum {
OPC2_32_RRR_IXMIN = 0x08,
OPC2_32_RRR_IXMIN_U = 0x09,
OPC2_32_RRR_PACK = 0x00,
+ OPC2_32_RRR_ADD_F = 0x02,
+ OPC2_32_RRR_SUB_F = 0x03,
+ OPC2_32_RRR_MADD_F = 0x06,
+ OPC2_32_RRR_MSUB_F = 0x07,
};
/*
* RRR1 Format