* [Qemu-devel] [PATCH v2 00/10] Alpha updates
@ 2012-03-24 16:51 Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 01/10] alpha-linux-user: Initialize fpu to round-to-normal Richard Henderson
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Changes v1->v2:
* Formatting fixed during the move to new files. It might have been
cleaner to fix it before the move, but it was easier to run the
existing patches through checkpatch.pl.
* Add noreturn marker, now that it's available.
r~
Richard Henderson (10):
alpha-linux-user: Initialize fpu to round-to-normal.
target-alpha: Move integer helpers to int_helper.c.
target-alpha: Move exception helpers to helper.c.
target-alpha: Move floating-point helpers to fpu_helper.c.
target-alpha: Move fpcr helpers from op_helper.c to helper.c.
target-alpha: Move integer overflow helpers to int_helper.c.
target-alpha: Move palcode support helpers to sys_helper.c.
target-alpha: Move memory helpers to mem_helper.c.
target-alpha: Make use of fp_status.flush_inputs_to_zero.
target-alpha: Use noreturn marker in helper.h.
Makefile.target | 3 +
configure | 2 +-
target-alpha/cpu.h | 4 +-
target-alpha/fpu_helper.c | 822 +++++++++++++++++++++++++++
target-alpha/helper.c | 61 ++-
target-alpha/helper.h | 143 +++---
target-alpha/int_helper.c | 320 +++++++++++
target-alpha/mem_helper.c | 151 +++++
target-alpha/op_helper.c | 1379 ---------------------------------------------
target-alpha/sys_helper.c | 87 +++
target-alpha/translate.c | 222 +++++---
11 files changed, 1643 insertions(+), 1551 deletions(-)
create mode 100644 target-alpha/fpu_helper.c
create mode 100644 target-alpha/int_helper.c
create mode 100644 target-alpha/mem_helper.c
delete mode 100644 target-alpha/op_helper.c
create mode 100644 target-alpha/sys_helper.c
--
1.7.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 01/10] alpha-linux-user: Initialize fpu to round-to-normal.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 02/10] target-alpha: Move integer helpers to int_helper.c Richard Henderson
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index b51fe5c..2c24619 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3513,7 +3513,8 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
#if defined (CONFIG_USER_ONLY)
env->ps = PS_USER_MODE;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
- | FPCR_UNFD | FPCR_INED | FPCR_DNOD));
+ | FPCR_UNFD | FPCR_INED | FPCR_DNOD
+ | FPCR_DYN_NORMAL));
#endif
env->lock_addr = -1;
env->fen = 1;
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 02/10] target-alpha: Move integer helpers to int_helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 01/10] alpha-linux-user: Initialize fpu to round-to-normal Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 03/10] target-alpha: Move exception helpers to helper.c Richard Henderson
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 1 +
target-alpha/int_helper.c | 257 +++++++++++++++++++++++++++++++++++++++++++++
target-alpha/op_helper.c | 233 ----------------------------------------
3 files changed, 258 insertions(+), 233 deletions(-)
create mode 100644 target-alpha/int_helper.c
diff --git a/Makefile.target b/Makefile.target
index 63cf769..ddeb7e0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,6 +96,7 @@ libobj-y += cpu_init.o
endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
new file mode 100644
index 0000000..79c0cfe
--- /dev/null
+++ b/target-alpha/int_helper.c
@@ -0,0 +1,257 @@
+/*
+ * Helpers for integer and multimedia instructions.
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+#include "host-utils.h"
+
+
+uint64_t helper_umulh(uint64_t op1, uint64_t op2)
+{
+ uint64_t tl, th;
+ mulu64(&tl, &th, op1, op2);
+ return th;
+}
+
+uint64_t helper_ctpop(uint64_t arg)
+{
+ return ctpop64(arg);
+}
+
+uint64_t helper_ctlz(uint64_t arg)
+{
+ return clz64(arg);
+}
+
+uint64_t helper_cttz(uint64_t arg)
+{
+ return ctz64(arg);
+}
+
+static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
+{
+ uint64_t mask;
+
+ mask = 0;
+ mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
+ mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
+ mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
+ mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
+ mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
+ mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
+ mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
+ mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
+
+ return op & ~mask;
+}
+
+uint64_t helper_zap(uint64_t val, uint64_t mask)
+{
+ return byte_zap(val, mask);
+}
+
+uint64_t helper_zapnot(uint64_t val, uint64_t mask)
+{
+ return byte_zap(val, ~mask);
+}
+
+uint64_t helper_cmpbge(uint64_t op1, uint64_t op2)
+{
+ uint8_t opa, opb, res;
+ int i;
+
+ res = 0;
+ for (i = 0; i < 8; i++) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ if (opa >= opb) {
+ res |= 1 << i;
+ }
+ }
+ return res;
+}
+
+uint64_t helper_minub8(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ uint8_t opa, opb, opr;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ opr = opa < opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 8);
+ }
+ return res;
+}
+
+uint64_t helper_minsb8(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ int8_t opa, opb;
+ uint8_t opr;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ opr = opa < opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 8);
+ }
+ return res;
+}
+
+uint64_t helper_minuw4(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ uint16_t opa, opb, opr;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ opa = op1 >> (i * 16);
+ opb = op2 >> (i * 16);
+ opr = opa < opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 16);
+ }
+ return res;
+}
+
+uint64_t helper_minsw4(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ int16_t opa, opb;
+ uint16_t opr;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ opa = op1 >> (i * 16);
+ opb = op2 >> (i * 16);
+ opr = opa < opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 16);
+ }
+ return res;
+}
+
+uint64_t helper_maxub8(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ uint8_t opa, opb, opr;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ opr = opa > opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 8);
+ }
+ return res;
+}
+
+uint64_t helper_maxsb8(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ int8_t opa, opb;
+ uint8_t opr;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ opr = opa > opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 8);
+ }
+ return res;
+}
+
+uint64_t helper_maxuw4(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ uint16_t opa, opb, opr;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ opa = op1 >> (i * 16);
+ opb = op2 >> (i * 16);
+ opr = opa > opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 16);
+ }
+ return res;
+}
+
+uint64_t helper_maxsw4(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ int16_t opa, opb;
+ uint16_t opr;
+ int i;
+
+ for (i = 0; i < 4; ++i) {
+ opa = op1 >> (i * 16);
+ opb = op2 >> (i * 16);
+ opr = opa > opb ? opa : opb;
+ res |= (uint64_t)opr << (i * 16);
+ }
+ return res;
+}
+
+uint64_t helper_perr(uint64_t op1, uint64_t op2)
+{
+ uint64_t res = 0;
+ uint8_t opa, opb, opr;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ opa = op1 >> (i * 8);
+ opb = op2 >> (i * 8);
+ if (opa >= opb) {
+ opr = opa - opb;
+ } else {
+ opr = opb - opa;
+ }
+ res += opr;
+ }
+ return res;
+}
+
+uint64_t helper_pklb(uint64_t op1)
+{
+ return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
+}
+
+uint64_t helper_pkwb(uint64_t op1)
+{
+ return ((op1 & 0xff)
+ | ((op1 >> 8) & 0xff00)
+ | ((op1 >> 16) & 0xff0000)
+ | ((op1 >> 24) & 0xff000000));
+}
+
+uint64_t helper_unpkbl(uint64_t op1)
+{
+ return (op1 & 0xff) | ((op1 & 0xff00) << 24);
+}
+
+uint64_t helper_unpkbw(uint64_t op1)
+{
+ return ((op1 & 0xff)
+ | ((op1 & 0xff00) << 8)
+ | ((op1 & 0xff0000) << 16)
+ | ((op1 & 0xff000000) << 24));
+}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index c77f009..eab7a82 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -154,239 +154,6 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
return tl;
}
-uint64_t helper_umulh (uint64_t op1, uint64_t op2)
-{
- uint64_t tl, th;
-
- mulu64(&tl, &th, op1, op2);
- return th;
-}
-
-uint64_t helper_ctpop (uint64_t arg)
-{
- return ctpop64(arg);
-}
-
-uint64_t helper_ctlz (uint64_t arg)
-{
- return clz64(arg);
-}
-
-uint64_t helper_cttz (uint64_t arg)
-{
- return ctz64(arg);
-}
-
-static inline uint64_t byte_zap(uint64_t op, uint8_t mskb)
-{
- uint64_t mask;
-
- mask = 0;
- mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL;
- mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL;
- mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL;
- mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL;
- mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL;
- mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL;
- mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL;
- mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL;
-
- return op & ~mask;
-}
-
-uint64_t helper_zap(uint64_t val, uint64_t mask)
-{
- return byte_zap(val, mask);
-}
-
-uint64_t helper_zapnot(uint64_t val, uint64_t mask)
-{
- return byte_zap(val, ~mask);
-}
-
-uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
-{
- uint8_t opa, opb, res;
- int i;
-
- res = 0;
- for (i = 0; i < 8; i++) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- if (opa >= opb)
- res |= 1 << i;
- }
- return res;
-}
-
-uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- uint8_t opa, opb, opr;
- int i;
-
- for (i = 0; i < 8; ++i) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- opr = opa < opb ? opa : opb;
- res |= (uint64_t)opr << (i * 8);
- }
- return res;
-}
-
-uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- int8_t opa, opb;
- uint8_t opr;
- int i;
-
- for (i = 0; i < 8; ++i) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- opr = opa < opb ? opa : opb;
- res |= (uint64_t)opr << (i * 8);
- }
- return res;
-}
-
-uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- uint16_t opa, opb, opr;
- int i;
-
- for (i = 0; i < 4; ++i) {
- opa = op1 >> (i * 16);
- opb = op2 >> (i * 16);
- opr = opa < opb ? opa : opb;
- res |= (uint64_t)opr << (i * 16);
- }
- return res;
-}
-
-uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- int16_t opa, opb;
- uint16_t opr;
- int i;
-
- for (i = 0; i < 4; ++i) {
- opa = op1 >> (i * 16);
- opb = op2 >> (i * 16);
- opr = opa < opb ? opa : opb;
- res |= (uint64_t)opr << (i * 16);
- }
- return res;
-}
-
-uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- uint8_t opa, opb, opr;
- int i;
-
- for (i = 0; i < 8; ++i) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- opr = opa > opb ? opa : opb;
- res |= (uint64_t)opr << (i * 8);
- }
- return res;
-}
-
-uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- int8_t opa, opb;
- uint8_t opr;
- int i;
-
- for (i = 0; i < 8; ++i) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- opr = opa > opb ? opa : opb;
- res |= (uint64_t)opr << (i * 8);
- }
- return res;
-}
-
-uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- uint16_t opa, opb, opr;
- int i;
-
- for (i = 0; i < 4; ++i) {
- opa = op1 >> (i * 16);
- opb = op2 >> (i * 16);
- opr = opa > opb ? opa : opb;
- res |= (uint64_t)opr << (i * 16);
- }
- return res;
-}
-
-uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- int16_t opa, opb;
- uint16_t opr;
- int i;
-
- for (i = 0; i < 4; ++i) {
- opa = op1 >> (i * 16);
- opb = op2 >> (i * 16);
- opr = opa > opb ? opa : opb;
- res |= (uint64_t)opr << (i * 16);
- }
- return res;
-}
-
-uint64_t helper_perr (uint64_t op1, uint64_t op2)
-{
- uint64_t res = 0;
- uint8_t opa, opb, opr;
- int i;
-
- for (i = 0; i < 8; ++i) {
- opa = op1 >> (i * 8);
- opb = op2 >> (i * 8);
- if (opa >= opb)
- opr = opa - opb;
- else
- opr = opb - opa;
- res += opr;
- }
- return res;
-}
-
-uint64_t helper_pklb (uint64_t op1)
-{
- return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
-}
-
-uint64_t helper_pkwb (uint64_t op1)
-{
- return ((op1 & 0xff)
- | ((op1 >> 8) & 0xff00)
- | ((op1 >> 16) & 0xff0000)
- | ((op1 >> 24) & 0xff000000));
-}
-
-uint64_t helper_unpkbl (uint64_t op1)
-{
- return (op1 & 0xff) | ((op1 & 0xff00) << 24);
-}
-
-uint64_t helper_unpkbw (uint64_t op1)
-{
- return ((op1 & 0xff)
- | ((op1 & 0xff00) << 8)
- | ((op1 & 0xff0000) << 16)
- | ((op1 & 0xff000000) << 24));
-}
-
/* Floating point helpers */
void helper_setroundmode (uint32_t val)
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 03/10] target-alpha: Move exception helpers to helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 01/10] alpha-linux-user: Initialize fpu to round-to-normal Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 02/10] target-alpha: Move integer helpers to int_helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 04/10] target-alpha: Move floating-point helpers to fpu_helper.c Richard Henderson
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 3 ++
target-alpha/helper.c | 39 ++++++++++++++++++++++++
target-alpha/helper.h | 2 +-
target-alpha/op_helper.c | 73 ++++++++++++----------------------------------
target-alpha/translate.c | 2 +-
5 files changed, 63 insertions(+), 56 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 48c0fdc..c7787f6 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -434,6 +434,9 @@ int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, uint64_t address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_alpha_handle_mmu_fault
void do_interrupt (CPUAlphaState *env);
+void do_restore_state(CPUAlphaState *, void *retaddr);
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *, void *, int, int);
+void QEMU_NORETURN arith_excp(CPUAlphaState *, void *, int, uint64_t);
uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env);
void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val);
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3f2e7c3..584457f 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "softfloat.h"
+#include "helper.h"
uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
{
@@ -484,3 +485,41 @@ void cpu_dump_state (CPUAlphaState *env, FILE *f, fprintf_function cpu_fprintf,
}
cpu_fprintf(f, "\n");
}
+
+void do_restore_state(CPUAlphaState *env, void *retaddr)
+{
+ uintptr_t pc = (uintptr_t)retaddr;
+ if (pc) {
+ TranslationBlock *tb = tb_find_pc(pc);
+ if (tb) {
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+}
+
+/* This should only be called from translate, via gen_excp.
+ We expect that ENV->PC has already been updated. */
+void QEMU_NORETURN helper_excp(CPUAlphaState *env, int excp, int error)
+{
+ env->exception_index = excp;
+ env->error_code = error;
+ cpu_loop_exit(env);
+}
+
+/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
+void QEMU_NORETURN dynamic_excp(CPUAlphaState *env, void *retaddr,
+ int excp, int error)
+{
+ env->exception_index = excp;
+ env->error_code = error;
+ do_restore_state(env, retaddr);
+ cpu_loop_exit(env);
+}
+
+void QEMU_NORETURN arith_excp(CPUAlphaState *env, void *retaddr,
+ int exc, uint64_t mask)
+{
+ env->trap_arg0 = exc;
+ env->trap_arg1 = mask;
+ dynamic_excp(env, retaddr, EXCP_ARITH, 0);
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index b693cee..91a9e39 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,6 +1,6 @@
#include "def-helper.h"
-DEF_HELPER_2(excp, void, int, int)
+DEF_HELPER_3(excp, void, env, int, int)
DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
DEF_HELPER_2(addqv, i64, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index eab7a82..af5fa82 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -30,43 +30,6 @@
/*****************************************************************************/
/* Exceptions processing helpers */
-/* This should only be called from translate, via gen_excp.
- We expect that ENV->PC has already been updated. */
-void QEMU_NORETURN helper_excp(int excp, int error)
-{
- env->exception_index = excp;
- env->error_code = error;
- cpu_loop_exit(env);
-}
-
-static void do_restore_state(void *retaddr)
-{
- unsigned long pc = (unsigned long)retaddr;
-
- if (pc) {
- TranslationBlock *tb = tb_find_pc(pc);
- if (tb) {
- cpu_restore_state(tb, env, pc);
- }
- }
-}
-
-/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
-static void QEMU_NORETURN dynamic_excp(int excp, int error)
-{
- env->exception_index = excp;
- env->error_code = error;
- do_restore_state(GETPC());
- cpu_loop_exit(env);
-}
-
-static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
-{
- env->trap_arg0 = exc;
- env->trap_arg1 = mask;
- dynamic_excp(EXCP_ARITH, 0);
-}
-
uint64_t helper_load_pcc (void)
{
#ifndef CONFIG_USER_ONLY
@@ -97,7 +60,7 @@ uint64_t helper_addqv (uint64_t op1, uint64_t op2)
uint64_t tmp = op1;
op1 += op2;
if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return op1;
}
@@ -107,7 +70,7 @@ uint64_t helper_addlv (uint64_t op1, uint64_t op2)
uint64_t tmp = op1;
op1 = (uint32_t)(op1 + op2);
if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return op1;
}
@@ -117,7 +80,7 @@ uint64_t helper_subqv (uint64_t op1, uint64_t op2)
uint64_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return res;
}
@@ -127,7 +90,7 @@ uint64_t helper_sublv (uint64_t op1, uint64_t op2)
uint32_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return res;
}
@@ -137,7 +100,7 @@ uint64_t helper_mullv (uint64_t op1, uint64_t op2)
int64_t res = (int64_t)op1 * (int64_t)op2;
if (unlikely((int32_t)res != res)) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return (int64_t)((int32_t)res);
}
@@ -149,7 +112,7 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
muls64(&tl, &th, op1, op2);
/* If th != 0 && th != -1, then we had an overflow */
if (unlikely((th + 1) > 1)) {
- arith_excp(EXC_M_IOV, 0);
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
}
return tl;
}
@@ -200,7 +163,7 @@ void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
hw_exc |= EXC_M_INE;
}
- arith_excp(hw_exc, 1ull << regno);
+ arith_excp(env, GETPC(), hw_exc, 1ull << regno);
}
}
@@ -230,7 +193,7 @@ uint64_t helper_ieee_input(uint64_t val)
if (env->fpcr_dnz) {
val &= 1ull << 63;
} else {
- arith_excp(EXC_M_UNF, 0);
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
}
}
} else if (exp == 0x7ff) {
@@ -238,7 +201,7 @@ uint64_t helper_ieee_input(uint64_t val)
/* ??? I'm not sure these exception bit flags are correct. I do
know that the Linux kernel, at least, doesn't rely on them and
just emulates the insn to figure out what exception to use. */
- arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
+ arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
}
return val;
}
@@ -255,12 +218,12 @@ uint64_t helper_ieee_input_cmp(uint64_t val)
if (env->fpcr_dnz) {
val &= 1ull << 63;
} else {
- arith_excp(EXC_M_UNF, 0);
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
}
}
} else if (exp == 0x7ff && frac) {
/* NaN. */
- arith_excp(EXC_M_INV, 0);
+ arith_excp(env, GETPC(), EXC_M_INV, 0);
}
return val;
}
@@ -323,7 +286,7 @@ static inline float32 f_to_float32(uint64_t a)
if (unlikely(!exp && mant_sig)) {
/* Reserved operands / Dirty zero */
- dynamic_excp(EXCP_OPCDEC, 0);
+ dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
}
if (exp < 3) {
@@ -453,7 +416,7 @@ static inline float64 g_to_float64(uint64_t a)
if (!exp && mant_sig) {
/* Reserved operands / Dirty zero */
- dynamic_excp(EXCP_OPCDEC, 0);
+ dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
}
if (exp < 3) {
@@ -1085,7 +1048,7 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
uint64_t pc;
uint32_t insn;
- do_restore_state(retaddr);
+ do_restore_state(env, retaddr);
pc = env->pc;
insn = ldl_code(pc);
@@ -1093,7 +1056,9 @@ static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
env->trap_arg0 = addr;
env->trap_arg1 = insn >> 26; /* opcode */
env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
- helper_excp(EXCP_UNALIGN, 0);
+ env->exception_index = EXCP_UNALIGN;
+ env->error_code = 0;
+ cpu_loop_exit(env);
}
void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
@@ -1103,7 +1068,7 @@ void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
env = env1;
env->trap_arg0 = addr;
env->trap_arg1 = is_write;
- dynamic_excp(EXCP_MCHK, 0);
+ dynamic_excp(env1, GETPC(), EXCP_MCHK, 0);
}
#include "softmmu_exec.h"
@@ -1137,7 +1102,7 @@ void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
env = env1;
ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret != 0)) {
- do_restore_state(retaddr);
+ do_restore_state(env, retaddr);
/* Exception index and error code are already set */
cpu_loop_exit(env);
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2c24619..0c06b55 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -149,7 +149,7 @@ static void gen_excp_1(int exception, int error_code)
tmp1 = tcg_const_i32(exception);
tmp2 = tcg_const_i32(error_code);
- gen_helper_excp(tmp1, tmp2);
+ gen_helper_excp(cpu_env, tmp1, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp1);
}
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 04/10] target-alpha: Move floating-point helpers to fpu_helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (2 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 03/10] target-alpha: Move exception helpers to helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 05/10] target-alpha: Move fpcr helpers from op_helper.c to helper.c Richard Henderson
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 2 +-
target-alpha/fpu_helper.c | 846 +++++++++++++++++++++++++++++++++++++++++++++
target-alpha/helper.h | 106 +++---
target-alpha/op_helper.c | 812 -------------------------------------------
target-alpha/translate.c | 130 ++++----
5 files changed, 967 insertions(+), 929 deletions(-)
create mode 100644 target-alpha/fpu_helper.c
diff --git a/Makefile.target b/Makefile.target
index ddeb7e0..256e7b5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-y += cpu_init.o
endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
new file mode 100644
index 0000000..d38521b
--- /dev/null
+++ b/target-alpha/fpu_helper.c
@@ -0,0 +1,846 @@
+/*
+ * Helpers for floating point instructions.
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+#include "softfloat.h"
+
+#define FP_STATUS (env->fp_status)
+
+
+void helper_setroundmode(CPUAlphaState *env, uint32_t val)
+{
+ set_float_rounding_mode(val, &FP_STATUS);
+}
+
+void helper_setflushzero(CPUAlphaState *env, uint32_t val)
+{
+ set_flush_to_zero(val, &FP_STATUS);
+}
+
+void helper_fp_exc_clear(CPUAlphaState *env)
+{
+ set_float_exception_flags(0, &FP_STATUS);
+}
+
+uint32_t helper_fp_exc_get(CPUAlphaState *env)
+{
+ return get_float_exception_flags(&FP_STATUS);
+}
+
+static inline void inline_fp_exc_raise(CPUAlphaState *env, void *retaddr,
+ uint32_t exc, uint32_t regno)
+{
+ if (exc) {
+ uint32_t hw_exc = 0;
+
+ if (exc & float_flag_invalid) {
+ hw_exc |= EXC_M_INV;
+ }
+ if (exc & float_flag_divbyzero) {
+ hw_exc |= EXC_M_DZE;
+ }
+ if (exc & float_flag_overflow) {
+ hw_exc |= EXC_M_FOV;
+ }
+ if (exc & float_flag_underflow) {
+ hw_exc |= EXC_M_UNF;
+ }
+ if (exc & float_flag_inexact) {
+ hw_exc |= EXC_M_INE;
+ }
+
+ arith_excp(env, retaddr, hw_exc, 1ull << regno);
+ }
+}
+
+/* Raise exceptions for ieee fp insns without software completion.
+ In that case there are no exceptions that don't trap; the mask
+ doesn't apply. */
+void helper_fp_exc_raise(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+ inline_fp_exc_raise(env, GETPC(), exc, regno);
+}
+
+/* Raise exceptions for ieee fp insns with software completion. */
+void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
+{
+ if (exc) {
+ env->fpcr_exc_status |= exc;
+ exc &= ~env->fpcr_exc_mask;
+ inline_fp_exc_raise(env, GETPC(), exc, regno);
+ }
+}
+
+/* Input remapping without software completion. Handle denormal-map-to-zero
+ and trap for all other non-finite numbers. */
+uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
+{
+ uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+ uint64_t frac = val & 0xfffffffffffffull;
+
+ if (exp == 0) {
+ if (frac != 0) {
+ /* If DNZ is set flush denormals to zero on input. */
+ if (env->fpcr_dnz) {
+ val &= 1ull << 63;
+ } else {
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
+ }
+ }
+ } else if (exp == 0x7ff) {
+ /* Infinity or NaN. */
+ /* ??? I'm not sure these exception bit flags are correct. I do
+ know that the Linux kernel, at least, doesn't rely on them and
+ just emulates the insn to figure out what exception to use. */
+ arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
+ }
+ return val;
+}
+
+/* Similar, but does not trap for infinities. Used for comparisons. */
+uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
+{
+ uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+ uint64_t frac = val & 0xfffffffffffffull;
+
+ if (exp == 0) {
+ if (frac != 0) {
+ /* If DNZ is set flush denormals to zero on input. */
+ if (env->fpcr_dnz) {
+ val &= 1ull << 63;
+ } else {
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
+ }
+ }
+ } else if (exp == 0x7ff && frac) {
+ /* NaN. */
+ arith_excp(env, GETPC(), EXC_M_INV, 0);
+ }
+ return val;
+}
+
+/* Input remapping with software completion enabled. All we have to do
+ is handle denormal-map-to-zero; all other inputs get exceptions as
+ needed from the actual operation. */
+uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
+{
+ if (env->fpcr_dnz) {
+ uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
+ if (exp == 0) {
+ val &= 1ull << 63;
+ }
+ }
+ return val;
+}
+
+/* F floating (VAX) */
+static uint64_t float32_to_f(float32 fa)
+{
+ uint64_t r, exp, mant, sig;
+ CPU_FloatU a;
+
+ a.f = fa;
+ sig = ((uint64_t)a.l & 0x80000000) << 32;
+ exp = (a.l >> 23) & 0xff;
+ mant = ((uint64_t)a.l & 0x007fffff) << 29;
+
+ if (exp == 255) {
+ /* NaN or infinity */
+ r = 1; /* VAX dirty zero */
+ } else if (exp == 0) {
+ if (mant == 0) {
+ /* Zero */
+ r = 0;
+ } else {
+ /* Denormalized */
+ r = sig | ((exp + 1) << 52) | mant;
+ }
+ } else {
+ if (exp >= 253) {
+ /* Overflow */
+ r = 1; /* VAX dirty zero */
+ } else {
+ r = sig | ((exp + 2) << 52);
+ }
+ }
+
+ return r;
+}
+
+static float32 f_to_float32(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+ uint32_t exp, mant_sig;
+ CPU_FloatU r;
+
+ exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
+ mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
+
+ if (unlikely(!exp && mant_sig)) {
+ /* Reserved operands / Dirty zero */
+ dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+ }
+
+ if (exp < 3) {
+ /* Underflow */
+ r.l = 0;
+ } else {
+ r.l = ((exp - 2) << 23) | mant_sig;
+ }
+
+ return r.f;
+}
+
+uint32_t helper_f_to_memory(uint64_t a)
+{
+ uint32_t r;
+ r = (a & 0x00001fffe0000000ull) >> 13;
+ r |= (a & 0x07ffe00000000000ull) >> 45;
+ r |= (a & 0xc000000000000000ull) >> 48;
+ return r;
+}
+
+uint64_t helper_memory_to_f(uint32_t a)
+{
+ uint64_t r;
+ r = ((uint64_t)(a & 0x0000c000)) << 48;
+ r |= ((uint64_t)(a & 0x003fffff)) << 45;
+ r |= ((uint64_t)(a & 0xffff0000)) << 13;
+ if (!(a & 0x00004000)) {
+ r |= 0x7ll << 59;
+ }
+ return r;
+}
+
+/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
+ either implement VAX arithmetic properly or just signal invalid opcode. */
+
+uint64_t helper_addf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = f_to_float32(env, GETPC(), a);
+ fb = f_to_float32(env, GETPC(), b);
+ fr = float32_add(fa, fb, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_subf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = f_to_float32(env, GETPC(), a);
+ fb = f_to_float32(env, GETPC(), b);
+ fr = float32_sub(fa, fb, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_mulf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = f_to_float32(env, GETPC(), a);
+ fb = f_to_float32(env, GETPC(), b);
+ fr = float32_mul(fa, fb, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_divf(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = f_to_float32(env, GETPC(), a);
+ fb = f_to_float32(env, GETPC(), b);
+ fr = float32_div(fa, fb, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_sqrtf(CPUAlphaState *env, uint64_t t)
+{
+ float32 ft, fr;
+
+ ft = f_to_float32(env, GETPC(), t);
+ fr = float32_sqrt(ft, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+
+/* G floating (VAX) */
+static uint64_t float64_to_g(float64 fa)
+{
+ uint64_t r, exp, mant, sig;
+ CPU_DoubleU a;
+
+ a.d = fa;
+ sig = a.ll & 0x8000000000000000ull;
+ exp = (a.ll >> 52) & 0x7ff;
+ mant = a.ll & 0x000fffffffffffffull;
+
+ if (exp == 2047) {
+ /* NaN or infinity */
+ r = 1; /* VAX dirty zero */
+ } else if (exp == 0) {
+ if (mant == 0) {
+ /* Zero */
+ r = 0;
+ } else {
+ /* Denormalized */
+ r = sig | ((exp + 1) << 52) | mant;
+ }
+ } else {
+ if (exp >= 2045) {
+ /* Overflow */
+ r = 1; /* VAX dirty zero */
+ } else {
+ r = sig | ((exp + 2) << 52);
+ }
+ }
+
+ return r;
+}
+
+static float64 g_to_float64(CPUAlphaState *env, void *retaddr, uint64_t a)
+{
+ uint64_t exp, mant_sig;
+ CPU_DoubleU r;
+
+ exp = (a >> 52) & 0x7ff;
+ mant_sig = a & 0x800fffffffffffffull;
+
+ if (!exp && mant_sig) {
+ /* Reserved operands / Dirty zero */
+ dynamic_excp(env, retaddr, EXCP_OPCDEC, 0);
+ }
+
+ if (exp < 3) {
+ /* Underflow */
+ r.ll = 0;
+ } else {
+ r.ll = ((exp - 2) << 52) | mant_sig;
+ }
+
+ return r.d;
+}
+
+uint64_t helper_g_to_memory(uint64_t a)
+{
+ uint64_t r;
+ r = (a & 0x000000000000ffffull) << 48;
+ r |= (a & 0x00000000ffff0000ull) << 16;
+ r |= (a & 0x0000ffff00000000ull) >> 16;
+ r |= (a & 0xffff000000000000ull) >> 48;
+ return r;
+}
+
+uint64_t helper_memory_to_g(uint64_t a)
+{
+ uint64_t r;
+ r = (a & 0x000000000000ffffull) << 48;
+ r |= (a & 0x00000000ffff0000ull) << 16;
+ r |= (a & 0x0000ffff00000000ull) >> 16;
+ r |= (a & 0xffff000000000000ull) >> 48;
+ return r;
+}
+
+uint64_t helper_addg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+ fr = float64_add(fa, fb, &FP_STATUS);
+ return float64_to_g(fr);
+}
+
+uint64_t helper_subg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+ fr = float64_sub(fa, fb, &FP_STATUS);
+ return float64_to_g(fr);
+}
+
+uint64_t helper_mulg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+ fr = float64_mul(fa, fb, &FP_STATUS);
+ return float64_to_g(fr);
+}
+
+uint64_t helper_divg(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+ fr = float64_div(fa, fb, &FP_STATUS);
+ return float64_to_g(fr);
+}
+
+uint64_t helper_sqrtg(CPUAlphaState *env, uint64_t a)
+{
+ float64 fa, fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fr = float64_sqrt(fa, &FP_STATUS);
+ return float64_to_g(fr);
+}
+
+
+/* S floating (single) */
+
+/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
+static inline uint64_t float32_to_s_int(uint32_t fi)
+{
+ uint32_t frac = fi & 0x7fffff;
+ uint32_t sign = fi >> 31;
+ uint32_t exp_msb = (fi >> 30) & 1;
+ uint32_t exp_low = (fi >> 23) & 0x7f;
+ uint32_t exp;
+
+ exp = (exp_msb << 10) | exp_low;
+ if (exp_msb) {
+ if (exp_low == 0x7f) {
+ exp = 0x7ff;
+ }
+ } else {
+ if (exp_low != 0x00) {
+ exp |= 0x380;
+ }
+ }
+
+ return (((uint64_t)sign << 63)
+ | ((uint64_t)exp << 52)
+ | ((uint64_t)frac << 29));
+}
+
+static inline uint64_t float32_to_s(float32 fa)
+{
+ CPU_FloatU a;
+ a.f = fa;
+ return float32_to_s_int(a.l);
+}
+
+static inline uint32_t s_to_float32_int(uint64_t a)
+{
+ return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
+}
+
+static inline float32 s_to_float32(uint64_t a)
+{
+ CPU_FloatU r;
+ r.l = s_to_float32_int(a);
+ return r.f;
+}
+
+uint32_t helper_s_to_memory(uint64_t a)
+{
+ return s_to_float32_int(a);
+}
+
+uint64_t helper_memory_to_s(uint32_t a)
+{
+ return float32_to_s_int(a);
+}
+
+uint64_t helper_adds(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = s_to_float32(a);
+ fb = s_to_float32(b);
+ fr = float32_add(fa, fb, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+uint64_t helper_subs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = s_to_float32(a);
+ fb = s_to_float32(b);
+ fr = float32_sub(fa, fb, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+uint64_t helper_muls(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = s_to_float32(a);
+ fb = s_to_float32(b);
+ fr = float32_mul(fa, fb, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+uint64_t helper_divs(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float32 fa, fb, fr;
+
+ fa = s_to_float32(a);
+ fb = s_to_float32(b);
+ fr = float32_div(fa, fb, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+uint64_t helper_sqrts(CPUAlphaState *env, uint64_t a)
+{
+ float32 fa, fr;
+
+ fa = s_to_float32(a);
+ fr = float32_sqrt(fa, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+
+/* T floating (double) */
+static inline float64 t_to_float64(uint64_t a)
+{
+ /* Memory format is the same as float64 */
+ CPU_DoubleU r;
+ r.ll = a;
+ return r.d;
+}
+
+static inline uint64_t float64_to_t(float64 fa)
+{
+ /* Memory format is the same as float64 */
+ CPU_DoubleU r;
+ r.d = fa;
+ return r.ll;
+}
+
+uint64_t helper_addt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+ fr = float64_add(fa, fb, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_subt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+ fr = float64_sub(fa, fb, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_mult(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+ fr = float64_mul(fa, fb, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_divt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb, fr;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+ fr = float64_div(fa, fb, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_sqrtt(CPUAlphaState *env, uint64_t a)
+{
+ float64 fa, fr;
+
+ fa = t_to_float64(a);
+ fr = float64_sqrt(fa, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+/* Comparisons */
+uint64_t helper_cmptun(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+
+ if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmpteq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+
+ if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmptle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+
+ if (float64_le(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmptlt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = t_to_float64(a);
+ fb = t_to_float64(b);
+
+ if (float64_lt(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmpgeq(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+
+ if (float64_eq_quiet(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmpgle(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+
+ if (float64_le(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+uint64_t helper_cmpglt(CPUAlphaState *env, uint64_t a, uint64_t b)
+{
+ float64 fa, fb;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fb = g_to_float64(env, GETPC(), b);
+
+ if (float64_lt(fa, fb, &FP_STATUS)) {
+ return 0x4000000000000000ULL;
+ } else {
+ return 0;
+ }
+}
+
+/* Floating point format conversion */
+uint64_t helper_cvtts(CPUAlphaState *env, uint64_t a)
+{
+ float64 fa;
+ float32 fr;
+
+ fa = t_to_float64(a);
+ fr = float64_to_float32(fa, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+uint64_t helper_cvtst(CPUAlphaState *env, uint64_t a)
+{
+ float32 fa;
+ float64 fr;
+
+ fa = s_to_float32(a);
+ fr = float32_to_float64(fa, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a)
+{
+ float32 fr = int64_to_float32(a, &FP_STATUS);
+ return float32_to_s(fr);
+}
+
+/* Implement float64 to uint64 conversion without saturation -- we must
+ supply the truncated result. This behaviour is used by the compiler
+ to get unsigned conversion for free with the same instruction.
+
+ The VI flag is set when overflow or inexact exceptions should be raised. */
+
+static inline uint64_t inline_cvttq(CPUAlphaState *env, uint64_t a,
+ int roundmode, int VI)
+{
+ uint64_t frac, ret = 0;
+ uint32_t exp, sign, exc = 0;
+ int shift;
+
+ sign = (a >> 63);
+ exp = (uint32_t)(a >> 52) & 0x7ff;
+ frac = a & 0xfffffffffffffull;
+
+ if (exp == 0) {
+ if (unlikely(frac != 0)) {
+ goto do_underflow;
+ }
+ } else if (exp == 0x7ff) {
+ exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
+ } else {
+ /* Restore implicit bit. */
+ frac |= 0x10000000000000ull;
+
+ shift = exp - 1023 - 52;
+ if (shift >= 0) {
+ /* In this case the number is so large that we must shift
+ the fraction left. There is no rounding to do. */
+ if (shift < 63) {
+ ret = frac << shift;
+ if (VI && (ret >> shift) != frac) {
+ exc = float_flag_overflow;
+ }
+ }
+ } else {
+ uint64_t round;
+
+ /* In this case the number is smaller than the fraction as
+ represented by the 52 bit number. Here we must think
+ about rounding the result. Handle this by shifting the
+ fractional part of the number into the high bits of ROUND.
+ This will let us efficiently handle round-to-nearest. */
+ shift = -shift;
+ if (shift < 63) {
+ ret = frac >> shift;
+ round = frac << (64 - shift);
+ } else {
+ /* The exponent is so small we shift out everything.
+ Leave a sticky bit for proper rounding below. */
+ do_underflow:
+ round = 1;
+ }
+
+ if (round) {
+ exc = (VI ? float_flag_inexact : 0);
+ switch (roundmode) {
+ case float_round_nearest_even:
+ if (round == (1ull << 63)) {
+ /* Fraction is exactly 0.5; round to even. */
+ ret += (ret & 1);
+ } else if (round > (1ull << 63)) {
+ ret += 1;
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_up:
+ ret += 1 - sign;
+ break;
+ case float_round_down:
+ ret += sign;
+ break;
+ }
+ }
+ }
+ if (sign) {
+ ret = -ret;
+ }
+ }
+ if (unlikely(exc)) {
+ float_raise(exc, &FP_STATUS);
+ }
+
+ return ret;
+}
+
+uint64_t helper_cvttq(CPUAlphaState *env, uint64_t a)
+{
+ return inline_cvttq(env, a, FP_STATUS.float_rounding_mode, 1);
+}
+
+uint64_t helper_cvttq_c(CPUAlphaState *env, uint64_t a)
+{
+ return inline_cvttq(env, a, float_round_to_zero, 0);
+}
+
+uint64_t helper_cvttq_svic(CPUAlphaState *env, uint64_t a)
+{
+ return inline_cvttq(env, a, float_round_to_zero, 1);
+}
+
+uint64_t helper_cvtqt(CPUAlphaState *env, uint64_t a)
+{
+ float64 fr = int64_to_float64(a, &FP_STATUS);
+ return float64_to_t(fr);
+}
+
+uint64_t helper_cvtqf(CPUAlphaState *env, uint64_t a)
+{
+ float32 fr = int64_to_float32(a, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgf(CPUAlphaState *env, uint64_t a)
+{
+ float64 fa;
+ float32 fr;
+
+ fa = g_to_float64(env, GETPC(), a);
+ fr = float64_to_float32(fa, &FP_STATUS);
+ return float32_to_f(fr);
+}
+
+uint64_t helper_cvtgq(CPUAlphaState *env, uint64_t a)
+{
+ float64 fa = g_to_float64(env, GETPC(), a);
+ return float64_to_int64_round_to_zero(fa, &FP_STATUS);
+}
+
+uint64_t helper_cvtqg(CPUAlphaState *env, uint64_t a)
+{
+ float64 fr;
+ fr = int64_to_float64(a, &FP_STATUS);
+ return float64_to_g(fr);
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 91a9e39..d36df5f 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -39,65 +39,65 @@ DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(addf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divf, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtf, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divf, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtf, TCG_CALL_CONST, i64, env, i64)
DEF_HELPER_FLAGS_1(g_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_FLAGS_1(memory_to_g, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
-DEF_HELPER_FLAGS_2(addg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mulg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divg, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtg, TCG_CALL_CONST, i64, i64)
+DEF_HELPER_FLAGS_3(addg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mulg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divg, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtg, TCG_CALL_CONST, i64, env, i64)
DEF_HELPER_FLAGS_1(s_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
DEF_HELPER_FLAGS_1(memory_to_s, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
-DEF_HELPER_FLAGS_2(adds, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(muls, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divs, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrts, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_2(addt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(subt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(mult, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_2(divt, TCG_CALL_CONST, i64, i64, i64)
-DEF_HELPER_FLAGS_1(sqrtt, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_2(cmptun, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpteq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmptlt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgeq, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpgle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-DEF_HELPER_FLAGS_2(cmpglt, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
-
-DEF_HELPER_FLAGS_1(cvtts, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtst, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqs, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqt, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgf, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtgq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvtqg, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_1(cvttq, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_c, TCG_CALL_CONST, i64, i64)
-DEF_HELPER_FLAGS_1(cvttq_svic, TCG_CALL_CONST, i64, i64)
-
-DEF_HELPER_FLAGS_1(setroundmode, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_1(setflushzero, TCG_CALL_CONST, void, i32)
-DEF_HELPER_FLAGS_0(fp_exc_clear, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_0(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32)
-DEF_HELPER_2(fp_exc_raise, void, i32, i32)
-DEF_HELPER_2(fp_exc_raise_s, void, i32, i32)
-
-DEF_HELPER_1(ieee_input, i64, i64)
-DEF_HELPER_1(ieee_input_cmp, i64, i64)
-DEF_HELPER_1(ieee_input_s, i64, i64)
+DEF_HELPER_FLAGS_3(adds, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(muls, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divs, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrts, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_3(addt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(subt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(mult, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(divt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_2(sqrtt, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_3(cmptun, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpteq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmptlt, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgeq, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpgle, TCG_CALL_CONST, i64, env, i64, i64)
+DEF_HELPER_FLAGS_3(cmpglt, TCG_CALL_CONST, i64, env, i64, i64)
+
+DEF_HELPER_FLAGS_2(cvtts, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtst, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqs, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqt, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgf, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtgq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvtqg, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(cvttq, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_c, TCG_CALL_CONST, i64, env, i64)
+DEF_HELPER_FLAGS_2(cvttq_svic, TCG_CALL_CONST, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(setroundmode, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_2(setflushzero, TCG_CALL_CONST, void, env, i32)
+DEF_HELPER_FLAGS_1(fp_exc_clear, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
+DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
+DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)
+
+DEF_HELPER_2(ieee_input, i64, env, i64)
+DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
+DEF_HELPER_2(ieee_input_s, i64, env, i64)
#if !defined (CONFIG_USER_ONLY)
DEF_HELPER_1(hw_ret, void, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index af5fa82..6711d99 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -25,8 +25,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
-#define FP_STATUS (env->fp_status)
-
/*****************************************************************************/
/* Exceptions processing helpers */
@@ -117,816 +115,6 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
return tl;
}
-/* Floating point helpers */
-
-void helper_setroundmode (uint32_t val)
-{
- set_float_rounding_mode(val, &FP_STATUS);
-}
-
-void helper_setflushzero (uint32_t val)
-{
- set_flush_to_zero(val, &FP_STATUS);
-}
-
-void helper_fp_exc_clear (void)
-{
- set_float_exception_flags(0, &FP_STATUS);
-}
-
-uint32_t helper_fp_exc_get (void)
-{
- return get_float_exception_flags(&FP_STATUS);
-}
-
-/* Raise exceptions for ieee fp insns without software completion.
- In that case there are no exceptions that don't trap; the mask
- doesn't apply. */
-void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
-{
- if (exc) {
- uint32_t hw_exc = 0;
-
- if (exc & float_flag_invalid) {
- hw_exc |= EXC_M_INV;
- }
- if (exc & float_flag_divbyzero) {
- hw_exc |= EXC_M_DZE;
- }
- if (exc & float_flag_overflow) {
- hw_exc |= EXC_M_FOV;
- }
- if (exc & float_flag_underflow) {
- hw_exc |= EXC_M_UNF;
- }
- if (exc & float_flag_inexact) {
- hw_exc |= EXC_M_INE;
- }
-
- arith_excp(env, GETPC(), hw_exc, 1ull << regno);
- }
-}
-
-/* Raise exceptions for ieee fp insns with software completion. */
-void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
-{
- if (exc) {
- env->fpcr_exc_status |= exc;
-
- exc &= ~env->fpcr_exc_mask;
- if (exc) {
- helper_fp_exc_raise(exc, regno);
- }
- }
-}
-
-/* Input remapping without software completion. Handle denormal-map-to-zero
- and trap for all other non-finite numbers. */
-uint64_t helper_ieee_input(uint64_t val)
-{
- uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
- uint64_t frac = val & 0xfffffffffffffull;
-
- if (exp == 0) {
- if (frac != 0) {
- /* If DNZ is set flush denormals to zero on input. */
- if (env->fpcr_dnz) {
- val &= 1ull << 63;
- } else {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
- }
- }
- } else if (exp == 0x7ff) {
- /* Infinity or NaN. */
- /* ??? I'm not sure these exception bit flags are correct. I do
- know that the Linux kernel, at least, doesn't rely on them and
- just emulates the insn to figure out what exception to use. */
- arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
- }
- return val;
-}
-
-/* Similar, but does not trap for infinities. Used for comparisons. */
-uint64_t helper_ieee_input_cmp(uint64_t val)
-{
- uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
- uint64_t frac = val & 0xfffffffffffffull;
-
- if (exp == 0) {
- if (frac != 0) {
- /* If DNZ is set flush denormals to zero on input. */
- if (env->fpcr_dnz) {
- val &= 1ull << 63;
- } else {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
- }
- }
- } else if (exp == 0x7ff && frac) {
- /* NaN. */
- arith_excp(env, GETPC(), EXC_M_INV, 0);
- }
- return val;
-}
-
-/* Input remapping with software completion enabled. All we have to do
- is handle denormal-map-to-zero; all other inputs get exceptions as
- needed from the actual operation. */
-uint64_t helper_ieee_input_s(uint64_t val)
-{
- if (env->fpcr_dnz) {
- uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
- if (exp == 0) {
- val &= 1ull << 63;
- }
- }
- return val;
-}
-
-/* F floating (VAX) */
-static inline uint64_t float32_to_f(float32 fa)
-{
- uint64_t r, exp, mant, sig;
- CPU_FloatU a;
-
- a.f = fa;
- sig = ((uint64_t)a.l & 0x80000000) << 32;
- exp = (a.l >> 23) & 0xff;
- mant = ((uint64_t)a.l & 0x007fffff) << 29;
-
- if (exp == 255) {
- /* NaN or infinity */
- r = 1; /* VAX dirty zero */
- } else if (exp == 0) {
- if (mant == 0) {
- /* Zero */
- r = 0;
- } else {
- /* Denormalized */
- r = sig | ((exp + 1) << 52) | mant;
- }
- } else {
- if (exp >= 253) {
- /* Overflow */
- r = 1; /* VAX dirty zero */
- } else {
- r = sig | ((exp + 2) << 52);
- }
- }
-
- return r;
-}
-
-static inline float32 f_to_float32(uint64_t a)
-{
- uint32_t exp, mant_sig;
- CPU_FloatU r;
-
- exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
- mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
-
- if (unlikely(!exp && mant_sig)) {
- /* Reserved operands / Dirty zero */
- dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
- }
-
- if (exp < 3) {
- /* Underflow */
- r.l = 0;
- } else {
- r.l = ((exp - 2) << 23) | mant_sig;
- }
-
- return r.f;
-}
-
-uint32_t helper_f_to_memory (uint64_t a)
-{
- uint32_t r;
- r = (a & 0x00001fffe0000000ull) >> 13;
- r |= (a & 0x07ffe00000000000ull) >> 45;
- r |= (a & 0xc000000000000000ull) >> 48;
- return r;
-}
-
-uint64_t helper_memory_to_f (uint32_t a)
-{
- uint64_t r;
- r = ((uint64_t)(a & 0x0000c000)) << 48;
- r |= ((uint64_t)(a & 0x003fffff)) << 45;
- r |= ((uint64_t)(a & 0xffff0000)) << 13;
- if (!(a & 0x00004000))
- r |= 0x7ll << 59;
- return r;
-}
-
-/* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
- either implement VAX arithmetic properly or just signal invalid opcode. */
-
-uint64_t helper_addf (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = f_to_float32(a);
- fb = f_to_float32(b);
- fr = float32_add(fa, fb, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_subf (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = f_to_float32(a);
- fb = f_to_float32(b);
- fr = float32_sub(fa, fb, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_mulf (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = f_to_float32(a);
- fb = f_to_float32(b);
- fr = float32_mul(fa, fb, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_divf (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = f_to_float32(a);
- fb = f_to_float32(b);
- fr = float32_div(fa, fb, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_sqrtf (uint64_t t)
-{
- float32 ft, fr;
-
- ft = f_to_float32(t);
- fr = float32_sqrt(ft, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-
-/* G floating (VAX) */
-static inline uint64_t float64_to_g(float64 fa)
-{
- uint64_t r, exp, mant, sig;
- CPU_DoubleU a;
-
- a.d = fa;
- sig = a.ll & 0x8000000000000000ull;
- exp = (a.ll >> 52) & 0x7ff;
- mant = a.ll & 0x000fffffffffffffull;
-
- if (exp == 2047) {
- /* NaN or infinity */
- r = 1; /* VAX dirty zero */
- } else if (exp == 0) {
- if (mant == 0) {
- /* Zero */
- r = 0;
- } else {
- /* Denormalized */
- r = sig | ((exp + 1) << 52) | mant;
- }
- } else {
- if (exp >= 2045) {
- /* Overflow */
- r = 1; /* VAX dirty zero */
- } else {
- r = sig | ((exp + 2) << 52);
- }
- }
-
- return r;
-}
-
-static inline float64 g_to_float64(uint64_t a)
-{
- uint64_t exp, mant_sig;
- CPU_DoubleU r;
-
- exp = (a >> 52) & 0x7ff;
- mant_sig = a & 0x800fffffffffffffull;
-
- if (!exp && mant_sig) {
- /* Reserved operands / Dirty zero */
- dynamic_excp(env, GETPC(), EXCP_OPCDEC, 0);
- }
-
- if (exp < 3) {
- /* Underflow */
- r.ll = 0;
- } else {
- r.ll = ((exp - 2) << 52) | mant_sig;
- }
-
- return r.d;
-}
-
-uint64_t helper_g_to_memory (uint64_t a)
-{
- uint64_t r;
- r = (a & 0x000000000000ffffull) << 48;
- r |= (a & 0x00000000ffff0000ull) << 16;
- r |= (a & 0x0000ffff00000000ull) >> 16;
- r |= (a & 0xffff000000000000ull) >> 48;
- return r;
-}
-
-uint64_t helper_memory_to_g (uint64_t a)
-{
- uint64_t r;
- r = (a & 0x000000000000ffffull) << 48;
- r |= (a & 0x00000000ffff0000ull) << 16;
- r |= (a & 0x0000ffff00000000ull) >> 16;
- r |= (a & 0xffff000000000000ull) >> 48;
- return r;
-}
-
-uint64_t helper_addg (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
- fr = float64_add(fa, fb, &FP_STATUS);
- return float64_to_g(fr);
-}
-
-uint64_t helper_subg (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
- fr = float64_sub(fa, fb, &FP_STATUS);
- return float64_to_g(fr);
-}
-
-uint64_t helper_mulg (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
- fr = float64_mul(fa, fb, &FP_STATUS);
- return float64_to_g(fr);
-}
-
-uint64_t helper_divg (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
- fr = float64_div(fa, fb, &FP_STATUS);
- return float64_to_g(fr);
-}
-
-uint64_t helper_sqrtg (uint64_t a)
-{
- float64 fa, fr;
-
- fa = g_to_float64(a);
- fr = float64_sqrt(fa, &FP_STATUS);
- return float64_to_g(fr);
-}
-
-
-/* S floating (single) */
-
-/* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
-static inline uint64_t float32_to_s_int(uint32_t fi)
-{
- uint32_t frac = fi & 0x7fffff;
- uint32_t sign = fi >> 31;
- uint32_t exp_msb = (fi >> 30) & 1;
- uint32_t exp_low = (fi >> 23) & 0x7f;
- uint32_t exp;
-
- exp = (exp_msb << 10) | exp_low;
- if (exp_msb) {
- if (exp_low == 0x7f)
- exp = 0x7ff;
- } else {
- if (exp_low != 0x00)
- exp |= 0x380;
- }
-
- return (((uint64_t)sign << 63)
- | ((uint64_t)exp << 52)
- | ((uint64_t)frac << 29));
-}
-
-static inline uint64_t float32_to_s(float32 fa)
-{
- CPU_FloatU a;
- a.f = fa;
- return float32_to_s_int(a.l);
-}
-
-static inline uint32_t s_to_float32_int(uint64_t a)
-{
- return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
-}
-
-static inline float32 s_to_float32(uint64_t a)
-{
- CPU_FloatU r;
- r.l = s_to_float32_int(a);
- return r.f;
-}
-
-uint32_t helper_s_to_memory (uint64_t a)
-{
- return s_to_float32_int(a);
-}
-
-uint64_t helper_memory_to_s (uint32_t a)
-{
- return float32_to_s_int(a);
-}
-
-uint64_t helper_adds (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = s_to_float32(a);
- fb = s_to_float32(b);
- fr = float32_add(fa, fb, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-uint64_t helper_subs (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = s_to_float32(a);
- fb = s_to_float32(b);
- fr = float32_sub(fa, fb, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-uint64_t helper_muls (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = s_to_float32(a);
- fb = s_to_float32(b);
- fr = float32_mul(fa, fb, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-uint64_t helper_divs (uint64_t a, uint64_t b)
-{
- float32 fa, fb, fr;
-
- fa = s_to_float32(a);
- fb = s_to_float32(b);
- fr = float32_div(fa, fb, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-uint64_t helper_sqrts (uint64_t a)
-{
- float32 fa, fr;
-
- fa = s_to_float32(a);
- fr = float32_sqrt(fa, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-
-/* T floating (double) */
-static inline float64 t_to_float64(uint64_t a)
-{
- /* Memory format is the same as float64 */
- CPU_DoubleU r;
- r.ll = a;
- return r.d;
-}
-
-static inline uint64_t float64_to_t(float64 fa)
-{
- /* Memory format is the same as float64 */
- CPU_DoubleU r;
- r.d = fa;
- return r.ll;
-}
-
-uint64_t helper_addt (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
- fr = float64_add(fa, fb, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_subt (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
- fr = float64_sub(fa, fb, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_mult (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
- fr = float64_mul(fa, fb, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_divt (uint64_t a, uint64_t b)
-{
- float64 fa, fb, fr;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
- fr = float64_div(fa, fb, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_sqrtt (uint64_t a)
-{
- float64 fa, fr;
-
- fa = t_to_float64(a);
- fr = float64_sqrt(fa, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-/* Comparisons */
-uint64_t helper_cmptun (uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
-
- if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
- return 0x4000000000000000ULL;
- } else {
- return 0;
- }
-}
-
-uint64_t helper_cmpteq(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
-
- if (float64_eq_quiet(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-uint64_t helper_cmptle(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
-
- if (float64_le(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-uint64_t helper_cmptlt(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = t_to_float64(a);
- fb = t_to_float64(b);
-
- if (float64_lt(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
-
- if (float64_eq_quiet(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-uint64_t helper_cmpgle(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
-
- if (float64_le(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-uint64_t helper_cmpglt(uint64_t a, uint64_t b)
-{
- float64 fa, fb;
-
- fa = g_to_float64(a);
- fb = g_to_float64(b);
-
- if (float64_lt(fa, fb, &FP_STATUS))
- return 0x4000000000000000ULL;
- else
- return 0;
-}
-
-/* Floating point format conversion */
-uint64_t helper_cvtts (uint64_t a)
-{
- float64 fa;
- float32 fr;
-
- fa = t_to_float64(a);
- fr = float64_to_float32(fa, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-uint64_t helper_cvtst (uint64_t a)
-{
- float32 fa;
- float64 fr;
-
- fa = s_to_float32(a);
- fr = float32_to_float64(fa, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqs (uint64_t a)
-{
- float32 fr = int64_to_float32(a, &FP_STATUS);
- return float32_to_s(fr);
-}
-
-/* Implement float64 to uint64 conversion without saturation -- we must
- supply the truncated result. This behaviour is used by the compiler
- to get unsigned conversion for free with the same instruction.
-
- The VI flag is set when overflow or inexact exceptions should be raised. */
-
-static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI)
-{
- uint64_t frac, ret = 0;
- uint32_t exp, sign, exc = 0;
- int shift;
-
- sign = (a >> 63);
- exp = (uint32_t)(a >> 52) & 0x7ff;
- frac = a & 0xfffffffffffffull;
-
- if (exp == 0) {
- if (unlikely(frac != 0)) {
- goto do_underflow;
- }
- } else if (exp == 0x7ff) {
- exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
- } else {
- /* Restore implicit bit. */
- frac |= 0x10000000000000ull;
-
- shift = exp - 1023 - 52;
- if (shift >= 0) {
- /* In this case the number is so large that we must shift
- the fraction left. There is no rounding to do. */
- if (shift < 63) {
- ret = frac << shift;
- if (VI && (ret >> shift) != frac) {
- exc = float_flag_overflow;
- }
- }
- } else {
- uint64_t round;
-
- /* In this case the number is smaller than the fraction as
- represented by the 52 bit number. Here we must think
- about rounding the result. Handle this by shifting the
- fractional part of the number into the high bits of ROUND.
- This will let us efficiently handle round-to-nearest. */
- shift = -shift;
- if (shift < 63) {
- ret = frac >> shift;
- round = frac << (64 - shift);
- } else {
- /* The exponent is so small we shift out everything.
- Leave a sticky bit for proper rounding below. */
- do_underflow:
- round = 1;
- }
-
- if (round) {
- exc = (VI ? float_flag_inexact : 0);
- switch (roundmode) {
- case float_round_nearest_even:
- if (round == (1ull << 63)) {
- /* Fraction is exactly 0.5; round to even. */
- ret += (ret & 1);
- } else if (round > (1ull << 63)) {
- ret += 1;
- }
- break;
- case float_round_to_zero:
- break;
- case float_round_up:
- ret += 1 - sign;
- break;
- case float_round_down:
- ret += sign;
- break;
- }
- }
- }
- if (sign) {
- ret = -ret;
- }
- }
- if (unlikely(exc)) {
- float_raise(exc, &FP_STATUS);
- }
-
- return ret;
-}
-
-uint64_t helper_cvttq(uint64_t a)
-{
- return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1);
-}
-
-uint64_t helper_cvttq_c(uint64_t a)
-{
- return helper_cvttq_internal(a, float_round_to_zero, 0);
-}
-
-uint64_t helper_cvttq_svic(uint64_t a)
-{
- return helper_cvttq_internal(a, float_round_to_zero, 1);
-}
-
-uint64_t helper_cvtqt (uint64_t a)
-{
- float64 fr = int64_to_float64(a, &FP_STATUS);
- return float64_to_t(fr);
-}
-
-uint64_t helper_cvtqf (uint64_t a)
-{
- float32 fr = int64_to_float32(a, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgf (uint64_t a)
-{
- float64 fa;
- float32 fr;
-
- fa = g_to_float64(a);
- fr = float64_to_float32(fa, &FP_STATUS);
- return float32_to_f(fr);
-}
-
-uint64_t helper_cvtgq (uint64_t a)
-{
- float64 fa = g_to_float64(a);
- return float64_to_int64_round_to_zero(fa, &FP_STATUS);
-}
-
-uint64_t helper_cvtqg (uint64_t a)
-{
- float64 fr;
- fr = int64_to_float64(a, &FP_STATUS);
- return float64_to_g(fr);
-}
-
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
void helper_hw_ret (uint64_t a)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0c06b55..a9b97a3 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -611,7 +611,8 @@ static void gen_qual_roundmode(DisasContext *ctx, int fn11)
tcg_gen_movi_i32(tmp, float_round_down);
break;
case QUAL_RM_D:
- tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_dyn_round));
+ tcg_gen_ld8u_i32(tmp, cpu_env,
+ offsetof(CPUAlphaState, fpcr_dyn_round));
break;
}
@@ -641,7 +642,8 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
tmp = tcg_temp_new_i32();
if (fn11) {
/* Underflow is enabled, use the FPCR setting. */
- tcg_gen_ld8u_i32(tmp, cpu_env, offsetof(CPUAlphaState, fpcr_flush_to_zero));
+ tcg_gen_ld8u_i32(tmp, cpu_env,
+ offsetof(CPUAlphaState, fpcr_flush_to_zero));
} else {
/* Underflow is disabled, force flush-to-zero. */
tcg_gen_movi_i32(tmp, 1);
@@ -663,11 +665,11 @@ static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
if (reg == 31) {
tcg_gen_movi_i64(val, 0);
} else if (fn11 & QUAL_S) {
- gen_helper_ieee_input_s(val, cpu_fir[reg]);
+ gen_helper_ieee_input_s(val, cpu_env, cpu_fir[reg]);
} else if (is_cmp) {
- gen_helper_ieee_input_cmp(val, cpu_fir[reg]);
+ gen_helper_ieee_input_cmp(val, cpu_env, cpu_fir[reg]);
} else {
- gen_helper_ieee_input(val, cpu_fir[reg]);
+ gen_helper_ieee_input(val, cpu_env, cpu_fir[reg]);
}
return val;
}
@@ -680,7 +682,7 @@ static void gen_fp_exc_clear(void)
offsetof(CPUAlphaState, fp_status.float_exception_flags));
tcg_temp_free_i32(zero);
#else
- gen_helper_fp_exc_clear();
+ gen_helper_fp_exc_clear(cpu_env);
#endif
}
@@ -698,7 +700,7 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
tcg_gen_ld8u_i32(exc, cpu_env,
offsetof(CPUAlphaState, fp_status.float_exception_flags));
#else
- gen_helper_fp_exc_get(exc);
+ gen_helper_fp_exc_get(exc, cpu_env);
#endif
if (ignore) {
@@ -713,9 +715,9 @@ static void gen_fp_exc_raise_ignore(int rc, int fn11, int ignore)
reg = tcg_const_i32(rc + 32);
if (fn11 & QUAL_S) {
- gen_helper_fp_exc_raise_s(exc, reg);
+ gen_helper_fp_exc_raise_s(cpu_env, exc, reg);
} else {
- gen_helper_fp_exc_raise(exc, reg);
+ gen_helper_fp_exc_raise(cpu_env, exc, reg);
}
tcg_temp_free_i32(reg);
@@ -784,20 +786,20 @@ static void gen_fcvtql_v(DisasContext *ctx, int rb, int rc)
gen_fcvtql(rb, rc);
}
-#define FARITH2(name) \
-static inline void glue(gen_f, name)(int rb, int rc) \
-{ \
- if (unlikely(rc == 31)) { \
- return; \
- } \
- if (rb != 31) { \
- gen_helper_ ## name (cpu_fir[rc], cpu_fir[rb]); \
- } else { \
- TCGv tmp = tcg_const_i64(0); \
- gen_helper_ ## name (cpu_fir[rc], tmp); \
- tcg_temp_free(tmp); \
- } \
-}
+#define FARITH2(name) \
+ static inline void glue(gen_f, name)(int rb, int rc) \
+ { \
+ if (unlikely(rc == 31)) { \
+ return; \
+ } \
+ if (rb != 31) { \
+ gen_helper_ ## name(cpu_fir[rc], cpu_env, cpu_fir[rb]); \
+ } else { \
+ TCGv tmp = tcg_const_i64(0); \
+ gen_helper_ ## name(cpu_fir[rc], cpu_env, tmp); \
+ tcg_temp_free(tmp); \
+ } \
+ }
/* ??? VAX instruction qualifiers ignored. */
FARITH2(sqrtf)
@@ -807,7 +809,8 @@ FARITH2(cvtgq)
FARITH2(cvtqf)
FARITH2(cvtqg)
-static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_arith2(DisasContext *ctx,
+ void (*helper)(TCGv, TCGv_ptr, TCGv),
int rb, int rc, int fn11)
{
TCGv vb;
@@ -823,7 +826,7 @@ static void gen_ieee_arith2(DisasContext *ctx, void (*helper)(TCGv, TCGv),
gen_fp_exc_clear();
vb = gen_ieee_input(rb, fn11, 0);
- helper(cpu_fir[rc], vb);
+ helper(cpu_fir[rc], cpu_env, vb);
tcg_temp_free(vb);
gen_fp_exc_raise(rc, fn11);
@@ -859,18 +862,18 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
also do not have integer overflow enabled. Special case that. */
switch (fn11) {
case QUAL_RM_C:
- gen_helper_cvttq_c(cpu_fir[rc], vb);
+ gen_helper_cvttq_c(cpu_fir[rc], cpu_env, vb);
break;
case QUAL_V | QUAL_RM_C:
case QUAL_S | QUAL_V | QUAL_RM_C:
ignore = float_flag_inexact;
/* FALLTHRU */
case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
- gen_helper_cvttq_svic(cpu_fir[rc], vb);
+ gen_helper_cvttq_svic(cpu_fir[rc], cpu_env, vb);
break;
default:
gen_qual_roundmode(ctx, fn11);
- gen_helper_cvttq(cpu_fir[rc], vb);
+ gen_helper_cvttq(cpu_fir[rc], cpu_env, vb);
ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
break;
@@ -880,7 +883,8 @@ static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
gen_fp_exc_raise_ignore(rc, fn11, ignore);
}
-static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
+static void gen_ieee_intcvt(DisasContext *ctx,
+ void (*helper)(TCGv, TCGv_ptr, TCGv),
int rb, int rc, int fn11)
{
TCGv vb;
@@ -904,10 +908,10 @@ static void gen_ieee_intcvt(DisasContext *ctx, void (*helper)(TCGv, TCGv),
inexact handling is requested. */
if (fn11 & QUAL_I) {
gen_fp_exc_clear();
- helper(cpu_fir[rc], vb);
+ helper(cpu_fir[rc], cpu_env, vb);
gen_fp_exc_raise(rc, fn11);
} else {
- helper(cpu_fir[rc], vb);
+ helper(cpu_fir[rc], cpu_env, vb);
}
if (rb == 31) {
@@ -999,34 +1003,34 @@ static inline void gen_fcpyse(int ra, int rb, int rc)
gen_cpys_internal(ra, rb, rc, 0, 0xFFF0000000000000ULL);
}
-#define FARITH3(name) \
-static inline void glue(gen_f, name)(int ra, int rb, int rc) \
-{ \
- TCGv va, vb; \
- \
- if (unlikely(rc == 31)) { \
- return; \
- } \
- if (ra == 31) { \
- va = tcg_const_i64(0); \
- } else { \
- va = cpu_fir[ra]; \
- } \
- if (rb == 31) { \
- vb = tcg_const_i64(0); \
- } else { \
- vb = cpu_fir[rb]; \
- } \
- \
- gen_helper_ ## name (cpu_fir[rc], va, vb); \
- \
- if (ra == 31) { \
- tcg_temp_free(va); \
- } \
- if (rb == 31) { \
- tcg_temp_free(vb); \
- } \
-}
+#define FARITH3(name) \
+ static inline void glue(gen_f, name)(int ra, int rb, int rc) \
+ { \
+ TCGv va, vb; \
+ \
+ if (unlikely(rc == 31)) { \
+ return; \
+ } \
+ if (ra == 31) { \
+ va = tcg_const_i64(0); \
+ } else { \
+ va = cpu_fir[ra]; \
+ } \
+ if (rb == 31) { \
+ vb = tcg_const_i64(0); \
+ } else { \
+ vb = cpu_fir[rb]; \
+ } \
+ \
+ gen_helper_ ## name(cpu_fir[rc], cpu_env, va, vb); \
+ \
+ if (ra == 31) { \
+ tcg_temp_free(va); \
+ } \
+ if (rb == 31) { \
+ tcg_temp_free(vb); \
+ } \
+ }
/* ??? VAX instruction qualifiers ignored. */
FARITH3(addf)
@@ -1042,7 +1046,7 @@ FARITH3(cmpglt)
FARITH3(cmpgle)
static void gen_ieee_arith3(DisasContext *ctx,
- void (*helper)(TCGv, TCGv, TCGv),
+ void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
int ra, int rb, int rc, int fn11)
{
TCGv va, vb;
@@ -1059,7 +1063,7 @@ static void gen_ieee_arith3(DisasContext *ctx,
va = gen_ieee_input(ra, fn11, 0);
vb = gen_ieee_input(rb, fn11, 0);
- helper(cpu_fir[rc], va, vb);
+ helper(cpu_fir[rc], cpu_env, va, vb);
tcg_temp_free(va);
tcg_temp_free(vb);
@@ -1082,7 +1086,7 @@ IEEE_ARITH3(mult)
IEEE_ARITH3(divt)
static void gen_ieee_compare(DisasContext *ctx,
- void (*helper)(TCGv, TCGv, TCGv),
+ void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
int ra, int rb, int rc, int fn11)
{
TCGv va, vb;
@@ -1097,7 +1101,7 @@ static void gen_ieee_compare(DisasContext *ctx,
va = gen_ieee_input(ra, fn11, 1);
vb = gen_ieee_input(rb, fn11, 1);
- helper(cpu_fir[rc], va, vb);
+ helper(cpu_fir[rc], cpu_env, va, vb);
tcg_temp_free(va);
tcg_temp_free(vb);
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 05/10] target-alpha: Move fpcr helpers from op_helper.c to helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (3 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 04/10] target-alpha: Move floating-point helpers to fpu_helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 06/10] target-alpha: Move integer overflow helpers to int_helper.c Richard Henderson
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.c | 14 ++++++++++++--
target-alpha/helper.h | 4 ++--
target-alpha/op_helper.c | 10 ----------
target-alpha/translate.c | 6 +++---
4 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 584457f..3333bfa 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -159,9 +159,19 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
env->fpcr_undz = (val & FPCR_UNDZ) != 0;
}
+uint64_t helper_load_fpcr(CPUAlphaState *env)
+{
+ return cpu_alpha_load_fpcr(env);
+}
+
+void helper_store_fpcr(CPUAlphaState *env, uint64_t val)
+{
+ cpu_alpha_store_fpcr(env, val);
+}
+
#if defined(CONFIG_USER_ONLY)
-int cpu_alpha_handle_mmu_fault (CPUAlphaState *env, target_ulong address, int rw,
- int mmu_idx)
+int cpu_alpha_handle_mmu_fault(CPUAlphaState *env, target_ulong address,
+ int rw, int mmu_idx)
{
env->exception_index = EXCP_MMFAULT;
env->trap_arg0 = address;
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index d36df5f..e193c26 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -34,8 +34,8 @@ DEF_HELPER_FLAGS_1(pkwb, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_FLAGS_1(unpkbl, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
DEF_HELPER_FLAGS_1(unpkbw, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
-DEF_HELPER_FLAGS_0(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_FLAGS_1(store_fpcr, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(load_fpcr, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
+DEF_HELPER_FLAGS_2(store_fpcr, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_FLAGS_1(f_to_memory, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64)
DEF_HELPER_FLAGS_1(memory_to_f, TCG_CALL_CONST | TCG_CALL_PURE, i64, i32)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 6711d99..59ee31e 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -43,16 +43,6 @@ uint64_t helper_load_pcc (void)
#endif
}
-uint64_t helper_load_fpcr (void)
-{
- return cpu_alpha_load_fpcr (env);
-}
-
-void helper_store_fpcr (uint64_t val)
-{
- cpu_alpha_store_fpcr (env, val);
-}
-
uint64_t helper_addqv (uint64_t op1, uint64_t op2)
{
uint64_t tmp = op1;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index a9b97a3..6f31b6d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2678,17 +2678,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x024:
/* MT_FPCR */
if (likely(ra != 31))
- gen_helper_store_fpcr(cpu_fir[ra]);
+ gen_helper_store_fpcr(cpu_env, cpu_fir[ra]);
else {
TCGv tmp = tcg_const_i64(0);
- gen_helper_store_fpcr(tmp);
+ gen_helper_store_fpcr(cpu_env, tmp);
tcg_temp_free(tmp);
}
break;
case 0x025:
/* MF_FPCR */
if (likely(ra != 31))
- gen_helper_load_fpcr(cpu_fir[ra]);
+ gen_helper_load_fpcr(cpu_fir[ra], cpu_env);
break;
case 0x02A:
/* FCMOVEQ */
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 06/10] target-alpha: Move integer overflow helpers to int_helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (4 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 05/10] target-alpha: Move fpcr helpers from op_helper.c to helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 07/10] target-alpha: Move palcode support helpers to sys_helper.c Richard Henderson
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 12 ++++----
target-alpha/int_helper.c | 63 +++++++++++++++++++++++++++++++++++++++++++++
target-alpha/op_helper.c | 62 --------------------------------------------
target-alpha/translate.c | 45 +++++++++++++++++++++++++++-----
4 files changed, 107 insertions(+), 75 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index e193c26..45e187d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -3,12 +3,12 @@
DEF_HELPER_3(excp, void, env, int, int)
DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
-DEF_HELPER_2(addqv, i64, i64, i64)
-DEF_HELPER_2(addlv, i64, i64, i64)
-DEF_HELPER_2(subqv, i64, i64, i64)
-DEF_HELPER_2(sublv, i64, i64, i64)
-DEF_HELPER_2(mullv, i64, i64, i64)
-DEF_HELPER_2(mulqv, i64, i64, i64)
+DEF_HELPER_3(addqv, i64, env, i64, i64)
+DEF_HELPER_3(addlv, i64, env, i64, i64)
+DEF_HELPER_3(subqv, i64, env, i64, i64)
+DEF_HELPER_3(sublv, i64, env, i64, i64)
+DEF_HELPER_3(mullv, i64, env, i64, i64)
+DEF_HELPER_3(mulqv, i64, env, i64, i64)
DEF_HELPER_FLAGS_2(umulh, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
DEF_HELPER_FLAGS_1(ctpop, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64)
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c
index 79c0cfe..28ac1b9 100644
--- a/target-alpha/int_helper.c
+++ b/target-alpha/int_helper.c
@@ -255,3 +255,66 @@ uint64_t helper_unpkbw(uint64_t op1)
| ((op1 & 0xff0000) << 16)
| ((op1 & 0xff000000) << 24));
}
+
+uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ uint64_t tmp = op1;
+ op1 += op2;
+ if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return op1;
+}
+
+uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ uint64_t tmp = op1;
+ op1 = (uint32_t)(op1 + op2);
+ if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return op1;
+}
+
+uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ uint64_t res;
+ res = op1 - op2;
+ if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return res;
+}
+
+uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ uint32_t res;
+ res = op1 - op2;
+ if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return res;
+}
+
+uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ int64_t res = (int64_t)op1 * (int64_t)op2;
+
+ if (unlikely((int32_t)res != res)) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return (int64_t)((int32_t)res);
+}
+
+uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2)
+{
+ uint64_t tl, th;
+
+ muls64(&tl, &th, op1, op2);
+ /* If th != 0 && th != -1, then we had an overflow */
+ if (unlikely((th + 1) > 1)) {
+ arith_excp(env, GETPC(), EXC_M_IOV, 0);
+ }
+ return tl;
+}
+
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 59ee31e..c51b535 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -43,68 +43,6 @@ uint64_t helper_load_pcc (void)
#endif
}
-uint64_t helper_addqv (uint64_t op1, uint64_t op2)
-{
- uint64_t tmp = op1;
- op1 += op2;
- if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return op1;
-}
-
-uint64_t helper_addlv (uint64_t op1, uint64_t op2)
-{
- uint64_t tmp = op1;
- op1 = (uint32_t)(op1 + op2);
- if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return op1;
-}
-
-uint64_t helper_subqv (uint64_t op1, uint64_t op2)
-{
- uint64_t res;
- res = op1 - op2;
- if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return res;
-}
-
-uint64_t helper_sublv (uint64_t op1, uint64_t op2)
-{
- uint32_t res;
- res = op1 - op2;
- if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return res;
-}
-
-uint64_t helper_mullv (uint64_t op1, uint64_t op2)
-{
- int64_t res = (int64_t)op1 * (int64_t)op2;
-
- if (unlikely((int32_t)res != res)) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return (int64_t)((int32_t)res);
-}
-
-uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
-{
- uint64_t tl, th;
-
- muls64(&tl, &th, op1, op2);
- /* If th != 0 && th != -1, then we had an overflow */
- if (unlikely((th + 1) > 1)) {
- arith_excp(env, GETPC(), EXC_M_IOV, 0);
- }
- return tl;
-}
-
/* PALcode support special instructions */
#if !defined (CONFIG_USER_ONLY)
void helper_hw_ret (uint64_t a)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 6f31b6d..551237c 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1392,14 +1392,8 @@ static inline void glue(gen_, name)(int ra, int rb, int rc, int islit,\
tcg_temp_free(tmp1); \
} \
}
-ARITH3(cmpbge)
-ARITH3(addlv)
-ARITH3(sublv)
-ARITH3(addqv)
-ARITH3(subqv)
ARITH3(umulh)
-ARITH3(mullv)
-ARITH3(mulqv)
+ARITH3(cmpbge)
ARITH3(minub8)
ARITH3(minsb8)
ARITH3(minuw4)
@@ -1410,6 +1404,43 @@ ARITH3(maxuw4)
ARITH3(maxsw4)
ARITH3(perr)
+/* Code to call arith3 helpers */
+#define ARITH3_EX(name) \
+ static inline void glue(gen_, name)(int ra, int rb, int rc, \
+ int islit, uint8_t lit) \
+ { \
+ if (unlikely(rc == 31)) { \
+ return; \
+ } \
+ if (ra != 31) { \
+ if (islit) { \
+ TCGv tmp = tcg_const_i64(lit); \
+ gen_helper_ ## name(cpu_ir[rc], cpu_env, \
+ cpu_ir[ra], tmp); \
+ tcg_temp_free(tmp); \
+ } else { \
+ gen_helper_ ## name(cpu_ir[rc], cpu_env, \
+ cpu_ir[ra], cpu_ir[rb]); \
+ } \
+ } else { \
+ TCGv tmp1 = tcg_const_i64(0); \
+ if (islit) { \
+ TCGv tmp2 = tcg_const_i64(lit); \
+ gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, tmp2); \
+ tcg_temp_free(tmp2); \
+ } else { \
+ gen_helper_ ## name(cpu_ir[rc], cpu_env, tmp1, cpu_ir[rb]); \
+ } \
+ tcg_temp_free(tmp1); \
+ } \
+ }
+ARITH3_EX(addlv)
+ARITH3_EX(sublv)
+ARITH3_EX(addqv)
+ARITH3_EX(subqv)
+ARITH3_EX(mullv)
+ARITH3_EX(mulqv)
+
#define MVIOP2(name) \
static inline void glue(gen_, name)(int rb, int rc) \
{ \
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 07/10] target-alpha: Move palcode support helpers to sys_helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (5 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 06/10] target-alpha: Move integer overflow helpers to int_helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 08/10] target-alpha: Move memory helpers to mem_helper.c Richard Henderson
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 2 +-
target-alpha/helper.h | 10 +++---
target-alpha/op_helper.c | 65 ---------------------------------
target-alpha/sys_helper.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
target-alpha/translate.c | 14 ++++----
5 files changed, 100 insertions(+), 78 deletions(-)
create mode 100644 target-alpha/sys_helper.c
diff --git a/Makefile.target b/Makefile.target
index 256e7b5..254a9fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -96,7 +96,7 @@ libobj-y += cpu_init.o
endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 45e187d..f057ecf 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,7 +1,7 @@
#include "def-helper.h"
DEF_HELPER_3(excp, void, env, int, int)
-DEF_HELPER_FLAGS_0(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64)
+DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
DEF_HELPER_3(addqv, i64, env, i64, i64)
DEF_HELPER_3(addlv, i64, env, i64, i64)
@@ -100,7 +100,7 @@ DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
DEF_HELPER_2(ieee_input_s, i64, env, i64)
#if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_1(hw_ret, void, i64)
+DEF_HELPER_2(hw_ret, void, env, i64)
DEF_HELPER_1(ldl_phys, i64, i64)
DEF_HELPER_1(ldq_phys, i64, i64)
@@ -111,13 +111,13 @@ DEF_HELPER_2(stq_phys, void, i64, i64)
DEF_HELPER_2(stl_c_phys, i64, i64, i64)
DEF_HELPER_2(stq_c_phys, i64, i64, i64)
-DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
-DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env)
+DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64)
DEF_HELPER_1(halt, void, i64);
DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
-DEF_HELPER_FLAGS_1(set_alarm, TCG_CALL_CONST, void, i64)
+DEF_HELPER_FLAGS_2(set_alarm, TCG_CALL_CONST, void, env, i64)
#endif
#include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index c51b535..df1f01c 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -25,71 +25,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
-/*****************************************************************************/
-/* Exceptions processing helpers */
-
-uint64_t helper_load_pcc (void)
-{
-#ifndef CONFIG_USER_ONLY
- /* In system mode we have access to a decent high-resolution clock.
- In order to make OS-level time accounting work with the RPCC,
- present it with a well-timed clock fixed at 250MHz. */
- return (((uint64_t)env->pcc_ofs << 32)
- | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
-#else
- /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
- clock ticks. Also, don't bother taking PCC_OFS into account. */
- return (uint32_t)cpu_get_real_ticks();
-#endif
-}
-
-/* PALcode support special instructions */
-#if !defined (CONFIG_USER_ONLY)
-void helper_hw_ret (uint64_t a)
-{
- env->pc = a & ~3;
- env->intr_flag = 0;
- env->lock_addr = -1;
- if ((a & 1) == 0) {
- env->pal_mode = 0;
- swap_shadow_regs(env);
- }
-}
-
-void helper_tbia(void)
-{
- tlb_flush(env, 1);
-}
-
-void helper_tbis(uint64_t p)
-{
- tlb_flush_page(env, p);
-}
-
-void helper_halt(uint64_t restart)
-{
- if (restart) {
- qemu_system_reset_request();
- } else {
- qemu_system_shutdown_request();
- }
-}
-
-uint64_t helper_get_time(void)
-{
- return qemu_get_clock_ns(rtc_clock);
-}
-
-void helper_set_alarm(uint64_t expire)
-{
- if (expire) {
- env->alarm_expire = expire;
- qemu_mod_timer(env->alarm_timer, expire);
- } else {
- qemu_del_timer(env->alarm_timer);
- }
-}
-#endif
/*****************************************************************************/
/* Softmmu support */
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
new file mode 100644
index 0000000..40ca49c
--- /dev/null
+++ b/target-alpha/sys_helper.c
@@ -0,0 +1,87 @@
+/*
+ * Helpers for system instructions.
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+#include "sysemu.h"
+#include "qemu-timer.h"
+
+
+uint64_t helper_load_pcc(CPUAlphaState *env)
+{
+#ifndef CONFIG_USER_ONLY
+ /* In system mode we have access to a decent high-resolution clock.
+ In order to make OS-level time accounting work with the RPCC,
+ present it with a well-timed clock fixed at 250MHz. */
+ return (((uint64_t)env->pcc_ofs << 32)
+ | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
+#else
+ /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
+ clock ticks. Also, don't bother taking PCC_OFS into account. */
+ return (uint32_t)cpu_get_real_ticks();
+#endif
+}
+
+/* PALcode support special instructions */
+#ifndef CONFIG_USER_ONLY
+void helper_hw_ret(CPUAlphaState *env, uint64_t a)
+{
+ env->pc = a & ~3;
+ env->intr_flag = 0;
+ env->lock_addr = -1;
+ if ((a & 1) == 0) {
+ env->pal_mode = 0;
+ swap_shadow_regs(env);
+ }
+}
+
+void helper_tbia(CPUAlphaState *env)
+{
+ tlb_flush(env, 1);
+}
+
+void helper_tbis(CPUAlphaState *env, uint64_t p)
+{
+ tlb_flush_page(env, p);
+}
+
+void helper_halt(uint64_t restart)
+{
+ if (restart) {
+ qemu_system_reset_request();
+ } else {
+ qemu_system_shutdown_request();
+ }
+}
+
+uint64_t helper_get_time(void)
+{
+ return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
+{
+ if (expire) {
+ env->alarm_expire = expire;
+ qemu_mod_timer(env->alarm_timer, expire);
+ } else {
+ qemu_del_timer(env->alarm_timer);
+ }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 551237c..cc87320 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1678,12 +1678,12 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
switch (regno) {
case 255:
/* TBIA */
- gen_helper_tbia();
+ gen_helper_tbia(cpu_env);
break;
case 254:
/* TBIS */
- gen_helper_tbis(tmp);
+ gen_helper_tbis(cpu_env, tmp);
break;
case 253:
@@ -1699,7 +1699,7 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
case 251:
/* ALARM */
- gen_helper_set_alarm(tmp);
+ gen_helper_set_alarm(cpu_env, tmp);
break;
default:
@@ -2793,11 +2793,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
if (ra != 31) {
if (use_icount) {
gen_io_start();
- gen_helper_load_pcc(cpu_ir[ra]);
+ gen_helper_load_pcc(cpu_ir[ra], cpu_env);
gen_io_end();
ret = EXIT_PC_STALE;
} else {
- gen_helper_load_pcc(cpu_ir[ra]);
+ gen_helper_load_pcc(cpu_ir[ra], cpu_env);
}
}
break;
@@ -3143,10 +3143,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
emulation PALcode, so continue to accept it. */
TCGv tmp = tcg_temp_new();
tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUAlphaState, exc_addr));
- gen_helper_hw_ret(tmp);
+ gen_helper_hw_ret(cpu_env, tmp);
tcg_temp_free(tmp);
} else {
- gen_helper_hw_ret(cpu_ir[rb]);
+ gen_helper_hw_ret(cpu_env, cpu_ir[rb]);
}
ret = EXIT_PC_UPDATED;
break;
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 08/10] target-alpha: Move memory helpers to mem_helper.c.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (6 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 07/10] target-alpha: Move palcode support helpers to sys_helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 09/10] target-alpha: Make use of fp_status.flush_inputs_to_zero Richard Henderson
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
This completes the transition away from AREG0. This patch must
be last because it requires CONFIG_TCG_PASS_AREG0 set too.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 4 +-
configure | 2 +-
target-alpha/helper.h | 8 +-
target-alpha/mem_helper.c | 151 +++++++++++++++++++++++++++++++++++++++++
target-alpha/op_helper.c | 162 ---------------------------------------------
target-alpha/translate.c | 10 ++--
6 files changed, 164 insertions(+), 173 deletions(-)
create mode 100644 target-alpha/mem_helper.c
delete mode 100644 target-alpha/op_helper.c
diff --git a/Makefile.target b/Makefile.target
index 254a9fa..44b2e83 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -81,8 +81,10 @@ libobj-y += tcg/tcg.o tcg/optimize.o
libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
libobj-y += fpu/softfloat.o
ifneq ($(TARGET_BASE_ARCH), sparc)
+ifneq ($(TARGET_BASE_ARCH), alpha)
libobj-y += op_helper.o
endif
+endif
libobj-y += helper.o
ifeq ($(TARGET_BASE_ARCH), i386)
libobj-y += cpuid.o
@@ -96,7 +98,7 @@ libobj-y += cpu_init.o
endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
-libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o
+libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/configure b/configure
index 8b4e3c1..14ef738 100755
--- a/configure
+++ b/configure
@@ -3608,7 +3608,7 @@ case "$target_arch2" in
esac
case "$target_arch2" in
- sparc*)
+ alpha | sparc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index f057ecf..03cc185 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -104,12 +104,12 @@ DEF_HELPER_2(hw_ret, void, env, i64)
DEF_HELPER_1(ldl_phys, i64, i64)
DEF_HELPER_1(ldq_phys, i64, i64)
-DEF_HELPER_1(ldl_l_phys, i64, i64)
-DEF_HELPER_1(ldq_l_phys, i64, i64)
+DEF_HELPER_2(ldl_l_phys, i64, env, i64)
+DEF_HELPER_2(ldq_l_phys, i64, env, i64)
DEF_HELPER_2(stl_phys, void, i64, i64)
DEF_HELPER_2(stq_phys, void, i64, i64)
-DEF_HELPER_2(stl_c_phys, i64, i64, i64)
-DEF_HELPER_2(stq_c_phys, i64, i64, i64)
+DEF_HELPER_3(stl_c_phys, i64, env, i64, i64)
+DEF_HELPER_3(stq_c_phys, i64, env, i64, i64)
DEF_HELPER_FLAGS_1(tbia, TCG_CALL_CONST, void, env)
DEF_HELPER_FLAGS_2(tbis, TCG_CALL_CONST, void, env, i64)
diff --git a/target-alpha/mem_helper.c b/target-alpha/mem_helper.c
new file mode 100644
index 0000000..dd5ca49
--- /dev/null
+++ b/target-alpha/mem_helper.c
@@ -0,0 +1,151 @@
+/*
+ * Helpers for loads and stores
+ *
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
+ * 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 "cpu.h"
+#include "helper.h"
+
+
+/* Softmmu support */
+#ifndef CONFIG_USER_ONLY
+
+uint64_t helper_ldl_phys(uint64_t p)
+{
+ return (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_phys(uint64_t p)
+{
+ return ldq_phys(p);
+}
+
+uint64_t helper_ldl_l_phys(CPUAlphaState *env, uint64_t p)
+{
+ env->lock_addr = p;
+ return env->lock_value = (int32_t)ldl_phys(p);
+}
+
+uint64_t helper_ldq_l_phys(CPUAlphaState *env, uint64_t p)
+{
+ env->lock_addr = p;
+ return env->lock_value = ldq_phys(p);
+}
+
+void helper_stl_phys(uint64_t p, uint64_t v)
+{
+ stl_phys(p, v);
+}
+
+void helper_stq_phys(uint64_t p, uint64_t v)
+{
+ stq_phys(p, v);
+}
+
+uint64_t helper_stl_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+ uint64_t ret = 0;
+
+ if (p == env->lock_addr) {
+ int32_t old = ldl_phys(p);
+ if (old == (int32_t)env->lock_value) {
+ stl_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
+
+ return ret;
+}
+
+uint64_t helper_stq_c_phys(CPUAlphaState *env, uint64_t p, uint64_t v)
+{
+ uint64_t ret = 0;
+
+ if (p == env->lock_addr) {
+ uint64_t old = ldq_phys(p);
+ if (old == env->lock_value) {
+ stq_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
+
+ return ret;
+}
+
+static void do_unaligned_access(CPUAlphaState *env, target_ulong addr,
+ int is_write, int is_user, void *retaddr)
+{
+ uint64_t pc;
+ uint32_t insn;
+
+ do_restore_state(env, retaddr);
+
+ pc = env->pc;
+ insn = cpu_ldl_code(env, pc);
+
+ env->trap_arg0 = addr;
+ env->trap_arg1 = insn >> 26; /* opcode */
+ env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
+ env->exception_index = EXCP_UNALIGN;
+ env->error_code = 0;
+ cpu_loop_exit(env);
+}
+
+void cpu_unassigned_access(CPUAlphaState *env, target_phys_addr_t addr,
+ int is_write, int is_exec, int unused, int size)
+{
+ env->trap_arg0 = addr;
+ env->trap_arg1 = is_write;
+ dynamic_excp(env, NULL, EXCP_MCHK, 0);
+}
+
+#include "softmmu_exec.h"
+
+#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+/* try to fill the TLB and return an exception if error. If retaddr is
+ NULL, it means that the function was called in C code (i.e. not
+ from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUAlphaState *env, target_ulong addr, int is_write,
+ int mmu_idx, void *retaddr)
+{
+ int ret;
+
+ ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ if (unlikely(ret != 0)) {
+ do_restore_state(env, retaddr);
+ /* Exception index and error code are already set */
+ cpu_loop_exit(env);
+ }
+}
+#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
deleted file mode 100644
index df1f01c..0000000
--- a/target-alpha/op_helper.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Alpha emulation cpu micro-operations helpers for qemu.
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * 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 "cpu.h"
-#include "dyngen-exec.h"
-#include "host-utils.h"
-#include "softfloat.h"
-#include "helper.h"
-#include "sysemu.h"
-#include "qemu-timer.h"
-
-
-/*****************************************************************************/
-/* Softmmu support */
-#if !defined (CONFIG_USER_ONLY)
-uint64_t helper_ldl_phys(uint64_t p)
-{
- return (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_phys(uint64_t p)
-{
- return ldq_phys(p);
-}
-
-uint64_t helper_ldl_l_phys(uint64_t p)
-{
- env->lock_addr = p;
- return env->lock_value = (int32_t)ldl_phys(p);
-}
-
-uint64_t helper_ldq_l_phys(uint64_t p)
-{
- env->lock_addr = p;
- return env->lock_value = ldl_phys(p);
-}
-
-void helper_stl_phys(uint64_t p, uint64_t v)
-{
- stl_phys(p, v);
-}
-
-void helper_stq_phys(uint64_t p, uint64_t v)
-{
- stq_phys(p, v);
-}
-
-uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
-{
- uint64_t ret = 0;
-
- if (p == env->lock_addr) {
- int32_t old = ldl_phys(p);
- if (old == (int32_t)env->lock_value) {
- stl_phys(p, v);
- ret = 1;
- }
- }
- env->lock_addr = -1;
-
- return ret;
-}
-
-uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
-{
- uint64_t ret = 0;
-
- if (p == env->lock_addr) {
- uint64_t old = ldq_phys(p);
- if (old == env->lock_value) {
- stq_phys(p, v);
- ret = 1;
- }
- }
- env->lock_addr = -1;
-
- return ret;
-}
-
-static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
- int is_user, void *retaddr)
-{
- uint64_t pc;
- uint32_t insn;
-
- do_restore_state(env, retaddr);
-
- pc = env->pc;
- insn = ldl_code(pc);
-
- env->trap_arg0 = addr;
- env->trap_arg1 = insn >> 26; /* opcode */
- env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
- env->exception_index = EXCP_UNALIGN;
- env->error_code = 0;
- cpu_loop_exit(env);
-}
-
-void QEMU_NORETURN cpu_unassigned_access(CPUAlphaState *env1,
- target_phys_addr_t addr, int is_write,
- int is_exec, int unused, int size)
-{
- env = env1;
- env->trap_arg0 = addr;
- env->trap_arg1 = is_write;
- dynamic_excp(env1, GETPC(), EXCP_MCHK, 0);
-}
-
-#include "softmmu_exec.h"
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUAlphaState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
-{
- CPUAlphaState *saved_env;
- int ret;
-
- saved_env = env;
- env = env1;
- ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx);
- if (unlikely(ret != 0)) {
- do_restore_state(env, retaddr);
- /* Exception index and error code are already set */
- cpu_loop_exit(env);
- }
- env = saved_env;
-}
-#endif
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index cc87320..dd09ad8 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2867,11 +2867,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2:
/* Longword physical access with lock (hw_ldl_l/p) */
- gen_helper_ldl_l_phys(cpu_ir[ra], addr);
+ gen_helper_ldl_l_phys(cpu_ir[ra], cpu_env, addr);
break;
case 0x3:
/* Quadword physical access with lock (hw_ldq_l/p) */
- gen_helper_ldq_l_phys(cpu_ir[ra], addr);
+ gen_helper_ldq_l_phys(cpu_ir[ra], cpu_env, addr);
break;
case 0x4:
/* Longword virtual PTE fetch (hw_ldl/v) */
@@ -3180,11 +3180,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2:
/* Longword physical access with lock */
- gen_helper_stl_c_phys(val, addr, val);
+ gen_helper_stl_c_phys(val, cpu_env, addr, val);
break;
case 0x3:
/* Quadword physical access with lock */
- gen_helper_stq_c_phys(val, addr, val);
+ gen_helper_stq_c_phys(val, cpu_env, addr, val);
break;
case 0x4:
/* Longword virtual access */
@@ -3420,7 +3420,7 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env,
}
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- insn = ldl_code(ctx.pc);
+ insn = cpu_ldl_code(env, ctx.pc);
num_insns++;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 09/10] target-alpha: Make use of fp_status.flush_inputs_to_zero.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (7 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 08/10] target-alpha: Move memory helpers to mem_helper.c Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 10/10] target-alpha: Use noreturn marker in helper.h Richard Henderson
2012-03-24 18:34 ` [Qemu-devel] [PATCH v2 00/10] Alpha updates Blue Swirl
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
This softfp feature post-dates the last major update to the Alpha
fpu translation. We can make use of this to eliminate at least
one helper function that was performing this operation by hand.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 1 -
target-alpha/fpu_helper.c | 44 ++++++++++----------------------------------
target-alpha/helper.c | 8 +++-----
target-alpha/helper.h | 5 ++---
target-alpha/translate.c | 18 +++++++++++-------
5 files changed, 26 insertions(+), 50 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c7787f6..6c5d28b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -234,7 +234,6 @@ struct CPUAlphaState {
uint8_t fpcr_exc_mask;
uint8_t fpcr_dyn_round;
uint8_t fpcr_flush_to_zero;
- uint8_t fpcr_dnz;
uint8_t fpcr_dnod;
uint8_t fpcr_undz;
diff --git a/target-alpha/fpu_helper.c b/target-alpha/fpu_helper.c
index d38521b..dda1103 100644
--- a/target-alpha/fpu_helper.c
+++ b/target-alpha/fpu_helper.c
@@ -88,21 +88,17 @@ void helper_fp_exc_raise_s(CPUAlphaState *env, uint32_t exc, uint32_t regno)
}
}
-/* Input remapping without software completion. Handle denormal-map-to-zero
- and trap for all other non-finite numbers. */
-uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
+/* Input handing without software completion. Trap for all
+ non-finite numbers. */
+void helper_ieee_input(CPUAlphaState *env, uint64_t val)
{
uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
uint64_t frac = val & 0xfffffffffffffull;
if (exp == 0) {
- if (frac != 0) {
- /* If DNZ is set flush denormals to zero on input. */
- if (env->fpcr_dnz) {
- val &= 1ull << 63;
- } else {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
- }
+ /* Denormals without DNZ set raise an exception. */
+ if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
}
} else if (exp == 0x7ff) {
/* Infinity or NaN. */
@@ -111,43 +107,23 @@ uint64_t helper_ieee_input(CPUAlphaState *env, uint64_t val)
just emulates the insn to figure out what exception to use. */
arith_excp(env, GETPC(), frac ? EXC_M_INV : EXC_M_FOV, 0);
}
- return val;
}
/* Similar, but does not trap for infinities. Used for comparisons. */
-uint64_t helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
+void helper_ieee_input_cmp(CPUAlphaState *env, uint64_t val)
{
uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
uint64_t frac = val & 0xfffffffffffffull;
if (exp == 0) {
- if (frac != 0) {
- /* If DNZ is set flush denormals to zero on input. */
- if (env->fpcr_dnz) {
- val &= 1ull << 63;
- } else {
- arith_excp(env, GETPC(), EXC_M_UNF, 0);
- }
+ /* Denormals without DNZ set raise an exception. */
+ if (frac != 0 && !env->fp_status.flush_inputs_to_zero) {
+ arith_excp(env, GETPC(), EXC_M_UNF, 0);
}
} else if (exp == 0x7ff && frac) {
/* NaN. */
arith_excp(env, GETPC(), EXC_M_INV, 0);
}
- return val;
-}
-
-/* Input remapping with software completion enabled. All we have to do
- is handle denormal-map-to-zero; all other inputs get exceptions as
- needed from the actual operation. */
-uint64_t helper_ieee_input_s(CPUAlphaState *env, uint64_t val)
-{
- if (env->fpcr_dnz) {
- uint32_t exp = (uint32_t)(val >> 52) & 0x7ff;
- if (exp == 0) {
- val &= 1ull << 63;
- }
- }
- return val;
}
/* F floating (VAX) */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3333bfa..765e650 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -82,7 +82,7 @@ uint64_t cpu_alpha_load_fpcr (CPUAlphaState *env)
break;
}
- if (env->fpcr_dnz) {
+ if (env->fp_status.flush_inputs_to_zero) {
r |= FPCR_DNZ;
}
if (env->fpcr_dnod) {
@@ -151,12 +151,10 @@ void cpu_alpha_store_fpcr (CPUAlphaState *env, uint64_t val)
}
env->fpcr_dyn_round = t;
- env->fpcr_flush_to_zero
- = (val & (FPCR_UNDZ|FPCR_UNFD)) == (FPCR_UNDZ|FPCR_UNFD);
-
- env->fpcr_dnz = (val & FPCR_DNZ) != 0;
env->fpcr_dnod = (val & FPCR_DNOD) != 0;
env->fpcr_undz = (val & FPCR_UNDZ) != 0;
+ env->fpcr_flush_to_zero = env->fpcr_dnod & env->fpcr_undz;
+ env->fp_status.flush_inputs_to_zero = (val & FPCR_DNZ) != 0;
}
uint64_t helper_load_fpcr(CPUAlphaState *env)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 03cc185..9f97c5d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -95,9 +95,8 @@ DEF_HELPER_FLAGS_1(fp_exc_get, TCG_CALL_CONST | TCG_CALL_PURE, i32, env)
DEF_HELPER_3(fp_exc_raise, void, env, i32, i32)
DEF_HELPER_3(fp_exc_raise_s, void, env, i32, i32)
-DEF_HELPER_2(ieee_input, i64, env, i64)
-DEF_HELPER_2(ieee_input_cmp, i64, env, i64)
-DEF_HELPER_2(ieee_input_s, i64, env, i64)
+DEF_HELPER_2(ieee_input, void, env, i64)
+DEF_HELPER_2(ieee_input_cmp, void, env, i64)
#if !defined (CONFIG_USER_ONLY)
DEF_HELPER_2(hw_ret, void, env, i64)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dd09ad8..1f4565d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -661,15 +661,19 @@ static void gen_qual_flushzero(DisasContext *ctx, int fn11)
static TCGv gen_ieee_input(int reg, int fn11, int is_cmp)
{
- TCGv val = tcg_temp_new();
+ TCGv val;
if (reg == 31) {
- tcg_gen_movi_i64(val, 0);
- } else if (fn11 & QUAL_S) {
- gen_helper_ieee_input_s(val, cpu_env, cpu_fir[reg]);
- } else if (is_cmp) {
- gen_helper_ieee_input_cmp(val, cpu_env, cpu_fir[reg]);
+ val = tcg_const_i64(0);
} else {
- gen_helper_ieee_input(val, cpu_env, cpu_fir[reg]);
+ if ((fn11 & QUAL_S) == 0) {
+ if (is_cmp) {
+ gen_helper_ieee_input_cmp(cpu_env, cpu_fir[reg]);
+ } else {
+ gen_helper_ieee_input(cpu_env, cpu_fir[reg]);
+ }
+ }
+ val = tcg_temp_new();
+ tcg_gen_mov_i64(val, cpu_fir[reg]);
}
return val;
}
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [Qemu-devel] [PATCH 10/10] target-alpha: Use noreturn marker in helper.h.
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (8 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 09/10] target-alpha: Make use of fp_status.flush_inputs_to_zero Richard Henderson
@ 2012-03-24 16:51 ` Richard Henderson
2012-03-24 18:34 ` [Qemu-devel] [PATCH v2 00/10] Alpha updates Blue Swirl
10 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2012-03-24 16:51 UTC (permalink / raw)
To: qemu-devel; +Cc: blauwirbel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 9f97c5d..a184def 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -1,6 +1,6 @@
#include "def-helper.h"
-DEF_HELPER_3(excp, void, env, int, int)
+DEF_HELPER_3(excp, noreturn, env, int, int)
DEF_HELPER_FLAGS_1(load_pcc, TCG_CALL_CONST | TCG_CALL_PURE, i64, env)
DEF_HELPER_3(addqv, i64, env, i64, i64)
--
1.7.7.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] [PATCH v2 00/10] Alpha updates
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
` (9 preceding siblings ...)
2012-03-24 16:51 ` [Qemu-devel] [PATCH 10/10] target-alpha: Use noreturn marker in helper.h Richard Henderson
@ 2012-03-24 18:34 ` Blue Swirl
10 siblings, 0 replies; 12+ messages in thread
From: Blue Swirl @ 2012-03-24 18:34 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
Thanks, applied all.
On Sat, Mar 24, 2012 at 16:51, Richard Henderson <rth@twiddle.net> wrote:
> Changes v1->v2:
> * Formatting fixed during the move to new files. It might have been
> cleaner to fix it before the move, but it was easier to run the
> existing patches through checkpatch.pl.
>
> * Add noreturn marker, now that it's available.
>
>
> r~
>
>
> Richard Henderson (10):
> alpha-linux-user: Initialize fpu to round-to-normal.
> target-alpha: Move integer helpers to int_helper.c.
> target-alpha: Move exception helpers to helper.c.
> target-alpha: Move floating-point helpers to fpu_helper.c.
> target-alpha: Move fpcr helpers from op_helper.c to helper.c.
> target-alpha: Move integer overflow helpers to int_helper.c.
> target-alpha: Move palcode support helpers to sys_helper.c.
> target-alpha: Move memory helpers to mem_helper.c.
> target-alpha: Make use of fp_status.flush_inputs_to_zero.
> target-alpha: Use noreturn marker in helper.h.
>
> Makefile.target | 3 +
> configure | 2 +-
> target-alpha/cpu.h | 4 +-
> target-alpha/fpu_helper.c | 822 +++++++++++++++++++++++++++
> target-alpha/helper.c | 61 ++-
> target-alpha/helper.h | 143 +++---
> target-alpha/int_helper.c | 320 +++++++++++
> target-alpha/mem_helper.c | 151 +++++
> target-alpha/op_helper.c | 1379 ---------------------------------------------
> target-alpha/sys_helper.c | 87 +++
> target-alpha/translate.c | 222 +++++---
> 11 files changed, 1643 insertions(+), 1551 deletions(-)
> create mode 100644 target-alpha/fpu_helper.c
> create mode 100644 target-alpha/int_helper.c
> create mode 100644 target-alpha/mem_helper.c
> delete mode 100644 target-alpha/op_helper.c
> create mode 100644 target-alpha/sys_helper.c
>
> --
> 1.7.7.6
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2012-03-24 18:35 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-24 16:51 [Qemu-devel] [PATCH v2 00/10] Alpha updates Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 01/10] alpha-linux-user: Initialize fpu to round-to-normal Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 02/10] target-alpha: Move integer helpers to int_helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 03/10] target-alpha: Move exception helpers to helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 04/10] target-alpha: Move floating-point helpers to fpu_helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 05/10] target-alpha: Move fpcr helpers from op_helper.c to helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 06/10] target-alpha: Move integer overflow helpers to int_helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 07/10] target-alpha: Move palcode support helpers to sys_helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 08/10] target-alpha: Move memory helpers to mem_helper.c Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 09/10] target-alpha: Make use of fp_status.flush_inputs_to_zero Richard Henderson
2012-03-24 16:51 ` [Qemu-devel] [PATCH 10/10] target-alpha: Use noreturn marker in helper.h Richard Henderson
2012-03-24 18:34 ` [Qemu-devel] [PATCH v2 00/10] Alpha updates Blue Swirl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).