summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.target8
-rw-r--r--compatfd.c12
-rw-r--r--hw/arm_gic.c16
-rw-r--r--hw/m48t59.c4
-rw-r--r--hw/omap2.c5
-rw-r--r--hw/pci_bridge.c2
-rw-r--r--linux-user/main.c19
-rw-r--r--qemu-char.c227
-rw-r--r--target-sparc/cc_helper.c485
-rw-r--r--target-sparc/cpu.h7
-rw-r--r--target-sparc/cpu_init.c848
-rw-r--r--target-sparc/fop_helper.c394
-rw-r--r--target-sparc/helper.c1074
-rw-r--r--target-sparc/helper.h180
-rw-r--r--target-sparc/int32_helper.c125
-rw-r--r--target-sparc/int64_helper.c164
-rw-r--r--target-sparc/op_helper.c2590
-rw-r--r--target-sparc/translate.c314
-rw-r--r--target-sparc/vis_helper.c406
-rw-r--r--target-sparc/win_helper.c518
20 files changed, 3928 insertions, 3470 deletions
diff --git a/Makefile.target b/Makefile.target
index 417f23e00e..1e90df7e70 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -74,8 +74,14 @@ libobj-y += op_helper.o helper.o
ifeq ($(TARGET_BASE_ARCH), i386)
libobj-y += cpuid.o
endif
+libobj-$(TARGET_SPARC64) += vis_helper.o
libobj-$(CONFIG_NEED_MMU) += mmu.o
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
+ifeq ($(TARGET_BASE_ARCH), sparc)
+libobj-y += fop_helper.o cc_helper.o win_helper.o cpu_init.o
+endif
+libobj-$(TARGET_SPARC) += int32_helper.o
+libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-y += disas.o
@@ -91,7 +97,7 @@ tcg/tcg.o: cpu.h
# HELPER_CFLAGS is used for all the code compiled with static register
# variables
-op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
+op_helper.o win_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
# Note: this is a workaround. The real fix is to avoid compiling
# cpu_signal_handler() in user-exec.c.
diff --git a/compatfd.c b/compatfd.c
index 31654c62a6..02306a4f71 100644
--- a/compatfd.c
+++ b/compatfd.c
@@ -119,9 +119,17 @@ int qemu_signalfd(const sigset_t *mask)
bool qemu_signalfd_available(void)
{
#ifdef CONFIG_SIGNALFD
+ sigset_t mask;
+ int fd;
+ bool ok;
+ sigemptyset(&mask);
errno = 0;
- syscall(SYS_signalfd, -1, NULL, _NSIG / 8);
- return errno != ENOSYS;
+ fd = syscall(SYS_signalfd, -1, &mask, _NSIG / 8);
+ ok = (errno != ENOSYS);
+ if (fd >= 0) {
+ close(fd);
+ }
+ return ok;
#else
return false;
#endif
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 83213dd406..8dd8742f70 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -658,9 +658,6 @@ static void gic_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->enabled);
for (i = 0; i < NUM_CPU(s); i++) {
qemu_put_be32(f, s->cpu_enabled[i]);
-#ifndef NVIC
- qemu_put_be32(f, s->irq_target[i]);
-#endif
for (j = 0; j < 32; j++)
qemu_put_be32(f, s->priority1[j][i]);
for (j = 0; j < GIC_NIRQ; j++)
@@ -674,6 +671,9 @@ static void gic_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->priority2[i]);
}
for (i = 0; i < GIC_NIRQ; i++) {
+#ifndef NVIC
+ qemu_put_be32(f, s->irq_target[i]);
+#endif
qemu_put_byte(f, s->irq_state[i].enabled);
qemu_put_byte(f, s->irq_state[i].pending);
qemu_put_byte(f, s->irq_state[i].active);
@@ -689,15 +689,12 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
int i;
int j;
- if (version_id != 1)
+ if (version_id != 2)
return -EINVAL;
s->enabled = qemu_get_be32(f);
for (i = 0; i < NUM_CPU(s); i++) {
s->cpu_enabled[i] = qemu_get_be32(f);
-#ifndef NVIC
- s->irq_target[i] = qemu_get_be32(f);
-#endif
for (j = 0; j < 32; j++)
s->priority1[j][i] = qemu_get_be32(f);
for (j = 0; j < GIC_NIRQ; j++)
@@ -711,6 +708,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
s->priority2[i] = qemu_get_be32(f);
}
for (i = 0; i < GIC_NIRQ; i++) {
+#ifndef NVIC
+ s->irq_target[i] = qemu_get_be32(f);
+#endif
s->irq_state[i].enabled = qemu_get_byte(f);
s->irq_state[i].pending = qemu_get_byte(f);
s->irq_state[i].active = qemu_get_byte(f);
@@ -739,5 +739,5 @@ static void gic_init(gic_state *s)
}
memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
gic_reset(s);
- register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
+ register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
}
diff --git a/hw/m48t59.c b/hw/m48t59.c
index f318e67919..a77937ef68 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -480,7 +480,6 @@ static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
M48t59State *NVRAM = opaque;
- addr -= NVRAM->io_base;
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
switch (addr) {
case 0:
@@ -492,7 +491,7 @@ static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
NVRAM->addr |= val << 8;
break;
case 3:
- m48t59_write(NVRAM, val, NVRAM->addr);
+ m48t59_write(NVRAM, NVRAM->addr, val);
NVRAM->addr = 0x0000;
break;
default:
@@ -505,7 +504,6 @@ static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
M48t59State *NVRAM = opaque;
uint32_t retval;
- addr -= NVRAM->io_base;
switch (addr) {
case 3:
retval = m48t59_read(NVRAM, NVRAM->addr);
diff --git a/hw/omap2.c b/hw/omap2.c
index 838c32f371..5197fef2d8 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -2409,6 +2409,11 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
sysbus_connect_irq(busdev, 9,
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
+ if (s->mpu_model == omap2430) {
+ sysbus_connect_irq(busdev, 12,
+ qdev_get_gpio_in(s->ih[0],
+ OMAP_INT_243X_GPIO_BANK5));
+ }
ta = omap_l4ta(s->l4, 3);
sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
diff --git a/hw/pci_bridge.c b/hw/pci_bridge.c
index b6287cdc6d..650d1650c5 100644
--- a/hw/pci_bridge.c
+++ b/hw/pci_bridge.c
@@ -319,7 +319,7 @@ int pci_bridge_initfn(PCIDevice *dev)
sec_bus->parent_dev = dev;
sec_bus->map_irq = br->map_irq;
sec_bus->address_space_mem = &br->address_space_mem;
- memory_region_init(&br->address_space_mem, "pci_pridge_pci", INT64_MAX);
+ memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
sec_bus->address_space_io = &br->address_space_io;
memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
pci_bridge_region_init(br);
diff --git a/linux-user/main.c b/linux-user/main.c
index 186358bd63..e7dad547b8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3084,6 +3084,7 @@ static void handle_arg_version(const char *arg)
{
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
", Copyright (c) 2003-2008 Fabrice Bellard\n");
+ exit(0);
}
struct qemu_argument {
@@ -3129,7 +3130,7 @@ struct qemu_argument arg_table[] = {
{"strace", "QEMU_STRACE", false, handle_arg_strace,
"", "log system calls"},
{"version", "QEMU_VERSION", false, handle_arg_version,
- "", "log system calls"},
+ "", "display version information and exit"},
{NULL, NULL, false, NULL, NULL, NULL}
};
@@ -3231,16 +3232,15 @@ static int parse_args(int argc, char **argv)
for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
if (!strcmp(r, arginfo->argv)) {
- if (optind >= argc) {
- usage();
- }
-
- arginfo->handle_opt(argv[optind]);
-
if (arginfo->has_arg) {
+ if (optind >= argc) {
+ usage();
+ }
+ arginfo->handle_opt(argv[optind]);
optind++;
+ } else {
+ arginfo->handle_opt(NULL);
}
-
break;
}
}
@@ -3276,9 +3276,6 @@ int main(int argc, char **argv, char **envp)
int i;
int ret;
- if (argc <= 1)
- usage();
-
qemu_cache_utils_init(envp);
if ((envlist = envlist_create()) == NULL) {
diff --git a/qemu-char.c b/qemu-char.c
index fb9e058961..9fd94d1bb4 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -538,6 +538,9 @@ int send_all(int fd, const void *_buf, int len1)
}
#endif /* !_WIN32 */
+#define STDIO_MAX_CLIENTS 1
+static int stdio_nb_clients;
+
#ifndef _WIN32
typedef struct {
@@ -545,8 +548,6 @@ typedef struct {
int max_size;
} FDCharDriver;
-#define STDIO_MAX_CLIENTS 1
-static int stdio_nb_clients = 0;
static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
@@ -1451,6 +1452,8 @@ static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
#else /* _WIN32 */
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
typedef struct {
int max_size;
HANDLE hcom, hrecv, hsend;
@@ -1459,6 +1462,14 @@ typedef struct {
DWORD len;
} WinCharState;
+typedef struct {
+ HANDLE hStdIn;
+ HANDLE hInputReadyEvent;
+ HANDLE hInputDoneEvent;
+ HANDLE hInputThread;
+ uint8_t win_stdio_buf;
+} WinStdioCharState;
+
#define NSENDBUF 2048
#define NRECVBUF 2048
#define MAXCONNECT 1
@@ -1809,6 +1820,217 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, CharDriverState **_chr)
return qemu_chr_open_win_file(fd_out, _chr);
}
+
+static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD dwSize;
+ int len1;
+
+ len1 = len;
+
+ while (len1 > 0) {
+ if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL)) {
+ break;
+ }
+ buf += dwSize;
+ len1 -= dwSize;
+ }
+
+ return len - len1;
+}
+
+static void win_stdio_wait_func(void *opaque)
+{
+ CharDriverState *chr = opaque;
+ WinStdioCharState *stdio = chr->opaque;
+ INPUT_RECORD buf[4];
+ int ret;
+ DWORD dwSize;
+ int i;
+
+ ret = ReadConsoleInput(stdio->hStdIn, buf, sizeof(buf) / sizeof(*buf),
+ &dwSize);
+
+ if (!ret) {
+ /* Avoid error storm */
+ qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
+ return;
+ }
+
+ for (i = 0; i < dwSize; i++) {
+ KEY_EVENT_RECORD *kev = &buf[i].Event.KeyEvent;
+
+ if (buf[i].EventType == KEY_EVENT && kev->bKeyDown) {
+ int j;
+ if (kev->uChar.AsciiChar != 0) {
+ for (j = 0; j < kev->wRepeatCount; j++) {
+ if (qemu_chr_be_can_write(chr)) {
+ uint8_t c = kev->uChar.AsciiChar;
+ qemu_chr_be_write(chr, &c, 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+static DWORD WINAPI win_stdio_thread(LPVOID param)
+{
+ CharDriverState *chr = param;
+ WinStdioCharState *stdio = chr->opaque;
+ int ret;
+ DWORD dwSize;
+
+ while (1) {
+
+ /* Wait for one byte */
+ ret = ReadFile(stdio->hStdIn, &stdio->win_stdio_buf, 1, &dwSize, NULL);
+
+ /* Exit in case of error, continue if nothing read */
+ if (!ret) {
+ break;
+ }
+ if (!dwSize) {
+ continue;
+ }
+
+ /* Some terminal emulator returns \r\n for Enter, just pass \n */
+ if (stdio->win_stdio_buf == '\r') {
+ continue;
+ }
+
+ /* Signal the main thread and wait until the byte was eaten */
+ if (!SetEvent(stdio->hInputReadyEvent)) {
+ break;
+ }
+ if (WaitForSingleObject(stdio->hInputDoneEvent, INFINITE)
+ != WAIT_OBJECT_0) {
+ break;
+ }
+ }
+
+ qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
+ return 0;
+}
+
+static void win_stdio_thread_wait_func(void *opaque)
+{
+ CharDriverState *chr = opaque;
+ WinStdioCharState *stdio = chr->opaque;
+
+ if (qemu_chr_be_can_write(chr)) {
+ qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1);
+ }
+
+ SetEvent(stdio->hInputDoneEvent);
+}
+
+static void qemu_chr_set_echo_win_stdio(CharDriverState *chr, bool echo)
+{
+ WinStdioCharState *stdio = chr->opaque;
+ DWORD dwMode = 0;
+
+ GetConsoleMode(stdio->hStdIn, &dwMode);
+
+ if (echo) {
+ SetConsoleMode(stdio->hStdIn, dwMode | ENABLE_ECHO_INPUT);
+ } else {
+ SetConsoleMode(stdio->hStdIn, dwMode & ~ENABLE_ECHO_INPUT);
+ }
+}
+
+static void win_stdio_close(CharDriverState *chr)
+{
+ WinStdioCharState *stdio = chr->opaque;
+
+ if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
+ CloseHandle(stdio->hInputReadyEvent);
+ }
+ if (stdio->hInputDoneEvent != INVALID_HANDLE_VALUE) {
+ CloseHandle(stdio->hInputDoneEvent);
+ }
+ if (stdio->hInputThread != INVALID_HANDLE_VALUE) {
+ TerminateThread(stdio->hInputThread, 0);
+ }
+
+ g_free(chr->opaque);
+ g_free(chr);
+ stdio_nb_clients--;
+}
+
+static int qemu_chr_open_win_stdio(QemuOpts *opts, CharDriverState **_chr)
+{
+ CharDriverState *chr;
+ WinStdioCharState *stdio;
+ DWORD dwMode;
+ int is_console = 0;
+
+ if (stdio_nb_clients >= STDIO_MAX_CLIENTS
+ || ((display_type != DT_NOGRAPHIC) && (stdio_nb_clients != 0))) {
+ return -EIO;
+ }
+
+ chr = g_malloc0(sizeof(CharDriverState));
+ stdio = g_malloc0(sizeof(WinStdioCharState));
+
+ stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+ if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "cannot open stdio: invalid handle\n");
+ exit(1);
+ }
+
+ is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
+
+ chr->opaque = stdio;
+ chr->chr_write = win_stdio_write;
+ chr->chr_close = win_stdio_close;
+
+ if (stdio_nb_clients == 0) {
+ if (is_console) {
+ if (qemu_add_wait_object(stdio->hStdIn,
+ win_stdio_wait_func, chr)) {
+ fprintf(stderr, "qemu_add_wait_object: failed\n");
+ }
+ } else {
+ DWORD dwId;
+
+ stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
+ chr, 0, &dwId);
+
+ if (stdio->hInputThread == INVALID_HANDLE_VALUE
+ || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
+ || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "cannot create stdio thread or event\n");
+ exit(1);
+ }
+ if (qemu_add_wait_object(stdio->hInputReadyEvent,
+ win_stdio_thread_wait_func, chr)) {
+ fprintf(stderr, "qemu_add_wait_object: failed\n");
+ }
+ }
+ }
+
+ dwMode |= ENABLE_LINE_INPUT;
+
+ stdio_clients[stdio_nb_clients++] = chr;
+ if (stdio_nb_clients == 1 && is_console) {
+ /* set the terminal in raw mode */
+ /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
+ dwMode |= ENABLE_PROCESSED_INPUT;
+ }
+
+ SetConsoleMode(stdio->hStdIn, dwMode);
+
+ chr->chr_set_echo = qemu_chr_set_echo_win_stdio;
+ qemu_chr_fe_set_echo(chr, false);
+
+ *_chr = chr;
+
+ return 0;
+}
#endif /* !_WIN32 */
/***********************************************************/
@@ -2519,6 +2741,7 @@ static const struct {
{ .name = "pipe", .open = qemu_chr_open_win_pipe },
{ .name = "console", .open = qemu_chr_open_win_con },
{ .name = "serial", .open = qemu_chr_open_win },
+ { .name = "stdio", .open = qemu_chr_open_win_stdio },
#else
{ .name = "file", .open = qemu_chr_open_file_out },
{ .name = "pipe", .open = qemu_chr_open_pipe },
diff --git a/target-sparc/cc_helper.c b/target-sparc/cc_helper.c
new file mode 100644
index 0000000000..04bd2cf9c7
--- /dev/null
+++ b/target-sparc/cc_helper.c
@@ -0,0 +1,485 @@
+/*
+ * Helpers for lazy condition code handling
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+static uint32_t compute_all_flags(CPUState *env)
+{
+ return env->psr & PSR_ICC;
+}
+
+static uint32_t compute_C_flags(CPUState *env)
+{
+ return env->psr & PSR_CARRY;
+}
+
+static inline uint32_t get_NZ_icc(int32_t dst)
+{
+ uint32_t ret = 0;
+
+ if (dst == 0) {
+ ret = PSR_ZERO;
+ } else if (dst < 0) {
+ ret = PSR_NEG;
+ }
+ return ret;
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_flags_xcc(CPUState *env)
+{
+ return env->xcc & PSR_ICC;
+}
+
+static uint32_t compute_C_flags_xcc(CPUState *env)
+{
+ return env->xcc & PSR_CARRY;
+}
+
+static inline uint32_t get_NZ_xcc(target_long dst)
+{
+ uint32_t ret = 0;
+
+ if (!dst) {
+ ret = PSR_ZERO;
+ } else if (dst < 0) {
+ ret = PSR_NEG;
+ }
+ return ret;
+}
+#endif
+
+static inline uint32_t get_V_div_icc(target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (src2 != 0) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+static uint32_t compute_all_div(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_V_div_icc(CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_div(CPUState *env)
+{
+ return 0;
+}
+
+static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
+{
+ uint32_t ret = 0;
+
+ if (dst < src1) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+#ifdef TARGET_SPARC64
+static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
+{
+ uint32_t ret = 0;
+
+ if (dst < src1) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+static uint32_t compute_all_add_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_xcc(CC_DST);
+ ret |= get_C_add_xcc(CC_DST, CC_SRC);
+ ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_add_xcc(CPUState *env)
+{
+ return get_C_add_xcc(CC_DST, CC_SRC);
+}
+#endif
+
+static uint32_t compute_all_add(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
+ ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_add(CPUState *env)
+{
+ return get_C_add_icc(CC_DST, CC_SRC);
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_addx_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_xcc(CC_DST);
+ ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_addx_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+#endif
+
+static uint32_t compute_all_addx(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_addx(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if ((src1 | src2) & 0x3) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+static uint32_t compute_all_tadd(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
+ ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_all_taddtv(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
+ return ret;
+}
+
+static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (src1 < src2) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+
+#ifdef TARGET_SPARC64
+static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (src1 < src2) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
+ ret = PSR_OVF;
+ }
+ return ret;
+}
+
+static uint32_t compute_all_sub_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_xcc(CC_DST);
+ ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
+ ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_sub_xcc(CPUState *env)
+{
+ return get_C_sub_xcc(CC_SRC, CC_SRC2);
+}
+#endif
+
+static uint32_t compute_all_sub(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+ ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_sub(CPUState *env)
+{
+ return get_C_sub_icc(CC_SRC, CC_SRC2);
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_subx_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_xcc(CC_DST);
+ ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_subx_xcc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+#endif
+
+static uint32_t compute_all_subx(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_subx(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_all_tsub(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+ ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_all_tsubtv(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_all_logic(CPUState *env)
+{
+ return get_NZ_icc(CC_DST);
+}
+
+static uint32_t compute_C_logic(CPUState *env)
+{
+ return 0;
+}
+
+#ifdef TARGET_SPARC64
+static uint32_t compute_all_logic_xcc(CPUState *env)
+{
+ return get_NZ_xcc(CC_DST);
+}
+#endif
+
+typedef struct CCTable {
+ uint32_t (*compute_all)(CPUState *env); /* return all the flags */
+ uint32_t (*compute_c)(CPUState *env); /* return the C flag */
+} CCTable;
+
+static const CCTable icc_table[CC_OP_NB] = {
+ /* CC_OP_DYNAMIC should never happen */
+ [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
+ [CC_OP_DIV] = { compute_all_div, compute_C_div },
+ [CC_OP_ADD] = { compute_all_add, compute_C_add },
+ [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
+ [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
+ [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
+ [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
+ [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
+ [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
+ [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
+ [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
+};
+
+#ifdef TARGET_SPARC64
+static const CCTable xcc_table[CC_OP_NB] = {
+ /* CC_OP_DYNAMIC should never happen */
+ [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
+ [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
+ [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
+ [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
+ [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
+ [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
+ [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
+ [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
+ [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
+ [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
+ [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
+};
+#endif
+
+void helper_compute_psr(CPUState *env)
+{
+ uint32_t new_psr;
+
+ new_psr = icc_table[CC_OP].compute_all(env);
+ env->psr = new_psr;
+#ifdef TARGET_SPARC64
+ new_psr = xcc_table[CC_OP].compute_all(env);
+ env->xcc = new_psr;
+#endif
+ CC_OP = CC_OP_FLAGS;
+}
+
+uint32_t helper_compute_C_icc(CPUState *env)
+{
+ uint32_t ret;
+
+ ret = icc_table[CC_OP].compute_c(env) >> PSR_CARRY_SHIFT;
+ return ret;
+}
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 19de5ba334..6bf9275a74 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -485,10 +485,11 @@ typedef struct CPUSPARCState {
} CPUSPARCState;
#ifndef NO_CPU_IO_DEFS
-/* helper.c */
+/* cpu_init.c */
CPUSPARCState *cpu_sparc_init(const char *cpu_model);
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+/* helper.c */
int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
int mmu_idx);
#define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
@@ -508,7 +509,7 @@ void gen_intermediate_code_init(CPUSPARCState *env);
/* cpu-exec.c */
int cpu_sparc_exec(CPUSPARCState *s);
-/* op_helper.c */
+/* win_helper.c */
target_ulong cpu_get_psr(CPUState *env1);
void cpu_put_psr(CPUState *env1, target_ulong val);
#ifdef TARGET_SPARC64
@@ -521,6 +522,8 @@ void cpu_change_pstate(CPUState *env1, uint32_t new_pstate);
int cpu_cwp_inc(CPUState *env1, int cwp);
int cpu_cwp_dec(CPUState *env1, int cwp);
void cpu_set_cwp(CPUState *env1, int new_cwp);
+
+/* op_helper.c */
void leon3_irq_manager(void *irq_manager, int intno);
/* sun4m.c, sun4u.c */
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu_init.c
new file mode 100644
index 0000000000..08b72a9771
--- /dev/null
+++ b/target-sparc/cpu_init.c
@@ -0,0 +1,848 @@
+/*
+ * Sparc CPU init helpers
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_FEATURES
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
+
+void cpu_reset(CPUSPARCState *env)
+{
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ tlb_flush(env, 1);
+ env->cwp = 0;
+#ifndef TARGET_SPARC64
+ env->wim = 1;
+#endif
+ env->regwptr = env->regbase + (env->cwp * 16);
+ CC_OP = CC_OP_FLAGS;
+#if defined(CONFIG_USER_ONLY)
+#ifdef TARGET_SPARC64
+ env->cleanwin = env->nwindows - 2;
+ env->cansave = env->nwindows - 2;
+ env->pstate = PS_RMO | PS_PEF | PS_IE;
+ env->asi = 0x82; /* Primary no-fault */
+#endif
+#else
+#if !defined(TARGET_SPARC64)
+ env->psret = 0;
+ env->psrs = 1;
+ env->psrps = 1;
+#endif
+#ifdef TARGET_SPARC64
+ env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
+ env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
+ env->tl = env->maxtl;
+ cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
+ env->lsu = 0;
+#else
+ env->mmuregs[0] &= ~(MMU_E | MMU_NF);
+ env->mmuregs[0] |= env->def->mmu_bm;
+#endif
+ env->pc = 0;
+ env->npc = env->pc + 4;
+#endif
+ env->cache_control = 0;
+}
+
+static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
+{
+ sparc_def_t def1, *def = &def1;
+
+ if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
+ return -1;
+ }
+
+ env->def = g_malloc0(sizeof(*def));
+ memcpy(env->def, def, sizeof(*def));
+#if defined(CONFIG_USER_ONLY)
+ if ((env->def->features & CPU_FEATURE_FLOAT)) {
+ env->def->features |= CPU_FEATURE_FLOAT128;
+ }
+#endif
+ env->cpu_model_str = cpu_model;
+ env->version = def->iu_version;
+ env->fsr = def->fpu_version;
+ env->nwindows = def->nwindows;
+#if !defined(TARGET_SPARC64)
+ env->mmuregs[0] |= def->mmu_version;
+ cpu_sparc_set_id(env, 0);
+ env->mxccregs[7] |= def->mxcc_version;
+#else
+ env->mmu_version = def->mmu_version;
+ env->maxtl = def->maxtl;
+ env->version |= def->maxtl << 8;
+ env->version |= def->nwindows - 1;
+#endif
+ return 0;
+}
+
+static void cpu_sparc_close(CPUSPARCState *env)
+{
+ free(env->def);
+ free(env);
+}
+
+CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+{
+ CPUSPARCState *env;
+
+ env = g_malloc0(sizeof(CPUSPARCState));
+ cpu_exec_init(env);
+
+ gen_intermediate_code_init(env);
+
+ if (cpu_sparc_register(env, cpu_model) < 0) {
+ cpu_sparc_close(env);
+ return NULL;
+ }
+ qemu_init_vcpu(env);
+
+ return env;
+}
+
+void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
+{
+#if !defined(TARGET_SPARC64)
+ env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
+#endif
+}
+
+static const sparc_def_t sparc_defs[] = {
+#ifdef TARGET_SPARC64
+ {
+ .name = "Fujitsu Sparc64",
+ .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 4,
+ .maxtl = 4,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Fujitsu Sparc64 III",
+ .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 5,
+ .maxtl = 4,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Fujitsu Sparc64 IV",
+ .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Fujitsu Sparc64 V",
+ .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI UltraSparc I",
+ .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI UltraSparc II",
+ .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI UltraSparc IIi",
+ .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI UltraSparc IIe",
+ .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc III",
+ .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc III Cu",
+ .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_3,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc IIIi",
+ .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc IV",
+ .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_4,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc IV+",
+ .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
+ },
+ {
+ .name = "Sun UltraSparc IIIi+",
+ .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_3,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Sun UltraSparc T1",
+ /* defined in sparc_ifu_fdp.v and ctu.h */
+ .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_sun4v,
+ .nwindows = 8,
+ .maxtl = 6,
+ .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+ | CPU_FEATURE_GL,
+ },
+ {
+ .name = "Sun UltraSparc T2",
+ /* defined in tlu_asi_ctl.v and n2_revid_cust.v */
+ .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_sun4v,
+ .nwindows = 8,
+ .maxtl = 6,
+ .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
+ | CPU_FEATURE_GL,
+ },
+ {
+ .name = "NEC UltraSparc I",
+ .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
+ .fpu_version = 0x00000000,
+ .mmu_version = mmu_us_12,
+ .nwindows = 8,
+ .maxtl = 5,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+#else
+ {
+ .name = "Fujitsu MB86900",
+ .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
+ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+ .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 7,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "Fujitsu MB86904",
+ .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
+ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+ .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x00ffffc0,
+ .mmu_cxr_mask = 0x000000ff,
+ .mmu_sfsr_mask = 0x00016fff,
+ .mmu_trcr_mask = 0x00ffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Fujitsu MB86907",
+ .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
+ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+ .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x000000ff,
+ .mmu_sfsr_mask = 0x00016fff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "LSI L64811",
+ .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
+ .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
+ .mmu_version = 0x10 << 24,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "Cypress CY7C601",
+ .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
+ .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+ .mmu_version = 0x10 << 24,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "Cypress CY7C611",
+ .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
+ .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
+ .mmu_version = 0x10 << 24,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "TI MicroSparc I",
+ .iu_version = 0x41000000,
+ .fpu_version = 4 << 17,
+ .mmu_version = 0x41000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0x00016fff,
+ .mmu_trcr_mask = 0x0000003f,
+ .nwindows = 7,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
+ CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FMUL,
+ },
+ {
+ .name = "TI MicroSparc II",
+ .iu_version = 0x42000000,
+ .fpu_version = 4 << 17,
+ .mmu_version = 0x02000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x00ffffc0,
+ .mmu_cxr_mask = 0x000000ff,
+ .mmu_sfsr_mask = 0x00016fff,
+ .mmu_trcr_mask = 0x00ffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI MicroSparc IIep",
+ .iu_version = 0x42000000,
+ .fpu_version = 4 << 17,
+ .mmu_version = 0x04000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x00ffffc0,
+ .mmu_cxr_mask = 0x000000ff,
+ .mmu_sfsr_mask = 0x00016bff,
+ .mmu_trcr_mask = 0x00ffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc 40", /* STP1020NPGA */
+ .iu_version = 0x41000000, /* SuperSPARC 2.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x00000800, /* SuperSPARC 2.x, no MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc 50", /* STP1020PGA */
+ .iu_version = 0x40000000, /* SuperSPARC 3.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc 51",
+ .iu_version = 0x40000000, /* SuperSPARC 3.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc 60", /* STP1020APGA */
+ .iu_version = 0x40000000, /* SuperSPARC 3.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x01000800, /* SuperSPARC 3.x, no MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc 61",
+ .iu_version = 0x44000000, /* SuperSPARC 3.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x01000000, /* SuperSPARC 3.x, MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc II",
+ .iu_version = 0x40000000, /* SuperSPARC II 1.x */
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x08000000, /* SuperSPARC II 1.x, MXCC */
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Ross RT625",
+ .iu_version = 0x1e000000,
+ .fpu_version = 1 << 17,
+ .mmu_version = 0x1e000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "Ross RT620",
+ .iu_version = 0x1f000000,
+ .fpu_version = 1 << 17,
+ .mmu_version = 0x1f000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "BIT B5010",
+ .iu_version = 0x20000000,
+ .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
+ .mmu_version = 0x20000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "Matsushita MN10501",
+ .iu_version = 0x50000000,
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x50000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
+ CPU_FEATURE_FSMULD,
+ },
+ {
+ .name = "Weitek W8601",
+ .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
+ .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
+ .mmu_version = 0x10 << 24,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "LEON2",
+ .iu_version = 0xf2000000,
+ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+ .mmu_version = 0xf2000000,
+ .mmu_bm = 0x00004000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
+ },
+ {
+ .name = "LEON3",
+ .iu_version = 0xf3000000,
+ .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
+ .mmu_version = 0xf3000000,
+ .mmu_bm = 0x00000000,
+ .mmu_ctpr_mask = 0x007ffff0,
+ .mmu_cxr_mask = 0x0000003f,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
+ CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
+ },
+#endif
+};
+
+static const char * const feature_name[] = {
+ "float",
+ "float128",
+ "swap",
+ "mul",
+ "div",
+ "flush",
+ "fsqrt",
+ "fmul",
+ "vis1",
+ "vis2",
+ "fsmuld",
+ "hypv",
+ "cmt",
+ "gl",
+};
+
+static void print_features(FILE *f, fprintf_function cpu_fprintf,
+ uint32_t features, const char *prefix)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+ if (feature_name[i] && (features & (1 << i))) {
+ if (prefix) {
+ (*cpu_fprintf)(f, "%s", prefix);
+ }
+ (*cpu_fprintf)(f, "%s ", feature_name[i]);
+ }
+ }
+}
+
+static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(feature_name); i++) {
+ if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
+ *features |= 1 << i;
+ return;
+ }
+ }
+ fprintf(stderr, "CPU feature %s not found\n", flagname);
+}
+
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
+{
+ unsigned int i;
+ const sparc_def_t *def = NULL;
+ char *s = strdup(cpu_model);
+ char *featurestr, *name = strtok(s, ",");
+ uint32_t plus_features = 0;
+ uint32_t minus_features = 0;
+ uint64_t iu_version;
+ uint32_t fpu_version, mmu_version, nwindows;
+
+ for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+ if (strcasecmp(name, sparc_defs[i].name) == 0) {
+ def = &sparc_defs[i];
+ }
+ }
+ if (!def) {
+ goto error;
+ }
+ memcpy(cpu_def, def, sizeof(*def));
+
+ featurestr = strtok(NULL, ",");
+ while (featurestr) {
+ char *val;
+
+ if (featurestr[0] == '+') {
+ add_flagname_to_bitmaps(featurestr + 1, &plus_features);
+ } else if (featurestr[0] == '-') {
+ add_flagname_to_bitmaps(featurestr + 1, &minus_features);
+ } else if ((val = strchr(featurestr, '='))) {
+ *val = 0; val++;
+ if (!strcmp(featurestr, "iu_version")) {
+ char *err;
+
+ iu_version = strtoll(val, &err, 0);
+ if (!*val || *err) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ goto error;
+ }
+ cpu_def->iu_version = iu_version;
+#ifdef DEBUG_FEATURES
+ fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
+#endif
+ } else if (!strcmp(featurestr, "fpu_version")) {
+ char *err;
+
+ fpu_version = strtol(val, &err, 0);
+ if (!*val || *err) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ goto error;
+ }
+ cpu_def->fpu_version = fpu_version;
+#ifdef DEBUG_FEATURES
+ fprintf(stderr, "fpu_version %x\n", fpu_version);
+#endif
+ } else if (!strcmp(featurestr, "mmu_version")) {
+ char *err;
+
+ mmu_version = strtol(val, &err, 0);
+ if (!*val || *err) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ goto error;
+ }
+ cpu_def->mmu_version = mmu_version;
+#ifdef DEBUG_FEATURES
+ fprintf(stderr, "mmu_version %x\n", mmu_version);
+#endif
+ } else if (!strcmp(featurestr, "nwindows")) {
+ char *err;
+
+ nwindows = strtol(val, &err, 0);
+ if (!*val || *err || nwindows > MAX_NWINDOWS ||
+ nwindows < MIN_NWINDOWS) {
+ fprintf(stderr, "bad numerical value %s\n", val);
+ goto error;
+ }
+ cpu_def->nwindows = nwindows;
+#ifdef DEBUG_FEATURES
+ fprintf(stderr, "nwindows %d\n", nwindows);
+#endif
+ } else {
+ fprintf(stderr, "unrecognized feature %s\n", featurestr);
+ goto error;
+ }
+ } else {
+ fprintf(stderr, "feature string `%s' not in format "
+ "(+feature|-feature|feature=xyz)\n", featurestr);
+ goto error;
+ }
+ featurestr = strtok(NULL, ",");
+ }
+ cpu_def->features |= plus_features;
+ cpu_def->features &= ~minus_features;
+#ifdef DEBUG_FEATURES
+ print_features(stderr, fprintf, cpu_def->features, NULL);
+#endif
+ free(s);
+ return 0;
+
+ error:
+ free(s);
+ return -1;
+}
+
+void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
+ (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx
+ " FPU %08x MMU %08x NWINS %d ",
+ sparc_defs[i].name,
+ sparc_defs[i].iu_version,
+ sparc_defs[i].fpu_version,
+ sparc_defs[i].mmu_version,
+ sparc_defs[i].nwindows);
+ print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
+ ~sparc_defs[i].features, "-");
+ print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
+ sparc_defs[i].features, "+");
+ (*cpu_fprintf)(f, "\n");
+ }
+ (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
+ print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
+ (*cpu_fprintf)(f, "\n");
+ (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
+ print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
+ (*cpu_fprintf)(f, "\n");
+ (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
+ "fpu_version mmu_version nwindows\n");
+}
+
+static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
+ uint32_t cc)
+{
+ cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG ? 'N' : '-',
+ cc & PSR_ZERO ? 'Z' : '-', cc & PSR_OVF ? 'V' : '-',
+ cc & PSR_CARRY ? 'C' : '-');
+}
+
+#ifdef TARGET_SPARC64
+#define REGS_PER_LINE 4
+#else
+#define REGS_PER_LINE 8
+#endif
+
+void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
+ int flags)
+{
+ int i, x;
+
+ cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
+ env->npc);
+ cpu_fprintf(f, "General Registers:\n");
+
+ for (i = 0; i < 8; i++) {
+ if (i % REGS_PER_LINE == 0) {
+ cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
+ }
+ cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
+ if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+ cpu_fprintf(f, "\nCurrent Register Window:\n");
+ for (x = 0; x < 3; x++) {
+ for (i = 0; i < 8; i++) {
+ if (i % REGS_PER_LINE == 0) {
+ cpu_fprintf(f, "%%%c%d-%d: ",
+ x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
+ i, i + REGS_PER_LINE - 1);
+ }
+ cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
+ if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+ }
+ cpu_fprintf(f, "\nFloating Point Registers:\n");
+ for (i = 0; i < TARGET_FPREGS; i++) {
+ if ((i & 3) == 0) {
+ cpu_fprintf(f, "%%f%02d:", i);
+ }
+ cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
+ if ((i & 3) == 3) {
+ cpu_fprintf(f, "\n");
+ }
+ }
+#ifdef TARGET_SPARC64
+ cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
+ (unsigned)cpu_get_ccr(env));
+ cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
+ cpu_fprintf(f, " xcc: ");
+ cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
+ cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
+ env->psrpil);
+ cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
+ "cleanwin: %d cwp: %d\n",
+ env->cansave, env->canrestore, env->otherwin, env->wstate,
+ env->cleanwin, env->nwindows - 1 - env->cwp);
+ cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
+ TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
+#else
+ cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
+ cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
+ cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs ? 'S' : '-',
+ env->psrps ? 'P' : '-', env->psret ? 'E' : '-',
+ env->wim);
+ cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
+ env->fsr, env->y);
+#endif
+}
diff --git a/target-sparc/fop_helper.c b/target-sparc/fop_helper.c
new file mode 100644
index 0000000000..23502f3020
--- /dev/null
+++ b/target-sparc/fop_helper.c
@@ -0,0 +1,394 @@
+/*
+ * FPU op helpers
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define QT0 (env->qt0)
+#define QT1 (env->qt1)
+
+#define F_HELPER(name, p) void helper_f##name##p(CPUState *env)
+
+#define F_BINOP(name) \
+ float32 helper_f ## name ## s (CPUState * env, float32 src1,\
+ float32 src2) \
+ { \
+ return float32_ ## name (src1, src2, &env->fp_status); \
+ } \
+ F_HELPER(name, d) \
+ { \
+ DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
+ } \
+ F_HELPER(name, q) \
+ { \
+ QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
+ }
+
+F_BINOP(add);
+F_BINOP(sub);
+F_BINOP(mul);
+F_BINOP(div);
+#undef F_BINOP
+
+void helper_fsmuld(CPUState *env, float32 src1, float32 src2)
+{
+ DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
+ float32_to_float64(src2, &env->fp_status),
+ &env->fp_status);
+}
+
+void helper_fdmulq(CPUState *env)
+{
+ QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
+ float64_to_float128(DT1, &env->fp_status),
+ &env->fp_status);
+}
+
+float32 helper_fnegs(float32 src)
+{
+ return float32_chs(src);
+}
+
+#ifdef TARGET_SPARC64
+F_HELPER(neg, d)
+{
+ DT0 = float64_chs(DT1);
+}
+
+F_HELPER(neg, q)
+{
+ QT0 = float128_chs(QT1);
+}
+#endif
+
+/* Integer to float conversion. */
+float32 helper_fitos(CPUState *env, int32_t src)
+{
+ return int32_to_float32(src, &env->fp_status);
+}
+
+void helper_fitod(CPUState *env, int32_t src)
+{
+ DT0 = int32_to_float64(src, &env->fp_status);
+}
+
+void helper_fitoq(CPUState *env, int32_t src)
+{
+ QT0 = int32_to_float128(src, &env->fp_status);
+}
+
+#ifdef TARGET_SPARC64
+float32 helper_fxtos(CPUState *env)
+{
+ return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
+}
+
+F_HELPER(xto, d)
+{
+ DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
+}
+
+F_HELPER(xto, q)
+{
+ QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
+}
+#endif
+#undef F_HELPER
+
+/* floating point conversion */
+float32 helper_fdtos(CPUState *env)
+{
+ return float64_to_float32(DT1, &env->fp_status);
+}
+
+void helper_fstod(CPUState *env, float32 src)
+{
+ DT0 = float32_to_float64(src, &env->fp_status);
+}
+
+float32 helper_fqtos(CPUState *env)
+{
+ return float128_to_float32(QT1, &env->fp_status);
+}
+
+void helper_fstoq(CPUState *env, float32 src)
+{
+ QT0 = float32_to_float128(src, &env->fp_status);
+}
+
+void helper_fqtod(CPUState *env)
+{
+ DT0 = float128_to_float64(QT1, &env->fp_status);
+}
+
+void helper_fdtoq(CPUState *env)
+{
+ QT0 = float64_to_float128(DT1, &env->fp_status);
+}
+
+/* Float to integer conversion. */
+int32_t helper_fstoi(CPUState *env, float32 src)
+{
+ return float32_to_int32_round_to_zero(src, &env->fp_status);
+}
+
+int32_t helper_fdtoi(CPUState *env)
+{
+ return float64_to_int32_round_to_zero(DT1, &env->fp_status);
+}
+
+int32_t helper_fqtoi(CPUState *env)
+{
+ return float128_to_int32_round_to_zero(QT1, &env->fp_status);
+}
+
+#ifdef TARGET_SPARC64
+void helper_fstox(CPUState *env, float32 src)
+{
+ *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
+}
+
+void helper_fdtox(CPUState *env)
+{
+ *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
+}
+
+void helper_fqtox(CPUState *env)
+{
+ *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
+}
+#endif
+
+float32 helper_fabss(float32 src)
+{
+ return float32_abs(src);
+}
+
+#ifdef TARGET_SPARC64
+void helper_fabsd(CPUState *env)
+{
+ DT0 = float64_abs(DT1);
+}
+
+void helper_fabsq(CPUState *env)
+{
+ QT0 = float128_abs(QT1);
+}
+#endif
+
+float32 helper_fsqrts(CPUState *env, float32 src)
+{
+ return float32_sqrt(src, &env->fp_status);
+}
+
+void helper_fsqrtd(CPUState *env)
+{
+ DT0 = float64_sqrt(DT1, &env->fp_status);
+}
+
+void helper_fsqrtq(CPUState *env)
+{
+ QT0 = float128_sqrt(QT1, &env->fp_status);
+}
+
+#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
+ void glue(helper_, name) (CPUState *env) \
+ { \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(reg1) || \
+ glue(size, _is_any_nan)(reg2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ helper_raise_exception(env, TT_FP_EXCP); \
+ } \
+ switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
+ case float_relation_unordered: \
+ if ((env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ helper_raise_exception(env, TT_FP_EXCP); \
+ } else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
+ env->fsr |= FSR_NVA; \
+ } \
+ break; \
+ case float_relation_less: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
+ break; \
+ case float_relation_greater: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
+ break; \
+ default: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ break; \
+ } \
+ }
+#define GEN_FCMPS(name, size, FS, E) \
+ void glue(helper_, name)(CPUState *env, float32 src1, float32 src2) \
+ { \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(src1) || \
+ glue(size, _is_any_nan)(src2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ helper_raise_exception(env, TT_FP_EXCP); \
+ } \
+ switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
+ case float_relation_unordered: \
+ if ((env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ helper_raise_exception(env, TT_FP_EXCP); \
+ } else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
+ env->fsr |= FSR_NVA; \
+ } \
+ break; \
+ case float_relation_less: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
+ break; \
+ case float_relation_greater: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
+ break; \
+ default: \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ break; \
+ } \
+ }
+
+GEN_FCMPS(fcmps, float32, 0, 0);
+GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
+
+GEN_FCMPS(fcmpes, float32, 0, 1);
+GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
+
+GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
+GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
+
+#ifdef TARGET_SPARC64
+GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
+GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
+GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
+
+GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
+GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
+GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
+
+GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
+GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
+GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
+
+GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
+GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
+GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
+
+GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
+GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
+GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
+
+GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
+GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
+GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
+#endif
+#undef GEN_FCMPS
+
+void helper_check_ieee_exceptions(CPUState *env)
+{
+ target_ulong status;
+
+ status = get_float_exception_flags(&env->fp_status);
+ if (status) {
+ /* Copy IEEE 754 flags into FSR */
+ if (status & float_flag_invalid) {
+ env->fsr |= FSR_NVC;
+ }
+ if (status & float_flag_overflow) {
+ env->fsr |= FSR_OFC;
+ }
+ if (status & float_flag_underflow) {
+ env->fsr |= FSR_UFC;
+ }
+ if (status & float_flag_divbyzero) {
+ env->fsr |= FSR_DZC;
+ }
+ if (status & float_flag_inexact) {
+ env->fsr |= FSR_NXC;
+ }
+
+ if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
+ /* Unmasked exception, generate a trap */
+ env->fsr |= FSR_FTT_IEEE_EXCP;
+ helper_raise_exception(env, TT_FP_EXCP);
+ } else {
+ /* Accumulate exceptions */
+ env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
+ }
+ }
+}
+
+void helper_clear_float_exceptions(CPUState *env)
+{
+ set_float_exception_flags(0, &env->fp_status);
+}
+
+static inline void set_fsr(CPUState *env)
+{
+ int rnd_mode;
+
+ switch (env->fsr & FSR_RD_MASK) {
+ case FSR_RD_NEAREST:
+ rnd_mode = float_round_nearest_even;
+ break;
+ default:
+ case FSR_RD_ZERO:
+ rnd_mode = float_round_to_zero;
+ break;
+ case FSR_RD_POS:
+ rnd_mode = float_round_up;
+ break;
+ case FSR_RD_NEG:
+ rnd_mode = float_round_down;
+ break;
+ }
+ set_float_rounding_mode(rnd_mode, &env->fp_status);
+}
+
+void helper_ldfsr(CPUState *env, uint32_t new_fsr)
+{
+ env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
+ set_fsr(env);
+}
+
+#ifdef TARGET_SPARC64
+void helper_ldxfsr(CPUState *env, uint64_t new_fsr)
+{
+ env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
+ set_fsr(env);
+}
+#endif
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index c80531a16c..7a25605fa7 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -16,17 +16,13 @@
* 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 <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
#include "cpu.h"
-#include "qemu-common.h"
+#include "host-utils.h"
+#include "helper.h"
+#include "sysemu.h"
//#define DEBUG_MMU
-//#define DEBUG_FEATURES
#ifdef DEBUG_MMU
#define DPRINTF_MMU(fmt, ...) \
@@ -35,8 +31,6 @@
#define DPRINTF_MMU(fmt, ...) do {} while (0)
#endif
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
-
/* Sparc MMU emulation */
#if defined(CONFIG_USER_ONLY)
@@ -358,8 +352,6 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
}
}
-#if !defined(CONFIG_USER_ONLY)
-
/* Gdb expects all registers windows to be flushed in ram. This function handles
* reads (and only reads) in stack frames as if windows were flushed. We assume
* that the sparc ABI is followed.
@@ -440,8 +432,6 @@ int target_memory_rw_debug(CPUState *env, target_ulong addr,
return cpu_memory_rw_debug(env, addr, buf, len, is_write);
}
-#endif /* !defined(CONFIG_USER_ONLY) */
-
#else /* !TARGET_SPARC64 */
// 41 bit physical address space
@@ -839,10 +829,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
}
#endif /* TARGET_SPARC64 */
-#endif /* !CONFIG_USER_ONLY */
-
-#if !defined(CONFIG_USER_ONLY)
static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys,
target_ulong addr, int rw, int mmu_idx)
{
@@ -883,1059 +870,52 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
}
#endif
-#ifdef TARGET_SPARC64
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
- [TT_TFAULT] = "Instruction Access Fault",
- [TT_TMISS] = "Instruction Access MMU Miss",
- [TT_CODE_ACCESS] = "Instruction Access Error",
- [TT_ILL_INSN] = "Illegal Instruction",
- [TT_PRIV_INSN] = "Privileged Instruction",
- [TT_NFPU_INSN] = "FPU Disabled",
- [TT_FP_EXCP] = "FPU Exception",
- [TT_TOVF] = "Tag Overflow",
- [TT_CLRWIN] = "Clean Windows",
- [TT_DIV_ZERO] = "Division By Zero",
- [TT_DFAULT] = "Data Access Fault",
- [TT_DMISS] = "Data Access MMU Miss",
- [TT_DATA_ACCESS] = "Data Access Error",
- [TT_DPROT] = "Data Protection Error",
- [TT_UNALIGNED] = "Unaligned Memory Access",
- [TT_PRIV_ACT] = "Privileged Action",
- [TT_EXTINT | 0x1] = "External Interrupt 1",
- [TT_EXTINT | 0x2] = "External Interrupt 2",
- [TT_EXTINT | 0x3] = "External Interrupt 3",
- [TT_EXTINT | 0x4] = "External Interrupt 4",
- [TT_EXTINT | 0x5] = "External Interrupt 5",
- [TT_EXTINT | 0x6] = "External Interrupt 6",
- [TT_EXTINT | 0x7] = "External Interrupt 7",
- [TT_EXTINT | 0x8] = "External Interrupt 8",
- [TT_EXTINT | 0x9] = "External Interrupt 9",
- [TT_EXTINT | 0xa] = "External Interrupt 10",
- [TT_EXTINT | 0xb] = "External Interrupt 11",
- [TT_EXTINT | 0xc] = "External Interrupt 12",
- [TT_EXTINT | 0xd] = "External Interrupt 13",
- [TT_EXTINT | 0xe] = "External Interrupt 14",
- [TT_EXTINT | 0xf] = "External Interrupt 15",
-};
-#endif
-
-void do_interrupt(CPUState *env)
-{
- int intno = env->exception_index;
- trap_state *tsptr;
-
-#ifdef DEBUG_PCALL
- if (qemu_loglevel_mask(CPU_LOG_INT)) {
- static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x180) {
- name = "Unknown";
- } else if (intno >= 0x100) {
- name = "Trap Instruction";
- } else if (intno >= 0xc0) {
- name = "Window Fill";
- } else if (intno >= 0x80) {
- name = "Window Spill";
- } else {
- name = excp_names[intno];
- if (!name) {
- name = "Unknown";
- }
- }
-
- qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
- " SP=%016" PRIx64 "\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
- log_cpu_state(env, 0);
-#if 0
- {
- int i;
- uint8_t *ptr;
-
- qemu_log(" code=");
- ptr = (uint8_t *)env->pc;
- for (i = 0; i < 16; i++) {
- qemu_log(" %02x", ldub(ptr + i));
- }
- qemu_log("\n");
- }
-#endif
- count++;
- }
-#endif
-#if !defined(CONFIG_USER_ONLY)
- if (env->tl >= env->maxtl) {
- cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
- " Error state", env->exception_index, env->tl, env->maxtl);
- return;
- }
-#endif
- if (env->tl < env->maxtl - 1) {
- env->tl++;
- } else {
- env->pstate |= PS_RED;
- if (env->tl < env->maxtl) {
- env->tl++;
- }
- }
- tsptr = cpu_tsptr(env);
-
- tsptr->tstate = (cpu_get_ccr(env) << 32) |
- ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
- cpu_get_cwp64(env);
- tsptr->tpc = env->pc;
- tsptr->tnpc = env->npc;
- tsptr->tt = intno;
-
- switch (intno) {
- case TT_IVEC:
- cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
- break;
- case TT_TFAULT:
- case TT_DFAULT:
- case TT_TMISS ... TT_TMISS + 3:
- case TT_DMISS ... TT_DMISS + 3:
- case TT_DPROT ... TT_DPROT + 3:
- cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
- break;
- default:
- cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
- break;
- }
-
- if (intno == TT_CLRWIN) {
- cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
- } else if ((intno & 0x1c0) == TT_SPILL) {
- cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
- } else if ((intno & 0x1c0) == TT_FILL) {
- cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
- }
- env->tbr &= ~0x7fffULL;
- env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
- env->pc = env->tbr;
- env->npc = env->pc + 4;
- env->exception_index = -1;
-}
-#else
-#ifdef DEBUG_PCALL
-static const char * const excp_names[0x80] = {
- [TT_TFAULT] = "Instruction Access Fault",
- [TT_ILL_INSN] = "Illegal Instruction",
- [TT_PRIV_INSN] = "Privileged Instruction",
- [TT_NFPU_INSN] = "FPU Disabled",
- [TT_WIN_OVF] = "Window Overflow",
- [TT_WIN_UNF] = "Window Underflow",
- [TT_UNALIGNED] = "Unaligned Memory Access",
- [TT_FP_EXCP] = "FPU Exception",
- [TT_DFAULT] = "Data Access Fault",
- [TT_TOVF] = "Tag Overflow",
- [TT_EXTINT | 0x1] = "External Interrupt 1",
- [TT_EXTINT | 0x2] = "External Interrupt 2",
- [TT_EXTINT | 0x3] = "External Interrupt 3",
- [TT_EXTINT | 0x4] = "External Interrupt 4",
- [TT_EXTINT | 0x5] = "External Interrupt 5",
- [TT_EXTINT | 0x6] = "External Interrupt 6",
- [TT_EXTINT | 0x7] = "External Interrupt 7",
- [TT_EXTINT | 0x8] = "External Interrupt 8",
- [TT_EXTINT | 0x9] = "External Interrupt 9",
- [TT_EXTINT | 0xa] = "External Interrupt 10",
- [TT_EXTINT | 0xb] = "External Interrupt 11",
- [TT_EXTINT | 0xc] = "External Interrupt 12",
- [TT_EXTINT | 0xd] = "External Interrupt 13",
- [TT_EXTINT | 0xe] = "External Interrupt 14",
- [TT_EXTINT | 0xf] = "External Interrupt 15",
- [TT_TOVF] = "Tag Overflow",
- [TT_CODE_ACCESS] = "Instruction Access Error",
- [TT_DATA_ACCESS] = "Data Access Error",
- [TT_DIV_ZERO] = "Division By Zero",
- [TT_NCP_INSN] = "Coprocessor Disabled",
-};
-#endif
-
-void do_interrupt(CPUState *env)
-{
- int cwp, intno = env->exception_index;
-
-#ifdef DEBUG_PCALL
- if (qemu_loglevel_mask(CPU_LOG_INT)) {
- static int count;
- const char *name;
-
- if (intno < 0 || intno >= 0x100) {
- name = "Unknown";
- } else if (intno >= 0x80) {
- name = "Trap Instruction";
- } else {
- name = excp_names[intno];
- if (!name) {
- name = "Unknown";
- }
- }
-
- qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
- count, name, intno,
- env->pc,
- env->npc, env->regwptr[6]);
- log_cpu_state(env, 0);
-#if 0
- {
- int i;
- uint8_t *ptr;
-
- qemu_log(" code=");
- ptr = (uint8_t *)env->pc;
- for (i = 0; i < 16; i++) {
- qemu_log(" %02x", ldub(ptr + i));
- }
- qemu_log("\n");
- }
-#endif
- count++;
- }
-#endif
-#if !defined(CONFIG_USER_ONLY)
- if (env->psret == 0) {
- cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
- env->exception_index);
- return;
- }
-#endif
- env->psret = 0;
- cwp = cpu_cwp_dec(env, env->cwp - 1);
- cpu_set_cwp(env, cwp);
- env->regwptr[9] = env->pc;
- env->regwptr[10] = env->npc;
- env->psrps = env->psrs;
- env->psrs = 1;
- env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
- env->pc = env->tbr;
- env->npc = env->pc + 4;
- env->exception_index = -1;
-
-#if !defined(CONFIG_USER_ONLY)
- /* IRQ acknowledgment */
- if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
- env->qemu_irq_ack(env->irq_manager, intno);
- }
-#endif
-}
-#endif
-
-void cpu_reset(CPUSPARCState *env)
-{
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- tlb_flush(env, 1);
- env->cwp = 0;
-#ifndef TARGET_SPARC64
- env->wim = 1;
-#endif
- env->regwptr = env->regbase + (env->cwp * 16);
- CC_OP = CC_OP_FLAGS;
-#if defined(CONFIG_USER_ONLY)
-#ifdef TARGET_SPARC64
- env->cleanwin = env->nwindows - 2;
- env->cansave = env->nwindows - 2;
- env->pstate = PS_RMO | PS_PEF | PS_IE;
- env->asi = 0x82; // Primary no-fault
-#endif
-#else
-#if !defined(TARGET_SPARC64)
- env->psret = 0;
- env->psrs = 1;
- env->psrps = 1;
-#endif
-#ifdef TARGET_SPARC64
- env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
- env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
- env->tl = env->maxtl;
- cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
- env->lsu = 0;
-#else
- env->mmuregs[0] &= ~(MMU_E | MMU_NF);
- env->mmuregs[0] |= env->def->mmu_bm;
-#endif
- env->pc = 0;
- env->npc = env->pc + 4;
-#endif
- env->cache_control = 0;
-}
-
-static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
-{
- sparc_def_t def1, *def = &def1;
-
- if (cpu_sparc_find_by_name(def, cpu_model) < 0)
- return -1;
-
- env->def = g_malloc0(sizeof(*def));
- memcpy(env->def, def, sizeof(*def));
-#if defined(CONFIG_USER_ONLY)
- if ((env->def->features & CPU_FEATURE_FLOAT))
- env->def->features |= CPU_FEATURE_FLOAT128;
-#endif
- env->cpu_model_str = cpu_model;
- env->version = def->iu_version;
- env->fsr = def->fpu_version;
- env->nwindows = def->nwindows;
-#if !defined(TARGET_SPARC64)
- env->mmuregs[0] |= def->mmu_version;
- cpu_sparc_set_id(env, 0);
- env->mxccregs[7] |= def->mxcc_version;
-#else
- env->mmu_version = def->mmu_version;
- env->maxtl = def->maxtl;
- env->version |= def->maxtl << 8;
- env->version |= def->nwindows - 1;
-#endif
- return 0;
-}
-
-static void cpu_sparc_close(CPUSPARCState *env)
+/* misc op helpers */
+void helper_raise_exception(CPUState *env, int tt)
{
- free(env->def);
- free(env);
+ env->exception_index = tt;
+ cpu_loop_exit(env);
}
-CPUSPARCState *cpu_sparc_init(const char *cpu_model)
+void helper_debug(CPUState *env)
{
- CPUSPARCState *env;
-
- env = g_malloc0(sizeof(CPUSPARCState));
- cpu_exec_init(env);
-
- gen_intermediate_code_init(env);
-
- if (cpu_sparc_register(env, cpu_model) < 0) {
- cpu_sparc_close(env);
- return NULL;
- }
- qemu_init_vcpu(env);
-
- return env;
+ env->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(env);
}
-void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu)
+void helper_shutdown(void)
{
-#if !defined(TARGET_SPARC64)
- env->mxccregs[7] = ((cpu + 8) & 0xf) << 24;
+#if !defined(CONFIG_USER_ONLY)
+ qemu_system_shutdown_request();
#endif
}
-static const sparc_def_t sparc_defs[] = {
#ifdef TARGET_SPARC64
- {
- .name = "Fujitsu Sparc64",
- .iu_version = ((0x04ULL << 48) | (0x02ULL << 32) | (0ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 4,
- .maxtl = 4,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Fujitsu Sparc64 III",
- .iu_version = ((0x04ULL << 48) | (0x03ULL << 32) | (0ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 5,
- .maxtl = 4,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Fujitsu Sparc64 IV",
- .iu_version = ((0x04ULL << 48) | (0x04ULL << 32) | (0ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Fujitsu Sparc64 V",
- .iu_version = ((0x04ULL << 48) | (0x05ULL << 32) | (0x51ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI UltraSparc I",
- .iu_version = ((0x17ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI UltraSparc II",
- .iu_version = ((0x17ULL << 48) | (0x11ULL << 32) | (0x20ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI UltraSparc IIi",
- .iu_version = ((0x17ULL << 48) | (0x12ULL << 32) | (0x91ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI UltraSparc IIe",
- .iu_version = ((0x17ULL << 48) | (0x13ULL << 32) | (0x14ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc III",
- .iu_version = ((0x3eULL << 48) | (0x14ULL << 32) | (0x34ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc III Cu",
- .iu_version = ((0x3eULL << 48) | (0x15ULL << 32) | (0x41ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_3,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc IIIi",
- .iu_version = ((0x3eULL << 48) | (0x16ULL << 32) | (0x34ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc IV",
- .iu_version = ((0x3eULL << 48) | (0x18ULL << 32) | (0x31ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_4,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc IV+",
- .iu_version = ((0x3eULL << 48) | (0x19ULL << 32) | (0x22ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_CMT,
- },
- {
- .name = "Sun UltraSparc IIIi+",
- .iu_version = ((0x3eULL << 48) | (0x22ULL << 32) | (0ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_3,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Sun UltraSparc T1",
- // defined in sparc_ifu_fdp.v and ctu.h
- .iu_version = ((0x3eULL << 48) | (0x23ULL << 32) | (0x02ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_sun4v,
- .nwindows = 8,
- .maxtl = 6,
- .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
- | CPU_FEATURE_GL,
- },
- {
- .name = "Sun UltraSparc T2",
- // defined in tlu_asi_ctl.v and n2_revid_cust.v
- .iu_version = ((0x3eULL << 48) | (0x24ULL << 32) | (0x02ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_sun4v,
- .nwindows = 8,
- .maxtl = 6,
- .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_HYPV | CPU_FEATURE_CMT
- | CPU_FEATURE_GL,
- },
- {
- .name = "NEC UltraSparc I",
- .iu_version = ((0x22ULL << 48) | (0x10ULL << 32) | (0x40ULL << 24)),
- .fpu_version = 0x00000000,
- .mmu_version = mmu_us_12,
- .nwindows = 8,
- .maxtl = 5,
- .features = CPU_DEFAULT_FEATURES,
- },
-#else
- {
- .name = "Fujitsu MB86900",
- .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
- .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
- .mmu_version = 0x00 << 24, /* Impl 0, ver 0 */
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 7,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_FSMULD,
- },
- {
- .name = "Fujitsu MB86904",
- .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
- .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
- .mmu_version = 0x04 << 24, /* Impl 0, ver 4 */
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x00ffffc0,
- .mmu_cxr_mask = 0x000000ff,
- .mmu_sfsr_mask = 0x00016fff,
- .mmu_trcr_mask = 0x00ffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Fujitsu MB86907",
- .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
- .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
- .mmu_version = 0x05 << 24, /* Impl 0, ver 5 */
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x000000ff,
- .mmu_sfsr_mask = 0x00016fff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "LSI L64811",
- .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
- .fpu_version = 1 << 17, /* FPU version 1 (LSI L64814) */
- .mmu_version = 0x10 << 24,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FSMULD,
- },
- {
- .name = "Cypress CY7C601",
- .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
- .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
- .mmu_version = 0x10 << 24,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FSMULD,
- },
- {
- .name = "Cypress CY7C611",
- .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
- .fpu_version = 3 << 17, /* FPU version 3 (Cypress CY7C602) */
- .mmu_version = 0x10 << 24,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FSMULD,
- },
- {
- .name = "TI MicroSparc I",
- .iu_version = 0x41000000,
- .fpu_version = 4 << 17,
- .mmu_version = 0x41000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0x00016fff,
- .mmu_trcr_mask = 0x0000003f,
- .nwindows = 7,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_MUL |
- CPU_FEATURE_DIV | CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FMUL,
- },
- {
- .name = "TI MicroSparc II",
- .iu_version = 0x42000000,
- .fpu_version = 4 << 17,
- .mmu_version = 0x02000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x00ffffc0,
- .mmu_cxr_mask = 0x000000ff,
- .mmu_sfsr_mask = 0x00016fff,
- .mmu_trcr_mask = 0x00ffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI MicroSparc IIep",
- .iu_version = 0x42000000,
- .fpu_version = 4 << 17,
- .mmu_version = 0x04000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x00ffffc0,
- .mmu_cxr_mask = 0x000000ff,
- .mmu_sfsr_mask = 0x00016bff,
- .mmu_trcr_mask = 0x00ffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc 40", // STP1020NPGA
- .iu_version = 0x41000000, // SuperSPARC 2.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc 50", // STP1020PGA
- .iu_version = 0x40000000, // SuperSPARC 3.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc 51",
- .iu_version = 0x40000000, // SuperSPARC 3.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .mxcc_version = 0x00000104,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc 60", // STP1020APGA
- .iu_version = 0x40000000, // SuperSPARC 3.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc 61",
- .iu_version = 0x44000000, // SuperSPARC 3.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .mxcc_version = 0x00000104,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "TI SuperSparc II",
- .iu_version = 0x40000000, // SuperSPARC II 1.x
- .fpu_version = 0 << 17,
- .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .mxcc_version = 0x00000104,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Ross RT625",
- .iu_version = 0x1e000000,
- .fpu_version = 1 << 17,
- .mmu_version = 0x1e000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "Ross RT620",
- .iu_version = 0x1f000000,
- .fpu_version = 1 << 17,
- .mmu_version = 0x1f000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "BIT B5010",
- .iu_version = 0x20000000,
- .fpu_version = 0 << 17, /* B5010/B5110/B5120/B5210 */
- .mmu_version = 0x20000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FSMULD,
- },
- {
- .name = "Matsushita MN10501",
- .iu_version = 0x50000000,
- .fpu_version = 0 << 17,
- .mmu_version = 0x50000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_FEATURE_FLOAT | CPU_FEATURE_MUL | CPU_FEATURE_FSQRT |
- CPU_FEATURE_FSMULD,
- },
- {
- .name = "Weitek W8601",
- .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
- .fpu_version = 3 << 17, /* FPU version 3 (Weitek WTL3170/2) */
- .mmu_version = 0x10 << 24,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
- .name = "LEON2",
- .iu_version = 0xf2000000,
- .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
- .mmu_version = 0xf2000000,
- .mmu_bm = 0x00004000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN,
- },
- {
- .name = "LEON3",
- .iu_version = 0xf3000000,
- .fpu_version = 4 << 17, /* FPU version 4 (Meiko) */
- .mmu_version = 0xf3000000,
- .mmu_bm = 0x00000000,
- .mmu_ctpr_mask = 0x007ffff0,
- .mmu_cxr_mask = 0x0000003f,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
- CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
- },
-#endif
-};
-
-static const char * const feature_name[] = {
- "float",
- "float128",
- "swap",
- "mul",
- "div",
- "flush",
- "fsqrt",
- "fmul",
- "vis1",
- "vis2",
- "fsmuld",
- "hypv",
- "cmt",
- "gl",
-};
-
-static void print_features(FILE *f, fprintf_function cpu_fprintf,
- uint32_t features, const char *prefix)
+target_ulong helper_popc(target_ulong val)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(feature_name); i++)
- if (feature_name[i] && (features & (1 << i))) {
- if (prefix)
- (*cpu_fprintf)(f, "%s", prefix);
- (*cpu_fprintf)(f, "%s ", feature_name[i]);
- }
+ return ctpop64(val);
}
-static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
+void helper_tick_set_count(void *opaque, uint64_t count)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(feature_name); i++)
- if (feature_name[i] && !strcmp(flagname, feature_name[i])) {
- *features |= 1 << i;
- return;
- }
- fprintf(stderr, "CPU feature %s not found\n", flagname);
-}
-
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
-{
- unsigned int i;
- const sparc_def_t *def = NULL;
- char *s = strdup(cpu_model);
- char *featurestr, *name = strtok(s, ",");
- uint32_t plus_features = 0;
- uint32_t minus_features = 0;
- uint64_t iu_version;
- uint32_t fpu_version, mmu_version, nwindows;
-
- for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
- if (strcasecmp(name, sparc_defs[i].name) == 0) {
- def = &sparc_defs[i];
- }
- }
- if (!def)
- goto error;
- memcpy(cpu_def, def, sizeof(*def));
-
- featurestr = strtok(NULL, ",");
- while (featurestr) {
- char *val;
-
- if (featurestr[0] == '+') {
- add_flagname_to_bitmaps(featurestr + 1, &plus_features);
- } else if (featurestr[0] == '-') {
- add_flagname_to_bitmaps(featurestr + 1, &minus_features);
- } else if ((val = strchr(featurestr, '='))) {
- *val = 0; val++;
- if (!strcmp(featurestr, "iu_version")) {
- char *err;
-
- iu_version = strtoll(val, &err, 0);
- if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
- }
- cpu_def->iu_version = iu_version;
-#ifdef DEBUG_FEATURES
- fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
-#endif
- } else if (!strcmp(featurestr, "fpu_version")) {
- char *err;
-
- fpu_version = strtol(val, &err, 0);
- if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
- }
- cpu_def->fpu_version = fpu_version;
-#ifdef DEBUG_FEATURES
- fprintf(stderr, "fpu_version %x\n", fpu_version);
-#endif
- } else if (!strcmp(featurestr, "mmu_version")) {
- char *err;
-
- mmu_version = strtol(val, &err, 0);
- if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
- }
- cpu_def->mmu_version = mmu_version;
-#ifdef DEBUG_FEATURES
- fprintf(stderr, "mmu_version %x\n", mmu_version);
-#endif
- } else if (!strcmp(featurestr, "nwindows")) {
- char *err;
-
- nwindows = strtol(val, &err, 0);
- if (!*val || *err || nwindows > MAX_NWINDOWS ||
- nwindows < MIN_NWINDOWS) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
- }
- cpu_def->nwindows = nwindows;
-#ifdef DEBUG_FEATURES
- fprintf(stderr, "nwindows %d\n", nwindows);
-#endif
- } else {
- fprintf(stderr, "unrecognized feature %s\n", featurestr);
- goto error;
- }
- } else {
- fprintf(stderr, "feature string `%s' not in format "
- "(+feature|-feature|feature=xyz)\n", featurestr);
- goto error;
- }
- featurestr = strtok(NULL, ",");
- }
- cpu_def->features |= plus_features;
- cpu_def->features &= ~minus_features;
-#ifdef DEBUG_FEATURES
- print_features(stderr, fprintf, cpu_def->features, NULL);
+#if !defined(CONFIG_USER_ONLY)
+ cpu_tick_set_count(opaque, count);
#endif
- free(s);
- return 0;
-
- error:
- free(s);
- return -1;
-}
-
-void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
- (*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
- sparc_defs[i].name,
- sparc_defs[i].iu_version,
- sparc_defs[i].fpu_version,
- sparc_defs[i].mmu_version,
- sparc_defs[i].nwindows);
- print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES &
- ~sparc_defs[i].features, "-");
- print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES &
- sparc_defs[i].features, "+");
- (*cpu_fprintf)(f, "\n");
- }
- (*cpu_fprintf)(f, "Default CPU feature flags (use '-' to remove): ");
- print_features(f, cpu_fprintf, CPU_DEFAULT_FEATURES, NULL);
- (*cpu_fprintf)(f, "\n");
- (*cpu_fprintf)(f, "Available CPU feature flags (use '+' to add): ");
- print_features(f, cpu_fprintf, ~CPU_DEFAULT_FEATURES, NULL);
- (*cpu_fprintf)(f, "\n");
- (*cpu_fprintf)(f, "Numerical features (use '=' to set): iu_version "
- "fpu_version mmu_version nwindows\n");
}
-static void cpu_print_cc(FILE *f, fprintf_function cpu_fprintf,
- uint32_t cc)
+uint64_t helper_tick_get_count(void *opaque)
{
- cpu_fprintf(f, "%c%c%c%c", cc & PSR_NEG? 'N' : '-',
- cc & PSR_ZERO? 'Z' : '-', cc & PSR_OVF? 'V' : '-',
- cc & PSR_CARRY? 'C' : '-');
-}
-
-#ifdef TARGET_SPARC64
-#define REGS_PER_LINE 4
+#if !defined(CONFIG_USER_ONLY)
+ return cpu_tick_get_count(opaque);
#else
-#define REGS_PER_LINE 8
+ return 0;
#endif
+}
-void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
- int flags)
+void helper_tick_set_limit(void *opaque, uint64_t limit)
{
- int i, x;
-
- cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc,
- env->npc);
- cpu_fprintf(f, "General Registers:\n");
-
- for (i = 0; i < 8; i++) {
- if (i % REGS_PER_LINE == 0) {
- cpu_fprintf(f, "%%g%d-%d:", i, i + REGS_PER_LINE - 1);
- }
- cpu_fprintf(f, " " TARGET_FMT_lx, env->gregs[i]);
- if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
- cpu_fprintf(f, "\n");
- }
- }
- cpu_fprintf(f, "\nCurrent Register Window:\n");
- for (x = 0; x < 3; x++) {
- for (i = 0; i < 8; i++) {
- if (i % REGS_PER_LINE == 0) {
- cpu_fprintf(f, "%%%c%d-%d: ",
- x == 0 ? 'o' : (x == 1 ? 'l' : 'i'),
- i, i + REGS_PER_LINE - 1);
- }
- cpu_fprintf(f, TARGET_FMT_lx " ", env->regwptr[i + x * 8]);
- if (i % REGS_PER_LINE == REGS_PER_LINE - 1) {
- cpu_fprintf(f, "\n");
- }
- }
- }
- cpu_fprintf(f, "\nFloating Point Registers:\n");
- for (i = 0; i < TARGET_FPREGS; i++) {
- if ((i & 3) == 0)
- cpu_fprintf(f, "%%f%02d:", i);
- cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]);
- if ((i & 3) == 3)
- cpu_fprintf(f, "\n");
- }
-#ifdef TARGET_SPARC64
- cpu_fprintf(f, "pstate: %08x ccr: %02x (icc: ", env->pstate,
- (unsigned)cpu_get_ccr(env));
- cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << PSR_CARRY_SHIFT);
- cpu_fprintf(f, " xcc: ");
- cpu_print_cc(f, cpu_fprintf, cpu_get_ccr(env) << (PSR_CARRY_SHIFT - 4));
- cpu_fprintf(f, ") asi: %02x tl: %d pil: %x\n", env->asi, env->tl,
- env->psrpil);
- cpu_fprintf(f, "cansave: %d canrestore: %d otherwin: %d wstate: %d "
- "cleanwin: %d cwp: %d\n",
- env->cansave, env->canrestore, env->otherwin, env->wstate,
- env->cleanwin, env->nwindows - 1 - env->cwp);
- cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx " fprs: "
- TARGET_FMT_lx "\n", env->fsr, env->y, env->fprs);
-#else
- cpu_fprintf(f, "psr: %08x (icc: ", cpu_get_psr(env));
- cpu_print_cc(f, cpu_fprintf, cpu_get_psr(env));
- cpu_fprintf(f, " SPE: %c%c%c) wim: %08x\n", env->psrs? 'S' : '-',
- env->psrps? 'P' : '-', env->psret? 'E' : '-',
- env->wim);
- cpu_fprintf(f, "fsr: " TARGET_FMT_lx " y: " TARGET_FMT_lx "\n",
- env->fsr, env->y);
+#if !defined(CONFIG_USER_ONLY)
+ cpu_tick_set_limit(opaque, limit);
#endif
}
+#endif
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 2d36af3a31..57d0073f2b 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -16,8 +16,8 @@ DEF_HELPER_0(rdccr, tl)
DEF_HELPER_1(wrccr, void, tl)
DEF_HELPER_0(rdcwp, tl)
DEF_HELPER_1(wrcwp, void, tl)
-DEF_HELPER_2(array8, tl, tl, tl)
-DEF_HELPER_2(alignaddr, tl, tl, tl)
+DEF_HELPER_3(array8, tl, env, tl, tl)
+DEF_HELPER_3(alignaddr, tl, env, tl, tl)
DEF_HELPER_1(popc, tl, tl)
DEF_HELPER_3(ldda_asi, void, tl, int, int)
DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
@@ -32,7 +32,7 @@ DEF_HELPER_1(tick_get_count, i64, ptr)
DEF_HELPER_2(tick_set_limit, void, ptr, i64)
#endif
DEF_HELPER_2(check_align, void, tl, i32)
-DEF_HELPER_0(debug, void)
+DEF_HELPER_1(debug, void, env)
DEF_HELPER_0(save, void)
DEF_HELPER_0(restore, void)
DEF_HELPER_2(udiv, tl, tl, tl)
@@ -47,119 +47,119 @@ DEF_HELPER_2(stqf, void, tl, int)
DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
DEF_HELPER_4(st_asi, void, tl, i64, int, int)
#endif
-DEF_HELPER_1(ldfsr, void, i32)
-DEF_HELPER_0(check_ieee_exceptions, void)
-DEF_HELPER_0(clear_float_exceptions, void)
+DEF_HELPER_2(ldfsr, void, env, i32)
+DEF_HELPER_1(check_ieee_exceptions, void, env)
+DEF_HELPER_1(clear_float_exceptions, void, env)
DEF_HELPER_1(fabss, f32, f32)
-DEF_HELPER_1(fsqrts, f32, f32)
-DEF_HELPER_0(fsqrtd, void)
-DEF_HELPER_2(fcmps, void, f32, f32)
-DEF_HELPER_0(fcmpd, void)
-DEF_HELPER_2(fcmpes, void, f32, f32)
-DEF_HELPER_0(fcmped, void)
-DEF_HELPER_0(fsqrtq, void)
-DEF_HELPER_0(fcmpq, void)
-DEF_HELPER_0(fcmpeq, void)
+DEF_HELPER_2(fsqrts, f32, env, f32)
+DEF_HELPER_1(fsqrtd, void, env)
+DEF_HELPER_3(fcmps, void, env, f32, f32)
+DEF_HELPER_1(fcmpd, void, env)
+DEF_HELPER_3(fcmpes, void, env, f32, f32)
+DEF_HELPER_1(fcmped, void, env)
+DEF_HELPER_1(fsqrtq, void, env)
+DEF_HELPER_1(fcmpq, void, env)
+DEF_HELPER_1(fcmpeq, void, env)
#ifdef TARGET_SPARC64
-DEF_HELPER_1(ldxfsr, void, i64)
-DEF_HELPER_0(fabsd, void)
-DEF_HELPER_2(fcmps_fcc1, void, f32, f32)
-DEF_HELPER_2(fcmps_fcc2, void, f32, f32)
-DEF_HELPER_2(fcmps_fcc3, void, f32, f32)
-DEF_HELPER_0(fcmpd_fcc1, void)
-DEF_HELPER_0(fcmpd_fcc2, void)
-DEF_HELPER_0(fcmpd_fcc3, void)
-DEF_HELPER_2(fcmpes_fcc1, void, f32, f32)
-DEF_HELPER_2(fcmpes_fcc2, void, f32, f32)
-DEF_HELPER_2(fcmpes_fcc3, void, f32, f32)
-DEF_HELPER_0(fcmped_fcc1, void)
-DEF_HELPER_0(fcmped_fcc2, void)
-DEF_HELPER_0(fcmped_fcc3, void)
-DEF_HELPER_0(fabsq, void)
-DEF_HELPER_0(fcmpq_fcc1, void)
-DEF_HELPER_0(fcmpq_fcc2, void)
-DEF_HELPER_0(fcmpq_fcc3, void)
-DEF_HELPER_0(fcmpeq_fcc1, void)
-DEF_HELPER_0(fcmpeq_fcc2, void)
-DEF_HELPER_0(fcmpeq_fcc3, void)
+DEF_HELPER_2(ldxfsr, void, env, i64)
+DEF_HELPER_1(fabsd, void, env)
+DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32)
+DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32)
+DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32)
+DEF_HELPER_1(fcmpd_fcc1, void, env)
+DEF_HELPER_1(fcmpd_fcc2, void, env)
+DEF_HELPER_1(fcmpd_fcc3, void, env)
+DEF_HELPER_3(fcmpes_fcc1, void, env, f32, f32)
+DEF_HELPER_3(fcmpes_fcc2, void, env, f32, f32)
+DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32)
+DEF_HELPER_1(fcmped_fcc1, void, env)
+DEF_HELPER_1(fcmped_fcc2, void, env)
+DEF_HELPER_1(fcmped_fcc3, void, env)
+DEF_HELPER_1(fabsq, void, env)
+DEF_HELPER_1(fcmpq_fcc1, void, env)
+DEF_HELPER_1(fcmpq_fcc2, void, env)
+DEF_HELPER_1(fcmpq_fcc3, void, env)
+DEF_HELPER_1(fcmpeq_fcc1, void, env)
+DEF_HELPER_1(fcmpeq_fcc2, void, env)
+DEF_HELPER_1(fcmpeq_fcc3, void, env)
#endif
-DEF_HELPER_1(raise_exception, void, int)
+DEF_HELPER_2(raise_exception, void, env, int)
DEF_HELPER_0(shutdown, void)
-#define F_HELPER_0_0(name) DEF_HELPER_0(f ## name, void)
-#define F_HELPER_DQ_0_0(name) \
- F_HELPER_0_0(name ## d); \
- F_HELPER_0_0(name ## q)
+#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
+#define F_HELPER_DQ_0_1(name) \
+ F_HELPER_0_1(name ## d); \
+ F_HELPER_0_1(name ## q)
-F_HELPER_DQ_0_0(add);
-F_HELPER_DQ_0_0(sub);
-F_HELPER_DQ_0_0(mul);
-F_HELPER_DQ_0_0(div);
+F_HELPER_DQ_0_1(add);
+F_HELPER_DQ_0_1(sub);
+F_HELPER_DQ_0_1(mul);
+F_HELPER_DQ_0_1(div);
-DEF_HELPER_2(fadds, f32, f32, f32)
-DEF_HELPER_2(fsubs, f32, f32, f32)
-DEF_HELPER_2(fmuls, f32, f32, f32)
-DEF_HELPER_2(fdivs, f32, f32, f32)
+DEF_HELPER_3(fadds, f32, env, f32, f32)
+DEF_HELPER_3(fsubs, f32, env, f32, f32)
+DEF_HELPER_3(fmuls, f32, env, f32, f32)
+DEF_HELPER_3(fdivs, f32, env, f32, f32)
-DEF_HELPER_2(fsmuld, void, f32, f32)
-F_HELPER_0_0(dmulq);
+DEF_HELPER_3(fsmuld, void, env, f32, f32)
+F_HELPER_0_1(dmulq);
DEF_HELPER_1(fnegs, f32, f32)
-DEF_HELPER_1(fitod, void, s32)
-DEF_HELPER_1(fitoq, void, s32)
+DEF_HELPER_2(fitod, void, env, s32)
+DEF_HELPER_2(fitoq, void, env, s32)
-DEF_HELPER_1(fitos, f32, s32)
+DEF_HELPER_2(fitos, f32, env, s32)
#ifdef TARGET_SPARC64
-DEF_HELPER_0(fnegd, void)
-DEF_HELPER_0(fnegq, void)
-DEF_HELPER_0(fxtos, i32)
-F_HELPER_DQ_0_0(xto);
+DEF_HELPER_1(fnegd, void, env)
+DEF_HELPER_1(fnegq, void, env)
+DEF_HELPER_1(fxtos, i32, env)
+F_HELPER_DQ_0_1(xto);
#endif
-DEF_HELPER_0(fdtos, f32)
-DEF_HELPER_1(fstod, void, f32)
-DEF_HELPER_0(fqtos, f32)
-DEF_HELPER_1(fstoq, void, f32)
-F_HELPER_0_0(qtod);
-F_HELPER_0_0(dtoq);
-DEF_HELPER_1(fstoi, s32, f32)
-DEF_HELPER_0(fdtoi, s32)
-DEF_HELPER_0(fqtoi, s32)
+DEF_HELPER_1(fdtos, f32, env)
+DEF_HELPER_2(fstod, void, env, f32)
+DEF_HELPER_1(fqtos, f32, env)
+DEF_HELPER_2(fstoq, void, env, f32)
+F_HELPER_0_1(qtod);
+F_HELPER_0_1(dtoq);
+DEF_HELPER_2(fstoi, s32, env, f32)
+DEF_HELPER_1(fdtoi, s32, env)
+DEF_HELPER_1(fqtoi, s32, env)
#ifdef TARGET_SPARC64
-DEF_HELPER_1(fstox, void, i32)
-F_HELPER_0_0(dtox);
-F_HELPER_0_0(qtox);
-F_HELPER_0_0(aligndata);
+DEF_HELPER_2(fstox, void, env, i32)
+F_HELPER_0_1(dtox);
+F_HELPER_0_1(qtox);
+F_HELPER_0_1(aligndata);
-F_HELPER_0_0(pmerge);
-F_HELPER_0_0(mul8x16);
-F_HELPER_0_0(mul8x16al);
-F_HELPER_0_0(mul8x16au);
-F_HELPER_0_0(mul8sux16);
-F_HELPER_0_0(mul8ulx16);
-F_HELPER_0_0(muld8sux16);
-F_HELPER_0_0(muld8ulx16);
-F_HELPER_0_0(expand);
+F_HELPER_0_1(pmerge);
+F_HELPER_0_1(mul8x16);
+F_HELPER_0_1(mul8x16al);
+F_HELPER_0_1(mul8x16au);
+F_HELPER_0_1(mul8sux16);
+F_HELPER_0_1(mul8ulx16);
+F_HELPER_0_1(muld8sux16);
+F_HELPER_0_1(muld8ulx16);
+F_HELPER_0_1(expand);
#define VIS_HELPER(name) \
- F_HELPER_0_0(name##16); \
- DEF_HELPER_2(f ## name ## 16s, i32, i32, i32) \
- F_HELPER_0_0(name##32); \
- DEF_HELPER_2(f ## name ## 32s, i32, i32, i32)
+ F_HELPER_0_1(name##16); \
+ DEF_HELPER_3(f ## name ## 16s, i32, env, i32, i32) \
+ F_HELPER_0_1(name##32); \
+ DEF_HELPER_3(f ## name ## 32s, i32, env, i32, i32)
VIS_HELPER(padd);
VIS_HELPER(psub);
#define VIS_CMPHELPER(name) \
- DEF_HELPER_0(f##name##16, i64); \
- DEF_HELPER_0(f##name##32, i64)
+ DEF_HELPER_1(f##name##16, i64, env); \
+ DEF_HELPER_1(f##name##32, i64, env)
VIS_CMPHELPER(cmpgt);
VIS_CMPHELPER(cmpeq);
VIS_CMPHELPER(cmple);
VIS_CMPHELPER(cmpne);
#endif
-#undef F_HELPER_0_0
-#undef F_HELPER_DQ_0_0
+#undef F_HELPER_0_1
+#undef F_HELPER_DQ_0_1
#undef VIS_HELPER
#undef VIS_CMPHELPER
-DEF_HELPER_0(compute_psr, void);
-DEF_HELPER_0(compute_C_icc, i32);
+DEF_HELPER_1(compute_psr, void, env);
+DEF_HELPER_1(compute_C_icc, i32, env);
#include "def-helper.h"
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
new file mode 100644
index 0000000000..219a6c64cd
--- /dev/null
+++ b/target-sparc/int32_helper.c
@@ -0,0 +1,125 @@
+/*
+ * Sparc32 interrupt helpers
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_PCALL
+
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_WIN_OVF] = "Window Overflow",
+ [TT_WIN_UNF] = "Window Underflow",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_NCP_INSN] = "Coprocessor Disabled",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+ int cwp, intno = env->exception_index;
+
+#ifdef DEBUG_PCALL
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ const char *name;
+
+ if (intno < 0 || intno >= 0x100) {
+ name = "Unknown";
+ } else if (intno >= 0x80) {
+ name = "Trap Instruction";
+ } else {
+ name = excp_names[intno];
+ if (!name) {
+ name = "Unknown";
+ }
+ }
+
+ qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
+ count, name, intno,
+ env->pc,
+ env->npc, env->regwptr[6]);
+ log_cpu_state(env, 0);
+#if 0
+ {
+ int i;
+ uint8_t *ptr;
+
+ qemu_log(" code=");
+ ptr = (uint8_t *)env->pc;
+ for (i = 0; i < 16; i++) {
+ qemu_log(" %02x", ldub(ptr + i));
+ }
+ qemu_log("\n");
+ }
+#endif
+ count++;
+ }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+ if (env->psret == 0) {
+ cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
+ env->exception_index);
+ return;
+ }
+#endif
+ env->psret = 0;
+ cwp = cpu_cwp_dec(env, env->cwp - 1);
+ cpu_set_cwp(env, cwp);
+ env->regwptr[9] = env->pc;
+ env->regwptr[10] = env->npc;
+ env->psrps = env->psrs;
+ env->psrs = 1;
+ env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
+ env->pc = env->tbr;
+ env->npc = env->pc + 4;
+ env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+ /* IRQ acknowledgment */
+ if ((intno & ~15) == TT_EXTINT && env->qemu_irq_ack != NULL) {
+ env->qemu_irq_ack(env->irq_manager, intno);
+ }
+#endif
+}
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
new file mode 100644
index 0000000000..2bb1910ed9
--- /dev/null
+++ b/target-sparc/int64_helper.c
@@ -0,0 +1,164 @@
+/*
+ * Sparc64 interrupt helpers
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+//#define DEBUG_PCALL
+
+#ifdef DEBUG_PCALL
+static const char * const excp_names[0x80] = {
+ [TT_TFAULT] = "Instruction Access Fault",
+ [TT_TMISS] = "Instruction Access MMU Miss",
+ [TT_CODE_ACCESS] = "Instruction Access Error",
+ [TT_ILL_INSN] = "Illegal Instruction",
+ [TT_PRIV_INSN] = "Privileged Instruction",
+ [TT_NFPU_INSN] = "FPU Disabled",
+ [TT_FP_EXCP] = "FPU Exception",
+ [TT_TOVF] = "Tag Overflow",
+ [TT_CLRWIN] = "Clean Windows",
+ [TT_DIV_ZERO] = "Division By Zero",
+ [TT_DFAULT] = "Data Access Fault",
+ [TT_DMISS] = "Data Access MMU Miss",
+ [TT_DATA_ACCESS] = "Data Access Error",
+ [TT_DPROT] = "Data Protection Error",
+ [TT_UNALIGNED] = "Unaligned Memory Access",
+ [TT_PRIV_ACT] = "Privileged Action",
+ [TT_EXTINT | 0x1] = "External Interrupt 1",
+ [TT_EXTINT | 0x2] = "External Interrupt 2",
+ [TT_EXTINT | 0x3] = "External Interrupt 3",
+ [TT_EXTINT | 0x4] = "External Interrupt 4",
+ [TT_EXTINT | 0x5] = "External Interrupt 5",
+ [TT_EXTINT | 0x6] = "External Interrupt 6",
+ [TT_EXTINT | 0x7] = "External Interrupt 7",
+ [TT_EXTINT | 0x8] = "External Interrupt 8",
+ [TT_EXTINT | 0x9] = "External Interrupt 9",
+ [TT_EXTINT | 0xa] = "External Interrupt 10",
+ [TT_EXTINT | 0xb] = "External Interrupt 11",
+ [TT_EXTINT | 0xc] = "External Interrupt 12",
+ [TT_EXTINT | 0xd] = "External Interrupt 13",
+ [TT_EXTINT | 0xe] = "External Interrupt 14",
+ [TT_EXTINT | 0xf] = "External Interrupt 15",
+};
+#endif
+
+void do_interrupt(CPUState *env)
+{
+ int intno = env->exception_index;
+ trap_state *tsptr;
+
+#ifdef DEBUG_PCALL
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ const char *name;
+
+ if (intno < 0 || intno >= 0x180) {
+ name = "Unknown";
+ } else if (intno >= 0x100) {
+ name = "Trap Instruction";
+ } else if (intno >= 0xc0) {
+ name = "Window Fill";
+ } else if (intno >= 0x80) {
+ name = "Window Spill";
+ } else {
+ name = excp_names[intno];
+ if (!name) {
+ name = "Unknown";
+ }
+ }
+
+ qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
+ " SP=%016" PRIx64 "\n",
+ count, name, intno,
+ env->pc,
+ env->npc, env->regwptr[6]);
+ log_cpu_state(env, 0);
+#if 0
+ {
+ int i;
+ uint8_t *ptr;
+
+ qemu_log(" code=");
+ ptr = (uint8_t *)env->pc;
+ for (i = 0; i < 16; i++) {
+ qemu_log(" %02x", ldub(ptr + i));
+ }
+ qemu_log("\n");
+ }
+#endif
+ count++;
+ }
+#endif
+#if !defined(CONFIG_USER_ONLY)
+ if (env->tl >= env->maxtl) {
+ cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
+ " Error state", env->exception_index, env->tl, env->maxtl);
+ return;
+ }
+#endif
+ if (env->tl < env->maxtl - 1) {
+ env->tl++;
+ } else {
+ env->pstate |= PS_RED;
+ if (env->tl < env->maxtl) {
+ env->tl++;
+ }
+ }
+ tsptr = cpu_tsptr(env);
+
+ tsptr->tstate = (cpu_get_ccr(env) << 32) |
+ ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+ cpu_get_cwp64(env);
+ tsptr->tpc = env->pc;
+ tsptr->tnpc = env->npc;
+ tsptr->tt = intno;
+
+ switch (intno) {
+ case TT_IVEC:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_IG);
+ break;
+ case TT_TFAULT:
+ case TT_DFAULT:
+ case TT_TMISS ... TT_TMISS + 3:
+ case TT_DMISS ... TT_DMISS + 3:
+ case TT_DPROT ... TT_DPROT + 3:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_MG);
+ break;
+ default:
+ cpu_change_pstate(env, PS_PEF | PS_PRIV | PS_AG);
+ break;
+ }
+
+ if (intno == TT_CLRWIN) {
+ cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
+ } else if ((intno & 0x1c0) == TT_SPILL) {
+ cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
+ } else if ((intno & 0x1c0) == TT_FILL) {
+ cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
+ }
+ env->tbr &= ~0x7fffULL;
+ env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
+ env->pc = env->tbr;
+ env->npc = env->pc + 4;
+ env->exception_index = -1;
+}
+
+trap_state *cpu_tsptr(CPUState* env)
+{
+ return &env->ts[env->tl & MAXTL_MASK];
+}
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 1cb0636c30..cb0bf2e2a6 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1,8 +1,6 @@
#include "cpu.h"
#include "dyngen-exec.h"
-#include "host-utils.h"
#include "helper.h"
-#include "sysemu.h"
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
@@ -13,7 +11,6 @@
//#define DEBUG_UNALIGNED
//#define DEBUG_UNASSIGNED
//#define DEBUG_ASI
-//#define DEBUG_PCALL
//#define DEBUG_PSTATE
//#define DEBUG_CACHE_CONTROL
@@ -37,14 +34,14 @@
#endif
#ifdef DEBUG_PSTATE
-#define DPRINTF_PSTATE(fmt, ...) \
+#define DPRINTF_PSTATE(fmt, ...) \
do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
#endif
#ifdef DEBUG_CACHE_CONTROL
-#define DPRINTF_CACHE_CONTROL(fmt, ...) \
+#define DPRINTF_CACHE_CONTROL(fmt, ...) \
do { printf("CACHE_CONTROL: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF_CACHE_CONTROL(fmt, ...) do {} while (0)
@@ -95,7 +92,7 @@ static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
#endif
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
-// Calculates TSB pointer value for fault page size 8k or 64k
+/* Calculates TSB pointer value for fault page size 8k or 64k */
static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
uint64_t tag_access_register,
int page_size)
@@ -104,14 +101,14 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
int tsb_size = tsb_register & 0xf;
- // discard lower 13 bits which hold tag access context
+ /* discard lower 13 bits which hold tag access context */
uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
- // now reorder bits
+ /* now reorder bits */
uint64_t tsb_base_mask = ~0x1fffULL;
uint64_t va = tag_access_va;
- // move va bits to correct position
+ /* move va bits to correct position */
if (page_size == 8*1024) {
va >>= 9;
} else if (page_size == 64*1024) {
@@ -122,7 +119,7 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
tsb_base_mask <<= tsb_size;
}
- // calculate tsb_base mask and adjust va if split is in use
+ /* calculate tsb_base mask and adjust va if split is in use */
if (tsb_split) {
if (page_size == 8*1024) {
va &= ~(1ULL << (13 + tsb_size));
@@ -135,8 +132,8 @@ static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
}
-// Calculates tag target register value by reordering bits
-// in tag access register
+/* Calculates tag target register value by reordering bits
+ in tag access register */
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
{
return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
@@ -148,7 +145,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
{
target_ulong mask, size, va, offset;
- // flush page range if translation is valid
+ /* flush page range if translation is valid */
if (TTE_IS_VALID(tlb->tte)) {
mask = 0xffffffffffffe000ULL;
@@ -167,7 +164,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
}
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
- const char* strmmu, CPUState *env1)
+ const char *strmmu, CPUState *env1)
{
unsigned int i;
target_ulong mask;
@@ -175,18 +172,18 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
int is_demap_context = (demap_addr >> 6) & 1;
- // demap context
+ /* demap context */
switch ((demap_addr >> 4) & 3) {
- case 0: // primary
+ case 0: /* primary */
context = env1->dmmu.mmu_primary_context;
break;
- case 1: // secondary
+ case 1: /* secondary */
context = env1->dmmu.mmu_secondary_context;
break;
- case 2: // nucleus
+ case 2: /* nucleus */
context = 0;
break;
- case 3: // reserved
+ case 3: /* reserved */
default:
return;
}
@@ -195,14 +192,14 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
if (TTE_IS_VALID(tlb[i].tte)) {
if (is_demap_context) {
- // will remove non-global entries matching context value
+ /* will remove non-global entries matching context value */
if (TTE_IS_GLOBAL(tlb[i].tte) ||
!tlb_compare_context(&tlb[i], context)) {
continue;
}
} else {
- // demap page
- // will remove any entry matching VA
+ /* demap page
+ will remove any entry matching VA */
mask = 0xffffffffffffe000ULL;
mask <<= 3 * ((tlb[i].tte >> 61) & 3);
@@ -210,7 +207,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
continue;
}
- // entry should be global or matching context value
+ /* entry should be global or matching context value */
if (!TTE_IS_GLOBAL(tlb[i].tte) &&
!tlb_compare_context(&tlb[i], context)) {
continue;
@@ -228,11 +225,11 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
uint64_t tlb_tag, uint64_t tlb_tte,
- const char* strmmu, CPUState *env1)
+ const char *strmmu, CPUState *env1)
{
unsigned int i, replace_used;
- // Try replacing invalid entry
+ /* Try replacing invalid entry */
for (i = 0; i < 64; i++) {
if (!TTE_IS_VALID(tlb[i].tte)) {
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
@@ -244,11 +241,11 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
}
}
- // All entries are valid, try replacing unlocked entry
+ /* All entries are valid, try replacing unlocked entry */
for (replace_used = 0; replace_used < 2; ++replace_used) {
- // Used entries are not replaced on first pass
+ /* Used entries are not replaced on first pass */
for (i = 0; i < 64; i++) {
if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
@@ -256,14 +253,14 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
- strmmu, (replace_used?"used":"unused"), i);
+ strmmu, (replace_used ? "used" : "unused"), i);
dump_mmu(stdout, fprintf, env1);
#endif
return;
}
}
- // Now reset used bit and search for unused entries again
+ /* Now reset used bit and search for unused entries again */
for (i = 0; i < 64; i++) {
TTE_SET_UNUSED(tlb[i].tte);
@@ -273,7 +270,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
#endif
- // error state?
+ /* error state? */
}
#endif
@@ -281,8 +278,9 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
{
#ifdef TARGET_SPARC64
- if (AM_CHECK(env1))
+ if (AM_CHECK(env1)) {
addr &= 0xffffffffULL;
+ }
#endif
return addr;
}
@@ -294,7 +292,7 @@ static inline int is_translating_asi(int asi)
#ifdef TARGET_SPARC64
/* Ultrasparc IIi translating asi
- note this list is defined by cpu implementation
- */
+ */
switch (asi) {
case 0x04 ... 0x11:
case 0x16 ... 0x19:
@@ -324,1298 +322,18 @@ static inline target_ulong asi_address_mask(CPUState *env1,
}
}
-static void raise_exception(int tt)
-{
- env->exception_index = tt;
- cpu_loop_exit(env);
-}
-
-void HELPER(raise_exception)(int tt)
-{
- raise_exception(tt);
-}
-
-void helper_shutdown(void)
-{
-#if !defined(CONFIG_USER_ONLY)
- qemu_system_shutdown_request();
-#endif
-}
-
void helper_check_align(target_ulong addr, uint32_t align)
{
if (addr & align) {
#ifdef DEBUG_UNALIGNED
- printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
- "\n", addr, env->pc);
-#endif
- raise_exception(TT_UNALIGNED);
- }
-}
-
-#define F_HELPER(name, p) void helper_f##name##p(void)
-
-#define F_BINOP(name) \
- float32 helper_f ## name ## s (float32 src1, float32 src2) \
- { \
- return float32_ ## name (src1, src2, &env->fp_status); \
- } \
- F_HELPER(name, d) \
- { \
- DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
- } \
- F_HELPER(name, q) \
- { \
- QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
- }
-
-F_BINOP(add);
-F_BINOP(sub);
-F_BINOP(mul);
-F_BINOP(div);
-#undef F_BINOP
-
-void helper_fsmuld(float32 src1, float32 src2)
-{
- DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
- float32_to_float64(src2, &env->fp_status),
- &env->fp_status);
-}
-
-void helper_fdmulq(void)
-{
- QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
- float64_to_float128(DT1, &env->fp_status),
- &env->fp_status);
-}
-
-float32 helper_fnegs(float32 src)
-{
- return float32_chs(src);
-}
-
-#ifdef TARGET_SPARC64
-F_HELPER(neg, d)
-{
- DT0 = float64_chs(DT1);
-}
-
-F_HELPER(neg, q)
-{
- QT0 = float128_chs(QT1);
-}
-#endif
-
-/* Integer to float conversion. */
-float32 helper_fitos(int32_t src)
-{
- return int32_to_float32(src, &env->fp_status);
-}
-
-void helper_fitod(int32_t src)
-{
- DT0 = int32_to_float64(src, &env->fp_status);
-}
-
-void helper_fitoq(int32_t src)
-{
- QT0 = int32_to_float128(src, &env->fp_status);
-}
-
-#ifdef TARGET_SPARC64
-float32 helper_fxtos(void)
-{
- return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
-}
-
-F_HELPER(xto, d)
-{
- DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
-}
-
-F_HELPER(xto, q)
-{
- QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
-}
-#endif
-#undef F_HELPER
-
-/* floating point conversion */
-float32 helper_fdtos(void)
-{
- return float64_to_float32(DT1, &env->fp_status);
-}
-
-void helper_fstod(float32 src)
-{
- DT0 = float32_to_float64(src, &env->fp_status);
-}
-
-float32 helper_fqtos(void)
-{
- return float128_to_float32(QT1, &env->fp_status);
-}
-
-void helper_fstoq(float32 src)
-{
- QT0 = float32_to_float128(src, &env->fp_status);
-}
-
-void helper_fqtod(void)
-{
- DT0 = float128_to_float64(QT1, &env->fp_status);
-}
-
-void helper_fdtoq(void)
-{
- QT0 = float64_to_float128(DT1, &env->fp_status);
-}
-
-/* Float to integer conversion. */
-int32_t helper_fstoi(float32 src)
-{
- return float32_to_int32_round_to_zero(src, &env->fp_status);
-}
-
-int32_t helper_fdtoi(void)
-{
- return float64_to_int32_round_to_zero(DT1, &env->fp_status);
-}
-
-int32_t helper_fqtoi(void)
-{
- return float128_to_int32_round_to_zero(QT1, &env->fp_status);
-}
-
-#ifdef TARGET_SPARC64
-void helper_fstox(float32 src)
-{
- *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
-}
-
-void helper_fdtox(void)
-{
- *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
-}
-
-void helper_fqtox(void)
-{
- *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
-}
-
-void helper_faligndata(void)
-{
- uint64_t tmp;
-
- tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
- /* on many architectures a shift of 64 does nothing */
- if ((env->gsr & 7) != 0) {
- tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
- }
- *((uint64_t *)&DT0) = tmp;
-}
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define VIS_B64(n) b[7 - (n)]
-#define VIS_W64(n) w[3 - (n)]
-#define VIS_SW64(n) sw[3 - (n)]
-#define VIS_L64(n) l[1 - (n)]
-#define VIS_B32(n) b[3 - (n)]
-#define VIS_W32(n) w[1 - (n)]
-#else
-#define VIS_B64(n) b[n]
-#define VIS_W64(n) w[n]
-#define VIS_SW64(n) sw[n]
-#define VIS_L64(n) l[n]
-#define VIS_B32(n) b[n]
-#define VIS_W32(n) w[n]
-#endif
-
-typedef union {
- uint8_t b[8];
- uint16_t w[4];
- int16_t sw[4];
- uint32_t l[2];
- uint64_t ll;
- float64 d;
-} vis64;
-
-typedef union {
- uint8_t b[4];
- uint16_t w[2];
- uint32_t l;
- float32 f;
-} vis32;
-
-void helper_fpmerge(void)
-{
- vis64 s, d;
-
- s.d = DT0;
- d.d = DT1;
-
- // Reverse calculation order to handle overlap
- d.VIS_B64(7) = s.VIS_B64(3);
- d.VIS_B64(6) = d.VIS_B64(3);
- d.VIS_B64(5) = s.VIS_B64(2);
- d.VIS_B64(4) = d.VIS_B64(2);
- d.VIS_B64(3) = s.VIS_B64(1);
- d.VIS_B64(2) = d.VIS_B64(1);
- d.VIS_B64(1) = s.VIS_B64(0);
- //d.VIS_B64(0) = d.VIS_B64(0);
-
- DT0 = d.d;
-}
-
-void helper_fmul8x16(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_W64(r) = tmp >> 8;
-
- PMUL(0);
- PMUL(1);
- PMUL(2);
- PMUL(3);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmul8x16al(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_W64(r) = tmp >> 8;
-
- PMUL(0);
- PMUL(1);
- PMUL(2);
- PMUL(3);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmul8x16au(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_W64(r) = tmp >> 8;
-
- PMUL(0);
- PMUL(1);
- PMUL(2);
- PMUL(3);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmul8sux16(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_W64(r) = tmp >> 8;
-
- PMUL(0);
- PMUL(1);
- PMUL(2);
- PMUL(3);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmul8ulx16(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_W64(r) = tmp >> 8;
-
- PMUL(0);
- PMUL(1);
- PMUL(2);
- PMUL(3);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmuld8sux16(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_L64(r) = tmp;
-
- // Reverse calculation order to handle overlap
- PMUL(1);
- PMUL(0);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fmuld8ulx16(void)
-{
- vis64 s, d;
- uint32_t tmp;
-
- s.d = DT0;
- d.d = DT1;
-
-#define PMUL(r) \
- tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
- if ((tmp & 0xff) > 0x7f) \
- tmp += 0x100; \
- d.VIS_L64(r) = tmp;
-
- // Reverse calculation order to handle overlap
- PMUL(1);
- PMUL(0);
-#undef PMUL
-
- DT0 = d.d;
-}
-
-void helper_fexpand(void)
-{
- vis32 s;
- vis64 d;
-
- s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
- d.d = DT1;
- d.VIS_W64(0) = s.VIS_B32(0) << 4;
- d.VIS_W64(1) = s.VIS_B32(1) << 4;
- d.VIS_W64(2) = s.VIS_B32(2) << 4;
- d.VIS_W64(3) = s.VIS_B32(3) << 4;
-
- DT0 = d.d;
-}
-
-#define VIS_HELPER(name, F) \
- void name##16(void) \
- { \
- vis64 s, d; \
- \
- s.d = DT0; \
- d.d = DT1; \
- \
- d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
- d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
- d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
- d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
- \
- DT0 = d.d; \
- } \
- \
- uint32_t name##16s(uint32_t src1, uint32_t src2) \
- { \
- vis32 s, d; \
- \
- s.l = src1; \
- d.l = src2; \
- \
- d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
- d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
- \
- return d.l; \
- } \
- \
- void name##32(void) \
- { \
- vis64 s, d; \
- \
- s.d = DT0; \
- d.d = DT1; \
- \
- d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
- d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
- \
- DT0 = d.d; \
- } \
- \
- uint32_t name##32s(uint32_t src1, uint32_t src2) \
- { \
- vis32 s, d; \
- \
- s.l = src1; \
- d.l = src2; \
- \
- d.l = F(d.l, s.l); \
- \
- return d.l; \
- }
-
-#define FADD(a, b) ((a) + (b))
-#define FSUB(a, b) ((a) - (b))
-VIS_HELPER(helper_fpadd, FADD)
-VIS_HELPER(helper_fpsub, FSUB)
-
-#define VIS_CMPHELPER(name, F) \
- uint64_t name##16(void) \
- { \
- vis64 s, d; \
- \
- s.d = DT0; \
- d.d = DT1; \
- \
- d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \
- d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \
- d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0; \
- d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0; \
- d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0; \
- \
- return d.ll; \
- } \
- \
- uint64_t name##32(void) \
- { \
- vis64 s, d; \
- \
- s.d = DT0; \
- d.d = DT1; \
- \
- d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \
- d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \
- d.VIS_L64(1) = 0; \
- \
- return d.ll; \
- }
-
-#define FCMPGT(a, b) ((a) > (b))
-#define FCMPEQ(a, b) ((a) == (b))
-#define FCMPLE(a, b) ((a) <= (b))
-#define FCMPNE(a, b) ((a) != (b))
-
-VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
-VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
-VIS_CMPHELPER(helper_fcmple, FCMPLE)
-VIS_CMPHELPER(helper_fcmpne, FCMPNE)
-#endif
-
-void helper_check_ieee_exceptions(void)
-{
- target_ulong status;
-
- status = get_float_exception_flags(&env->fp_status);
- if (status) {
- /* Copy IEEE 754 flags into FSR */
- if (status & float_flag_invalid)
- env->fsr |= FSR_NVC;
- if (status & float_flag_overflow)
- env->fsr |= FSR_OFC;
- if (status & float_flag_underflow)
- env->fsr |= FSR_UFC;
- if (status & float_flag_divbyzero)
- env->fsr |= FSR_DZC;
- if (status & float_flag_inexact)
- env->fsr |= FSR_NXC;
-
- if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
- /* Unmasked exception, generate a trap */
- env->fsr |= FSR_FTT_IEEE_EXCP;
- raise_exception(TT_FP_EXCP);
- } else {
- /* Accumulate exceptions */
- env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
- }
- }
-}
-
-void helper_clear_float_exceptions(void)
-{
- set_float_exception_flags(0, &env->fp_status);
-}
-
-float32 helper_fabss(float32 src)
-{
- return float32_abs(src);
-}
-
-#ifdef TARGET_SPARC64
-void helper_fabsd(void)
-{
- DT0 = float64_abs(DT1);
-}
-
-void helper_fabsq(void)
-{
- QT0 = float128_abs(QT1);
-}
-#endif
-
-float32 helper_fsqrts(float32 src)
-{
- return float32_sqrt(src, &env->fp_status);
-}
-
-void helper_fsqrtd(void)
-{
- DT0 = float64_sqrt(DT1, &env->fp_status);
-}
-
-void helper_fsqrtq(void)
-{
- QT0 = float128_sqrt(QT1, &env->fp_status);
-}
-
-#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
- void glue(helper_, name) (void) \
- { \
- env->fsr &= FSR_FTT_NMASK; \
- if (E && (glue(size, _is_any_nan)(reg1) || \
- glue(size, _is_any_nan)(reg2)) && \
- (env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- raise_exception(TT_FP_EXCP); \
- } \
- switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
- case float_relation_unordered: \
- if ((env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- raise_exception(TT_FP_EXCP); \
- } else { \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
- env->fsr |= FSR_NVA; \
- } \
- break; \
- case float_relation_less: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= FSR_FCC0 << FS; \
- break; \
- case float_relation_greater: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= FSR_FCC1 << FS; \
- break; \
- default: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- break; \
- } \
- }
-#define GEN_FCMPS(name, size, FS, E) \
- void glue(helper_, name)(float32 src1, float32 src2) \
- { \
- env->fsr &= FSR_FTT_NMASK; \
- if (E && (glue(size, _is_any_nan)(src1) || \
- glue(size, _is_any_nan)(src2)) && \
- (env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- raise_exception(TT_FP_EXCP); \
- } \
- switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
- case float_relation_unordered: \
- if ((env->fsr & FSR_NVM)) { \
- env->fsr |= FSR_NVC; \
- env->fsr |= FSR_FTT_IEEE_EXCP; \
- raise_exception(TT_FP_EXCP); \
- } else { \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
- env->fsr |= FSR_NVA; \
- } \
- break; \
- case float_relation_less: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= FSR_FCC0 << FS; \
- break; \
- case float_relation_greater: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- env->fsr |= FSR_FCC1 << FS; \
- break; \
- default: \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
- break; \
- } \
- }
-
-GEN_FCMPS(fcmps, float32, 0, 0);
-GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
-
-GEN_FCMPS(fcmpes, float32, 0, 1);
-GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
-
-GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
-GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
-
-static uint32_t compute_all_flags(void)
-{
- return env->psr & PSR_ICC;
-}
-
-static uint32_t compute_C_flags(void)
-{
- return env->psr & PSR_CARRY;
-}
-
-static inline uint32_t get_NZ_icc(int32_t dst)
-{
- uint32_t ret = 0;
-
- if (dst == 0) {
- ret = PSR_ZERO;
- } else if (dst < 0) {
- ret = PSR_NEG;
- }
- return ret;
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_flags_xcc(void)
-{
- return env->xcc & PSR_ICC;
-}
-
-static uint32_t compute_C_flags_xcc(void)
-{
- return env->xcc & PSR_CARRY;
-}
-
-static inline uint32_t get_NZ_xcc(target_long dst)
-{
- uint32_t ret = 0;
-
- if (!dst) {
- ret = PSR_ZERO;
- } else if (dst < 0) {
- ret = PSR_NEG;
- }
- return ret;
-}
-#endif
-
-static inline uint32_t get_V_div_icc(target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (src2 != 0) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-static uint32_t compute_all_div(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_V_div_icc(CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_div(void)
-{
- return 0;
-}
-
-static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
-{
- uint32_t ret = 0;
-
- if (dst < src1) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
- uint32_t src2)
-{
- uint32_t ret = 0;
-
- if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
- uint32_t src2)
-{
- uint32_t ret = 0;
-
- if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-#ifdef TARGET_SPARC64
-static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
-{
- uint32_t ret = 0;
-
- if (dst < src1) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-static uint32_t compute_all_add_xcc(void)
-{
- uint32_t ret;
-
- ret = get_NZ_xcc(CC_DST);
- ret |= get_C_add_xcc(CC_DST, CC_SRC);
- ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_add_xcc(void)
-{
- return get_C_add_xcc(CC_DST, CC_SRC);
-}
-#endif
-
-static uint32_t compute_all_add(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_add(void)
-{
- return get_C_add_icc(CC_DST, CC_SRC);
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_addx_xcc(void)
-{
- uint32_t ret;
-
- ret = get_NZ_xcc(CC_DST);
- ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_addx_xcc(void)
-{
- uint32_t ret;
-
- ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-#endif
-
-static uint32_t compute_all_addx(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_addx(void)
-{
- uint32_t ret;
-
- ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
-{
- uint32_t ret = 0;
-
- if ((src1 | src2) & 0x3) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-static uint32_t compute_all_tadd(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC);
- ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_all_taddtv(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC);
- return ret;
-}
-
-static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
-{
- uint32_t ret = 0;
-
- if (src1 < src2) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
- uint32_t src2)
-{
- uint32_t ret = 0;
-
- if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
- uint32_t src2)
-{
- uint32_t ret = 0;
-
- if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-
-#ifdef TARGET_SPARC64
-static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (src1 < src2) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
- ret = PSR_CARRY;
- }
- return ret;
-}
-
-static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
- target_ulong src2)
-{
- uint32_t ret = 0;
-
- if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
- ret = PSR_OVF;
- }
- return ret;
-}
-
-static uint32_t compute_all_sub_xcc(void)
-{
- uint32_t ret;
-
- ret = get_NZ_xcc(CC_DST);
- ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
- ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_sub_xcc(void)
-{
- return get_C_sub_xcc(CC_SRC, CC_SRC2);
-}
-#endif
-
-static uint32_t compute_all_sub(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
- ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_sub(void)
-{
- return get_C_sub_icc(CC_SRC, CC_SRC2);
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_subx_xcc(void)
-{
- uint32_t ret;
-
- ret = get_NZ_xcc(CC_DST);
- ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_subx_xcc(void)
-{
- uint32_t ret;
-
- ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-#endif
-
-static uint32_t compute_all_subx(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_C_subx(void)
-{
- uint32_t ret;
-
- ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_all_tsub(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
- ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_all_tsubtv(void)
-{
- uint32_t ret;
-
- ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
- return ret;
-}
-
-static uint32_t compute_all_logic(void)
-{
- return get_NZ_icc(CC_DST);
-}
-
-static uint32_t compute_C_logic(void)
-{
- return 0;
-}
-
-#ifdef TARGET_SPARC64
-static uint32_t compute_all_logic_xcc(void)
-{
- return get_NZ_xcc(CC_DST);
-}
-#endif
-
-typedef struct CCTable {
- uint32_t (*compute_all)(void); /* return all the flags */
- uint32_t (*compute_c)(void); /* return the C flag */
-} CCTable;
-
-static const CCTable icc_table[CC_OP_NB] = {
- /* CC_OP_DYNAMIC should never happen */
- [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
- [CC_OP_DIV] = { compute_all_div, compute_C_div },
- [CC_OP_ADD] = { compute_all_add, compute_C_add },
- [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
- [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
- [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
- [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
- [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
- [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
- [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
- [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
-};
-
-#ifdef TARGET_SPARC64
-static const CCTable xcc_table[CC_OP_NB] = {
- /* CC_OP_DYNAMIC should never happen */
- [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
- [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
- [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
- [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
- [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
- [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
- [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
- [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
- [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
- [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
- [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
-};
-#endif
-
-void helper_compute_psr(void)
-{
- uint32_t new_psr;
-
- new_psr = icc_table[CC_OP].compute_all();
- env->psr = new_psr;
-#ifdef TARGET_SPARC64
- new_psr = xcc_table[CC_OP].compute_all();
- env->xcc = new_psr;
+ printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
+ "\n", addr, env->pc);
#endif
- CC_OP = CC_OP_FLAGS;
-}
-
-uint32_t helper_compute_C_icc(void)
-{
- uint32_t ret;
-
- ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
- return ret;
-}
-
-static inline void memcpy32(target_ulong *dst, const target_ulong *src)
-{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = src[3];
- dst[4] = src[4];
- dst[5] = src[5];
- dst[6] = src[6];
- dst[7] = src[7];
-}
-
-static void set_cwp(int new_cwp)
-{
- /* put the modified wrap registers at their proper location */
- if (env->cwp == env->nwindows - 1) {
- memcpy32(env->regbase, env->regbase + env->nwindows * 16);
- }
- env->cwp = new_cwp;
-
- /* put the wrap registers at their temporary location */
- if (new_cwp == env->nwindows - 1) {
- memcpy32(env->regbase + env->nwindows * 16, env->regbase);
- }
- env->regwptr = env->regbase + (new_cwp * 16);
-}
-
-void cpu_set_cwp(CPUState *env1, int new_cwp)
-{
- CPUState *saved_env;
-
- saved_env = env;
- env = env1;
- set_cwp(new_cwp);
- env = saved_env;
-}
-
-static target_ulong get_psr(void)
-{
- helper_compute_psr();
-
-#if !defined (TARGET_SPARC64)
- return env->version | (env->psr & PSR_ICC) |
- (env->psref? PSR_EF : 0) |
- (env->psrpil << 8) |
- (env->psrs? PSR_S : 0) |
- (env->psrps? PSR_PS : 0) |
- (env->psret? PSR_ET : 0) | env->cwp;
-#else
- return env->psr & PSR_ICC;
-#endif
-}
-
-target_ulong cpu_get_psr(CPUState *env1)
-{
- CPUState *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = get_psr();
- env = saved_env;
- return ret;
-}
-
-static void put_psr(target_ulong val)
-{
- env->psr = val & PSR_ICC;
-#if !defined (TARGET_SPARC64)
- env->psref = (val & PSR_EF)? 1 : 0;
- env->psrpil = (val & PSR_PIL) >> 8;
-#endif
-#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
- cpu_check_irqs(env);
-#endif
-#if !defined (TARGET_SPARC64)
- env->psrs = (val & PSR_S)? 1 : 0;
- env->psrps = (val & PSR_PS)? 1 : 0;
- env->psret = (val & PSR_ET)? 1 : 0;
- set_cwp(val & PSR_CWP);
-#endif
- env->cc_op = CC_OP_FLAGS;
-}
-
-void cpu_put_psr(CPUState *env1, target_ulong val)
-{
- CPUState *saved_env;
-
- saved_env = env;
- env = env1;
- put_psr(val);
- env = saved_env;
-}
-
-static int cwp_inc(int cwp)
-{
- if (unlikely(cwp >= env->nwindows)) {
- cwp -= env->nwindows;
+ helper_raise_exception(env, TT_UNALIGNED);
}
- return cwp;
}
-int cpu_cwp_inc(CPUState *env1, int cwp)
-{
- CPUState *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = cwp_inc(cwp);
- env = saved_env;
- return ret;
-}
-
-static int cwp_dec(int cwp)
-{
- if (unlikely(cwp < 0)) {
- cwp += env->nwindows;
- }
- return cwp;
-}
-
-int cpu_cwp_dec(CPUState *env1, int cwp)
-{
- CPUState *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = cwp_dec(cwp);
- env = saved_env;
- return ret;
-}
-
-#ifdef TARGET_SPARC64
-GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
-GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
-GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
-
-GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
-GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
-GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
-
-GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
-GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
-GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
-
-GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
-GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
-GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
-
-GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
-GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
-GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
-
-GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
-GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
-GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
-#endif
-#undef GEN_FCMPS
-
-#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
defined(DEBUG_MXCC)
static void dump_mxcc(CPUState *env)
{
@@ -1634,13 +352,12 @@ static void dump_mxcc(CPUState *env)
}
#endif
-#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
+#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
&& defined(DEBUG_ASI)
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
uint64_t r1)
{
- switch (size)
- {
+ switch (size) {
case 1:
DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
addr, asi, r1 & 0xff);
@@ -1785,33 +502,37 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
break;
case 0x01c00a00: /* MXCC control register */
- if (size == 8)
+ if (size == 8) {
ret = env->mxccregs[3];
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00a04: /* MXCC control register */
- if (size == 4)
+ if (size == 4) {
ret = env->mxccregs[3];
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00c00: /* Module reset register */
if (size == 8) {
ret = env->mxccregs[5];
- // should we do something here?
- } else
+ /* should we do something here? */
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00f00: /* MBus port address register */
- if (size == 8)
+ if (size == 8) {
ret = env->mxccregs[7];
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
default:
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
@@ -1830,10 +551,11 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
int mmulev;
mmulev = (addr >> 8) & 15;
- if (mmulev > 4)
+ if (mmulev > 4) {
ret = 0;
- else
+ } else {
ret = mmu_probe(env, addr, mmulev);
+ }
DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
addr, mmulev, ret);
}
@@ -1843,21 +565,22 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
int reg = (addr >> 8) & 0x1f;
ret = env->mmuregs[reg];
- if (reg == 3) /* Fault status cleared on read */
+ if (reg == 3) { /* Fault status cleared on read */
env->mmuregs[3] = 0;
- else if (reg == 0x13) /* Fault status read */
+ } else if (reg == 0x13) { /* Fault status read */
ret = env->mmuregs[3];
- else if (reg == 0x14) /* Fault address read */
+ } else if (reg == 0x14) { /* Fault address read */
ret = env->mmuregs[4];
+ }
DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
}
break;
- case 5: // Turbosparc ITLB Diagnostic
- case 6: // Turbosparc DTLB Diagnostic
- case 7: // Turbosparc IOTLB Diagnostic
+ case 5: /* Turbosparc ITLB Diagnostic */
+ case 6: /* Turbosparc DTLB Diagnostic */
+ case 7: /* Turbosparc IOTLB Diagnostic */
break;
case 9: /* Supervisor code access */
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_code(addr);
break;
@@ -1874,7 +597,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
break;
case 0xa: /* User data access */
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_user(addr);
break;
@@ -1891,7 +614,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
break;
case 0xb: /* Supervisor data access */
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_kernel(addr);
break;
@@ -1913,7 +636,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0xf: /* D-cache data */
break;
case 0x20: /* MMU passthrough */
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_phys(addr);
break;
@@ -1930,7 +653,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
break;
case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_phys((target_phys_addr_t)addr
| ((target_phys_addr_t)(asi & 0xf) << 32));
@@ -1950,9 +673,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
}
break;
- case 0x30: // Turbosparc secondary cache diagnostic
- case 0x31: // Turbosparc RAM snoop
- case 0x32: // Turbosparc page table descriptor diagnostic
+ case 0x30: /* Turbosparc secondary cache diagnostic */
+ case 0x31: /* Turbosparc RAM snoop */
+ case 0x32: /* Turbosparc page table descriptor diagnostic */
case 0x39: /* data cache diagnostic register */
ret = 0;
break;
@@ -1960,7 +683,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
{
int reg = (addr >> 8) & 3;
- switch(reg) {
+ switch (reg) {
case 0: /* Breakpoint Value (Addr) */
ret = env->mmubpregs[reg];
break;
@@ -1998,7 +721,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
}
if (sign) {
- switch(size) {
+ switch (size) {
case 1:
ret = (int8_t) ret;
break;
@@ -2021,7 +744,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
{
helper_check_align(addr, size - 1);
- switch(asi) {
+ switch (asi) {
case 2: /* SuperSparc MXCC registers and Leon3 cache control */
switch (addr) {
case 0x00: /* Leon3 Cache Control */
@@ -2033,39 +756,44 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
break;
case 0x01c00000: /* MXCC stream data register 0 */
- if (size == 8)
+ if (size == 8) {
env->mxccdata[0] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00008: /* MXCC stream data register 1 */
- if (size == 8)
+ if (size == 8) {
env->mxccdata[1] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00010: /* MXCC stream data register 2 */
- if (size == 8)
+ if (size == 8) {
env->mxccdata[2] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00018: /* MXCC stream data register 3 */
- if (size == 8)
+ if (size == 8) {
env->mxccdata[3] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00100: /* MXCC stream source */
- if (size == 8)
+ if (size == 8) {
env->mxccregs[0] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
0);
env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
@@ -2076,11 +804,12 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
24);
break;
case 0x01c00200: /* MXCC stream destination */
- if (size == 8)
+ if (size == 8) {
env->mxccregs[1] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
env->mxccdata[0]);
stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
@@ -2091,34 +820,38 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
env->mxccdata[3]);
break;
case 0x01c00a00: /* MXCC control register */
- if (size == 8)
+ if (size == 8) {
env->mxccregs[3] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00a04: /* MXCC control register */
- if (size == 4)
+ if (size == 4) {
env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
| val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00e00: /* MXCC error register */
- // writing a 1 bit clears the error
- if (size == 8)
+ /* writing a 1 bit clears the error */
+ if (size == 8) {
env->mxccregs[6] &= ~val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
case 0x01c00f00: /* MBus port address register */
- if (size == 8)
+ if (size == 8) {
env->mxccregs[7] = val;
- else
+ } else {
DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
size);
+ }
break;
default:
DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
@@ -2138,13 +871,13 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
mmulev = (addr >> 8) & 15;
DPRINTF_MMU("mmu flush level %d\n", mmulev);
switch (mmulev) {
- case 0: // flush page
+ case 0: /* flush page */
tlb_flush_page(env, addr & 0xfffff000);
break;
- case 1: // flush segment (256k)
- case 2: // flush region (16M)
- case 3: // flush context (4G)
- case 4: // flush entire
+ case 1: /* flush segment (256k) */
+ case 2: /* flush region (16M) */
+ case 3: /* flush context (4G) */
+ case 4: /* flush entire */
tlb_flush(env, 1);
break;
default:
@@ -2161,20 +894,21 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
uint32_t oldreg;
oldreg = env->mmuregs[reg];
- switch(reg) {
- case 0: // Control Register
+ switch (reg) {
+ case 0: /* Control Register */
env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
- (val & 0x00ffffff);
- // Mappings generated during no-fault mode or MMU
- // disabled mode are invalid in normal mode
+ (val & 0x00ffffff);
+ /* Mappings generated during no-fault mode or MMU
+ disabled mode are invalid in normal mode */
if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
- (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
+ (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
tlb_flush(env, 1);
+ }
break;
- case 1: // Context Table Pointer Register
+ case 1: /* Context Table Pointer Register */
env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
break;
- case 2: // Context Register
+ case 2: /* Context Register */
env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
if (oldreg != env->mmuregs[reg]) {
/* we flush when the MMU context changes because
@@ -2182,16 +916,17 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
tlb_flush(env, 1);
}
break;
- case 3: // Synchronous Fault Status Register with Clear
- case 4: // Synchronous Fault Address Register
+ case 3: /* Synchronous Fault Status Register with Clear */
+ case 4: /* Synchronous Fault Address Register */
break;
- case 0x10: // TLB Replacement Control Register
+ case 0x10: /* TLB Replacement Control Register */
env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
break;
- case 0x13: // Synchronous Fault Status Register with Read and Clear
+ case 0x13: /* Synchronous Fault Status Register with Read
+ and Clear */
env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
break;
- case 0x14: // Synchronous Fault Address Register
+ case 0x14: /* Synchronous Fault Address Register */
env->mmuregs[4] = val;
break;
default:
@@ -2207,12 +942,12 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
#endif
}
break;
- case 5: // Turbosparc ITLB Diagnostic
- case 6: // Turbosparc DTLB Diagnostic
- case 7: // Turbosparc IOTLB Diagnostic
+ case 5: /* Turbosparc ITLB Diagnostic */
+ case 6: /* Turbosparc DTLB Diagnostic */
+ case 7: /* Turbosparc IOTLB Diagnostic */
break;
case 0xa: /* User data access */
- switch(size) {
+ switch (size) {
case 1:
stb_user(addr, val);
break;
@@ -2229,7 +964,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
}
break;
case 0xb: /* Supervisor data access */
- switch(size) {
+ switch (size) {
case 1:
stb_kernel(addr, val);
break;
@@ -2257,9 +992,9 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
break;
case 0x17: /* Block copy, sta access */
{
- // val = src
- // addr = dst
- // copy 32 bytes
+ /* val = src
+ addr = dst
+ copy 32 bytes */
unsigned int i;
uint32_t src = val & ~3, dst = addr & ~3, temp;
@@ -2271,18 +1006,19 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
break;
case 0x1f: /* Block fill, stda access */
{
- // addr = dst
- // fill 32 bytes with val
+ /* addr = dst
+ fill 32 bytes with val */
unsigned int i;
uint32_t dst = addr & 7;
- for (i = 0; i < 32; i += 8, dst += 8)
+ for (i = 0; i < 32; i += 8, dst += 8) {
stq_kernel(dst, val);
+ }
}
break;
case 0x20: /* MMU passthrough */
{
- switch(size) {
+ switch (size) {
case 1:
stb_phys(addr, val);
break;
@@ -2301,7 +1037,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
break;
case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
{
- switch(size) {
+ switch (size) {
case 1:
stb_phys((target_phys_addr_t)addr
| ((target_phys_addr_t)(asi & 0xf) << 32), val);
@@ -2322,11 +1058,11 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
}
}
break;
- case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
- case 0x31: // store buffer data, Ross RT620 I-cache flush or
- // Turbosparc snoop RAM
- case 0x32: // store buffer control or Turbosparc page table
- // descriptor diagnostic
+ case 0x30: /* store buffer tags or Turbosparc secondary cache diagnostic */
+ case 0x31: /* store buffer data, Ross RT620 I-cache flush or
+ Turbosparc snoop RAM */
+ case 0x32: /* store buffer control or Turbosparc page table
+ descriptor diagnostic */
case 0x36: /* I-cache flash clear */
case 0x37: /* D-cache flash clear */
break;
@@ -2334,7 +1070,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
{
int reg = (addr >> 8) & 3;
- switch(reg) {
+ switch (reg) {
case 0: /* Breakpoint Value (Addr) */
env->mmubpregs[reg] = (val & 0xfffffffffULL);
break;
@@ -2386,26 +1122,27 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
target_ulong last_addr = addr;
#endif
- if (asi < 0x80)
- raise_exception(TT_PRIV_ACT);
+ if (asi < 0x80) {
+ helper_raise_exception(env, TT_PRIV_ACT);
+ }
helper_check_align(addr, size - 1);
addr = asi_address_mask(env, asi, addr);
switch (asi) {
- case 0x82: // Primary no-fault
- case 0x8a: // Primary no-fault LE
+ case 0x82: /* Primary no-fault */
+ case 0x8a: /* Primary no-fault LE */
if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
dump_asi("read ", last_addr, asi, size, ret);
#endif
return 0;
}
- // Fall through
- case 0x80: // Primary
- case 0x88: // Primary LE
+ /* Fall through */
+ case 0x80: /* Primary */
+ case 0x88: /* Primary LE */
{
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_raw(addr);
break;
@@ -2422,18 +1159,18 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
}
break;
- case 0x83: // Secondary no-fault
- case 0x8b: // Secondary no-fault LE
+ case 0x83: /* Secondary no-fault */
+ case 0x8b: /* Secondary no-fault LE */
if (page_check_range(addr, size, PAGE_READ) == -1) {
#ifdef DEBUG_ASI
dump_asi("read ", last_addr, asi, size, ret);
#endif
return 0;
}
- // Fall through
- case 0x81: // Secondary
- case 0x89: // Secondary LE
- // XXX
+ /* Fall through */
+ case 0x81: /* Secondary */
+ case 0x89: /* Secondary LE */
+ /* XXX */
break;
default:
break;
@@ -2441,11 +1178,11 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
/* Convert from little endian */
switch (asi) {
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
- case 0x8a: // Primary no-fault LE
- case 0x8b: // Secondary no-fault LE
- switch(size) {
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
+ case 0x8a: /* Primary no-fault LE */
+ case 0x8b: /* Secondary no-fault LE */
+ switch (size) {
case 2:
ret = bswap16(ret);
break;
@@ -2464,7 +1201,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
/* Convert to signed number */
if (sign) {
- switch(size) {
+ switch (size) {
case 1:
ret = (int8_t) ret;
break;
@@ -2489,17 +1226,18 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#ifdef DEBUG_ASI
dump_asi("write", addr, asi, size, val);
#endif
- if (asi < 0x80)
- raise_exception(TT_PRIV_ACT);
+ if (asi < 0x80) {
+ helper_raise_exception(env, TT_PRIV_ACT);
+ }
helper_check_align(addr, size - 1);
addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
switch (asi) {
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
- switch(size) {
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
+ switch (size) {
case 2:
val = bswap16(val);
break;
@@ -2516,11 +1254,11 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
break;
}
- switch(asi) {
- case 0x80: // Primary
- case 0x88: // Primary LE
+ switch (asi) {
+ case 0x80: /* Primary */
+ case 0x88: /* Primary LE */
{
- switch(size) {
+ switch (size) {
case 1:
stb_raw(addr, val);
break;
@@ -2537,15 +1275,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
}
}
break;
- case 0x81: // Secondary
- case 0x89: // Secondary LE
- // XXX
+ case 0x81: /* Secondary */
+ case 0x89: /* Secondary LE */
+ /* XXX */
return;
- case 0x82: // Primary no-fault, RO
- case 0x83: // Secondary no-fault, RO
- case 0x8a: // Primary no-fault LE, RO
- case 0x8b: // Secondary no-fault LE, RO
+ case 0x82: /* Primary no-fault, RO */
+ case 0x83: /* Secondary no-fault, RO */
+ case 0x8a: /* Primary no-fault LE, RO */
+ case 0x8b: /* Secondary no-fault LE, RO */
default:
do_unassigned_access(addr, 1, 0, 1, size);
return;
@@ -2566,8 +1304,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
- && !(env->hpstate & HS_PRIV)))
- raise_exception(TT_PRIV_ACT);
+ && !(env->hpstate & HS_PRIV))) {
+ helper_raise_exception(env, TT_PRIV_ACT);
+ }
helper_check_align(addr, size - 1);
addr = asi_address_mask(env, asi, addr);
@@ -2588,7 +1327,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
dump_asi("read ", last_addr, asi, size, ret);
#endif
/* env->exception_index is set in get_physical_address_data(). */
- raise_exception(env->exception_index);
+ helper_raise_exception(env, env->exception_index);
}
/* convert nonfaulting load ASIs to normal load ASIs */
@@ -2596,19 +1335,19 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
switch (asi) {
- case 0x10: // As if user primary
- case 0x11: // As if user secondary
- case 0x18: // As if user primary LE
- case 0x19: // As if user secondary LE
- case 0x80: // Primary
- case 0x81: // Secondary
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
- case 0xe2: // UA2007 Primary block init
- case 0xe3: // UA2007 Secondary block init
+ case 0x10: /* As if user primary */
+ case 0x11: /* As if user secondary */
+ case 0x18: /* As if user primary LE */
+ case 0x19: /* As if user secondary LE */
+ case 0x80: /* Primary */
+ case 0x81: /* Secondary */
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
+ case 0xe2: /* UA2007 Primary block init */
+ case 0xe3: /* UA2007 Secondary block init */
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
if (cpu_hypervisor_mode(env)) {
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_hypv(addr);
break;
@@ -2626,7 +1365,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
} else {
/* secondary space access has lowest asi bit equal to 1 */
if (asi & 1) {
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_kernel_secondary(addr);
break;
@@ -2642,7 +1381,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
}
} else {
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_kernel(addr);
break;
@@ -2662,7 +1401,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
} else {
/* secondary space access has lowest asi bit equal to 1 */
if (asi & 1) {
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_user_secondary(addr);
break;
@@ -2678,7 +1417,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
}
} else {
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_user(addr);
break;
@@ -2696,12 +1435,12 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
}
break;
- case 0x14: // Bypass
- case 0x15: // Bypass, non-cacheable
- case 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
+ case 0x14: /* Bypass */
+ case 0x15: /* Bypass, non-cacheable */
+ case 0x1c: /* Bypass LE */
+ case 0x1d: /* Bypass, non-cacheable LE */
{
- switch(size) {
+ switch (size) {
case 1:
ret = ldub_phys(addr);
break;
@@ -2718,43 +1457,43 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
}
break;
}
- case 0x24: // Nucleus quad LDD 128 bit atomic
- case 0x2c: // Nucleus quad LDD 128 bit atomic LE
- // Only ldda allowed
- raise_exception(TT_ILL_INSN);
+ case 0x24: /* Nucleus quad LDD 128 bit atomic */
+ case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
+ Only ldda allowed */
+ helper_raise_exception(env, TT_ILL_INSN);
return 0;
- case 0x04: // Nucleus
- case 0x0c: // Nucleus Little Endian (LE)
- {
- switch(size) {
- case 1:
- ret = ldub_nucleus(addr);
- break;
- case 2:
- ret = lduw_nucleus(addr);
- break;
- case 4:
- ret = ldl_nucleus(addr);
- break;
- default:
- case 8:
- ret = ldq_nucleus(addr);
+ case 0x04: /* Nucleus */
+ case 0x0c: /* Nucleus Little Endian (LE) */
+ {
+ switch (size) {
+ case 1:
+ ret = ldub_nucleus(addr);
+ break;
+ case 2:
+ ret = lduw_nucleus(addr);
+ break;
+ case 4:
+ ret = ldl_nucleus(addr);
+ break;
+ default:
+ case 8:
+ ret = ldq_nucleus(addr);
+ break;
+ }
break;
}
+ case 0x4a: /* UPA config */
+ /* XXX */
break;
- }
- case 0x4a: // UPA config
- // XXX
- break;
- case 0x45: // LSU
+ case 0x45: /* LSU */
ret = env->lsu;
break;
- case 0x50: // I-MMU regs
+ case 0x50: /* I-MMU regs */
{
int reg = (addr >> 3) & 0xf;
if (reg == 0) {
- // I-TSB Tag Target register
+ /* I-TSB Tag Target register */
ret = ultrasparc_tag_target(env->immu.tag_access);
} else {
ret = env->immuregs[reg];
@@ -2762,102 +1501,102 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
}
- case 0x51: // I-MMU 8k TSB pointer
+ case 0x51: /* I-MMU 8k TSB pointer */
{
- // env->immuregs[5] holds I-MMU TSB register value
- // env->immuregs[6] holds I-MMU Tag Access register value
+ /* env->immuregs[5] holds I-MMU TSB register value
+ env->immuregs[6] holds I-MMU Tag Access register value */
ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
8*1024);
break;
}
- case 0x52: // I-MMU 64k TSB pointer
+ case 0x52: /* I-MMU 64k TSB pointer */
{
- // env->immuregs[5] holds I-MMU TSB register value
- // env->immuregs[6] holds I-MMU Tag Access register value
+ /* env->immuregs[5] holds I-MMU TSB register value
+ env->immuregs[6] holds I-MMU Tag Access register value */
ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
64*1024);
break;
}
- case 0x55: // I-MMU data access
+ case 0x55: /* I-MMU data access */
{
int reg = (addr >> 3) & 0x3f;
ret = env->itlb[reg].tte;
break;
}
- case 0x56: // I-MMU tag read
+ case 0x56: /* I-MMU tag read */
{
int reg = (addr >> 3) & 0x3f;
ret = env->itlb[reg].tag;
break;
}
- case 0x58: // D-MMU regs
+ case 0x58: /* D-MMU regs */
{
int reg = (addr >> 3) & 0xf;
if (reg == 0) {
- // D-TSB Tag Target register
+ /* D-TSB Tag Target register */
ret = ultrasparc_tag_target(env->dmmu.tag_access);
} else {
ret = env->dmmuregs[reg];
}
break;
}
- case 0x59: // D-MMU 8k TSB pointer
+ case 0x59: /* D-MMU 8k TSB pointer */
{
- // env->dmmuregs[5] holds D-MMU TSB register value
- // env->dmmuregs[6] holds D-MMU Tag Access register value
+ /* env->dmmuregs[5] holds D-MMU TSB register value
+ env->dmmuregs[6] holds D-MMU Tag Access register value */
ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
8*1024);
break;
}
- case 0x5a: // D-MMU 64k TSB pointer
+ case 0x5a: /* D-MMU 64k TSB pointer */
{
- // env->dmmuregs[5] holds D-MMU TSB register value
- // env->dmmuregs[6] holds D-MMU Tag Access register value
+ /* env->dmmuregs[5] holds D-MMU TSB register value
+ env->dmmuregs[6] holds D-MMU Tag Access register value */
ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
64*1024);
break;
}
- case 0x5d: // D-MMU data access
+ case 0x5d: /* D-MMU data access */
{
int reg = (addr >> 3) & 0x3f;
ret = env->dtlb[reg].tte;
break;
}
- case 0x5e: // D-MMU tag read
+ case 0x5e: /* D-MMU tag read */
{
int reg = (addr >> 3) & 0x3f;
ret = env->dtlb[reg].tag;
break;
}
- case 0x46: // D-cache data
- case 0x47: // D-cache tag access
- case 0x4b: // E-cache error enable
- case 0x4c: // E-cache asynchronous fault status
- case 0x4d: // E-cache asynchronous fault address
- case 0x4e: // E-cache tag data
- case 0x66: // I-cache instruction access
- case 0x67: // I-cache tag access
- case 0x6e: // I-cache predecode
- case 0x6f: // I-cache LRU etc.
- case 0x76: // E-cache tag
- case 0x7e: // E-cache tag
- break;
- case 0x5b: // D-MMU data pointer
- case 0x48: // Interrupt dispatch, RO
- case 0x49: // Interrupt data receive
- case 0x7f: // Incoming interrupt vector, RO
- // XXX
- break;
- case 0x54: // I-MMU data in, WO
- case 0x57: // I-MMU demap, WO
- case 0x5c: // D-MMU data in, WO
- case 0x5f: // D-MMU demap, WO
- case 0x77: // Interrupt vector, WO
+ case 0x46: /* D-cache data */
+ case 0x47: /* D-cache tag access */
+ case 0x4b: /* E-cache error enable */
+ case 0x4c: /* E-cache asynchronous fault status */
+ case 0x4d: /* E-cache asynchronous fault address */
+ case 0x4e: /* E-cache tag data */
+ case 0x66: /* I-cache instruction access */
+ case 0x67: /* I-cache tag access */
+ case 0x6e: /* I-cache predecode */
+ case 0x6f: /* I-cache LRU etc. */
+ case 0x76: /* E-cache tag */
+ case 0x7e: /* E-cache tag */
+ break;
+ case 0x5b: /* D-MMU data pointer */
+ case 0x48: /* Interrupt dispatch, RO */
+ case 0x49: /* Interrupt data receive */
+ case 0x7f: /* Incoming interrupt vector, RO */
+ /* XXX */
+ break;
+ case 0x54: /* I-MMU data in, WO */
+ case 0x57: /* I-MMU demap, WO */
+ case 0x5c: /* D-MMU data in, WO */
+ case 0x5f: /* D-MMU demap, WO */
+ case 0x77: /* Interrupt vector, WO */
default:
do_unassigned_access(addr, 0, 0, 1, size);
ret = 0;
@@ -2866,13 +1605,13 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
/* Convert from little endian */
switch (asi) {
- case 0x0c: // Nucleus Little Endian (LE)
- case 0x18: // As if user primary LE
- case 0x19: // As if user secondary LE
- case 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
+ case 0x0c: /* Nucleus Little Endian (LE) */
+ case 0x18: /* As if user primary LE */
+ case 0x19: /* As if user secondary LE */
+ case 0x1c: /* Bypass LE */
+ case 0x1d: /* Bypass, non-cacheable LE */
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
switch(size) {
case 2:
ret = bswap16(ret);
@@ -2892,7 +1631,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
/* Convert to signed number */
if (sign) {
- switch(size) {
+ switch (size) {
case 1:
ret = (int8_t) ret;
break;
@@ -2923,22 +1662,23 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
- && !(env->hpstate & HS_PRIV)))
- raise_exception(TT_PRIV_ACT);
+ && !(env->hpstate & HS_PRIV))) {
+ helper_raise_exception(env, TT_PRIV_ACT);
+ }
helper_check_align(addr, size - 1);
addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
switch (asi) {
- case 0x0c: // Nucleus Little Endian (LE)
- case 0x18: // As if user primary LE
- case 0x19: // As if user secondary LE
- case 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
- switch(size) {
+ case 0x0c: /* Nucleus Little Endian (LE) */
+ case 0x18: /* As if user primary LE */
+ case 0x19: /* As if user secondary LE */
+ case 0x1c: /* Bypass LE */
+ case 0x1d: /* Bypass, non-cacheable LE */
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
+ switch (size) {
case 2:
val = bswap16(val);
break;
@@ -2955,20 +1695,20 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
break;
}
- switch(asi) {
- case 0x10: // As if user primary
- case 0x11: // As if user secondary
- case 0x18: // As if user primary LE
- case 0x19: // As if user secondary LE
- case 0x80: // Primary
- case 0x81: // Secondary
- case 0x88: // Primary LE
- case 0x89: // Secondary LE
- case 0xe2: // UA2007 Primary block init
- case 0xe3: // UA2007 Secondary block init
+ switch (asi) {
+ case 0x10: /* As if user primary */
+ case 0x11: /* As if user secondary */
+ case 0x18: /* As if user primary LE */
+ case 0x19: /* As if user secondary LE */
+ case 0x80: /* Primary */
+ case 0x81: /* Secondary */
+ case 0x88: /* Primary LE */
+ case 0x89: /* Secondary LE */
+ case 0xe2: /* UA2007 Primary block init */
+ case 0xe3: /* UA2007 Secondary block init */
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
if (cpu_hypervisor_mode(env)) {
- switch(size) {
+ switch (size) {
case 1:
stb_hypv(addr, val);
break;
@@ -2986,7 +1726,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
} else {
/* secondary space access has lowest asi bit equal to 1 */
if (asi & 1) {
- switch(size) {
+ switch (size) {
case 1:
stb_kernel_secondary(addr, val);
break;
@@ -3002,7 +1742,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
break;
}
} else {
- switch(size) {
+ switch (size) {
case 1:
stb_kernel(addr, val);
break;
@@ -3022,7 +1762,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
} else {
/* secondary space access has lowest asi bit equal to 1 */
if (asi & 1) {
- switch(size) {
+ switch (size) {
case 1:
stb_user_secondary(addr, val);
break;
@@ -3038,7 +1778,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
break;
}
} else {
- switch(size) {
+ switch (size) {
case 1:
stb_user(addr, val);
break;
@@ -3056,12 +1796,12 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
}
}
break;
- case 0x14: // Bypass
- case 0x15: // Bypass, non-cacheable
- case 0x1c: // Bypass LE
- case 0x1d: // Bypass, non-cacheable LE
+ case 0x14: /* Bypass */
+ case 0x15: /* Bypass, non-cacheable */
+ case 0x1c: /* Bypass LE */
+ case 0x1d: /* Bypass, non-cacheable LE */
{
- switch(size) {
+ switch (size) {
case 1:
stb_phys(addr, val);
break;
@@ -3078,43 +1818,43 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
}
}
return;
- case 0x24: // Nucleus quad LDD 128 bit atomic
- case 0x2c: // Nucleus quad LDD 128 bit atomic LE
- // Only ldda allowed
- raise_exception(TT_ILL_INSN);
+ case 0x24: /* Nucleus quad LDD 128 bit atomic */
+ case 0x2c: /* Nucleus quad LDD 128 bit atomic LE
+ Only ldda allowed */
+ helper_raise_exception(env, TT_ILL_INSN);
return;
- case 0x04: // Nucleus
- case 0x0c: // Nucleus Little Endian (LE)
- {
- switch(size) {
- case 1:
- stb_nucleus(addr, val);
- break;
- case 2:
- stw_nucleus(addr, val);
- break;
- case 4:
- stl_nucleus(addr, val);
- break;
- default:
- case 8:
- stq_nucleus(addr, val);
+ case 0x04: /* Nucleus */
+ case 0x0c: /* Nucleus Little Endian (LE) */
+ {
+ switch (size) {
+ case 1:
+ stb_nucleus(addr, val);
+ break;
+ case 2:
+ stw_nucleus(addr, val);
+ break;
+ case 4:
+ stl_nucleus(addr, val);
+ break;
+ default:
+ case 8:
+ stq_nucleus(addr, val);
+ break;
+ }
break;
}
- break;
- }
- case 0x4a: // UPA config
- // XXX
+ case 0x4a: /* UPA config */
+ /* XXX */
return;
- case 0x45: // LSU
+ case 0x45: /* LSU */
{
uint64_t oldreg;
oldreg = env->lsu;
env->lsu = val & (DMMU_E | IMMU_E);
- // Mappings generated during D/I MMU disabled mode are
- // invalid in normal mode
+ /* Mappings generated during D/I MMU disabled mode are
+ invalid in normal mode */
if (oldreg != env->lsu) {
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
oldreg, env->lsu);
@@ -3125,31 +1865,32 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
}
return;
}
- case 0x50: // I-MMU regs
+ case 0x50: /* I-MMU regs */
{
int reg = (addr >> 3) & 0xf;
uint64_t oldreg;
oldreg = env->immuregs[reg];
- switch(reg) {
- case 0: // RO
+ switch (reg) {
+ case 0: /* RO */
return;
- case 1: // Not in I-MMU
+ case 1: /* Not in I-MMU */
case 2:
return;
- case 3: // SFSR
- if ((val & 1) == 0)
- val = 0; // Clear SFSR
+ case 3: /* SFSR */
+ if ((val & 1) == 0) {
+ val = 0; /* Clear SFSR */
+ }
env->immu.sfsr = val;
break;
- case 4: // RO
+ case 4: /* RO */
return;
- case 5: // TSB access
+ case 5: /* TSB access */
DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
PRIx64 "\n", env->immu.tsb, val);
env->immu.tsb = val;
break;
- case 6: // Tag access
+ case 6: /* Tag access */
env->immu.tag_access = val;
break;
case 7:
@@ -3168,12 +1909,12 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#endif
return;
}
- case 0x54: // I-MMU data in
+ case 0x54: /* I-MMU data in */
replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
return;
- case 0x55: // I-MMU data access
+ case 0x55: /* I-MMU data access */
{
- // TODO: auto demap
+ /* TODO: auto demap */
unsigned int i = (addr >> 3) & 0x3f;
@@ -3185,48 +1926,48 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#endif
return;
}
- case 0x57: // I-MMU demap
+ case 0x57: /* I-MMU demap */
demap_tlb(env->itlb, addr, "immu", env);
return;
- case 0x58: // D-MMU regs
+ case 0x58: /* D-MMU regs */
{
int reg = (addr >> 3) & 0xf;
uint64_t oldreg;
oldreg = env->dmmuregs[reg];
- switch(reg) {
- case 0: // RO
+ switch (reg) {
+ case 0: /* RO */
case 4:
return;
- case 3: // SFSR
+ case 3: /* SFSR */
if ((val & 1) == 0) {
- val = 0; // Clear SFSR, Fault address
+ val = 0; /* Clear SFSR, Fault address */
env->dmmu.sfar = 0;
}
env->dmmu.sfsr = val;
break;
- case 1: // Primary context
+ case 1: /* Primary context */
env->dmmu.mmu_primary_context = val;
/* can be optimized to only flush MMU_USER_IDX
and MMU_KERNEL_IDX entries */
tlb_flush(env, 1);
break;
- case 2: // Secondary context
+ case 2: /* Secondary context */
env->dmmu.mmu_secondary_context = val;
/* can be optimized to only flush MMU_USER_SECONDARY_IDX
and MMU_KERNEL_SECONDARY_IDX entries */
tlb_flush(env, 1);
break;
- case 5: // TSB access
+ case 5: /* TSB access */
DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
PRIx64 "\n", env->dmmu.tsb, val);
env->dmmu.tsb = val;
break;
- case 6: // Tag access
+ case 6: /* Tag access */
env->dmmu.tag_access = val;
break;
- case 7: // Virtual Watchpoint
- case 8: // Physical Watchpoint
+ case 7: /* Virtual Watchpoint */
+ case 8: /* Physical Watchpoint */
default:
env->dmmuregs[reg] = val;
break;
@@ -3241,10 +1982,10 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#endif
return;
}
- case 0x5c: // D-MMU data in
+ case 0x5c: /* D-MMU data in */
replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
return;
- case 0x5d: // D-MMU data access
+ case 0x5d: /* D-MMU data access */
{
unsigned int i = (addr >> 3) & 0x3f;
@@ -3256,38 +1997,38 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#endif
return;
}
- case 0x5f: // D-MMU demap
+ case 0x5f: /* D-MMU demap */
demap_tlb(env->dtlb, addr, "dmmu", env);
return;
- case 0x49: // Interrupt data receive
- // XXX
+ case 0x49: /* Interrupt data receive */
+ /* XXX */
return;
- case 0x46: // D-cache data
- case 0x47: // D-cache tag access
- case 0x4b: // E-cache error enable
- case 0x4c: // E-cache asynchronous fault status
- case 0x4d: // E-cache asynchronous fault address
- case 0x4e: // E-cache tag data
- case 0x66: // I-cache instruction access
- case 0x67: // I-cache tag access
- case 0x6e: // I-cache predecode
- case 0x6f: // I-cache LRU etc.
- case 0x76: // E-cache tag
- case 0x7e: // E-cache tag
+ case 0x46: /* D-cache data */
+ case 0x47: /* D-cache tag access */
+ case 0x4b: /* E-cache error enable */
+ case 0x4c: /* E-cache asynchronous fault status */
+ case 0x4d: /* E-cache asynchronous fault address */
+ case 0x4e: /* E-cache tag data */
+ case 0x66: /* I-cache instruction access */
+ case 0x67: /* I-cache tag access */
+ case 0x6e: /* I-cache predecode */
+ case 0x6f: /* I-cache LRU etc. */
+ case 0x76: /* E-cache tag */
+ case 0x7e: /* E-cache tag */
return;
- case 0x51: // I-MMU 8k TSB pointer, RO
- case 0x52: // I-MMU 64k TSB pointer, RO
- case 0x56: // I-MMU tag read, RO
- case 0x59: // D-MMU 8k TSB pointer, RO
- case 0x5a: // D-MMU 64k TSB pointer, RO
- case 0x5b: // D-MMU data pointer, RO
- case 0x5e: // D-MMU tag read, RO
- case 0x48: // Interrupt dispatch, RO
- case 0x7f: // Incoming interrupt vector, RO
- case 0x82: // Primary no-fault, RO
- case 0x83: // Secondary no-fault, RO
- case 0x8a: // Primary no-fault LE, RO
- case 0x8b: // Secondary no-fault LE, RO
+ case 0x51: /* I-MMU 8k TSB pointer, RO */
+ case 0x52: /* I-MMU 64k TSB pointer, RO */
+ case 0x56: /* I-MMU tag read, RO */
+ case 0x59: /* D-MMU 8k TSB pointer, RO */
+ case 0x5a: /* D-MMU 64k TSB pointer, RO */
+ case 0x5b: /* D-MMU data pointer, RO */
+ case 0x5e: /* D-MMU tag read, RO */
+ case 0x48: /* Interrupt dispatch, RO */
+ case 0x7f: /* Incoming interrupt vector, RO */
+ case 0x82: /* Primary no-fault, RO */
+ case 0x83: /* Secondary no-fault, RO */
+ case 0x8a: /* Primary no-fault LE, RO */
+ case 0x8b: /* Secondary no-fault LE, RO */
default:
do_unassigned_access(addr, 1, 0, 1, size);
return;
@@ -3300,20 +2041,22 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
- && !(env->hpstate & HS_PRIV)))
- raise_exception(TT_PRIV_ACT);
+ && !(env->hpstate & HS_PRIV))) {
+ helper_raise_exception(env, TT_PRIV_ACT);
+ }
addr = asi_address_mask(env, asi, addr);
switch (asi) {
#if !defined(CONFIG_USER_ONLY)
- case 0x24: // Nucleus quad LDD 128 bit atomic
- case 0x2c: // Nucleus quad LDD 128 bit atomic LE
+ case 0x24: /* Nucleus quad LDD 128 bit atomic */
+ case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
helper_check_align(addr, 0xf);
if (rd == 0) {
env->gregs[1] = ldq_nucleus(addr + 8);
- if (asi == 0x2c)
+ if (asi == 0x2c) {
bswap64s(&env->gregs[1]);
+ }
} else if (rd < 8) {
env->gregs[rd] = ldq_nucleus(addr);
env->gregs[rd + 1] = ldq_nucleus(addr + 8);
@@ -3333,9 +2076,9 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
#endif
default:
helper_check_align(addr, 0x3);
- if (rd == 0)
+ if (rd == 0) {
env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
- else if (rd < 8) {
+ } else if (rd < 8) {
env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
} else {
@@ -3360,7 +2103,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
case 0xf8: /* UA2007/JPS1 Block load primary LE */
case 0xf9: /* UA2007/JPS1 Block load secondary LE */
if (rd & 7) {
- raise_exception(TT_ILL_INSN);
+ helper_raise_exception(env, TT_ILL_INSN);
return;
}
helper_check_align(addr, 0x3f);
@@ -3380,7 +2123,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
case 0x78: /* JPS1 Block load primary LE, user privilege */
case 0x79: /* JPS1 Block load secondary LE, user privilege */
if (rd & 7) {
- raise_exception(TT_ILL_INSN);
+ helper_raise_exception(env, TT_ILL_INSN);
return;
}
helper_check_align(addr, 0x3f);
@@ -3395,7 +2138,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
break;
}
- switch(size) {
+ switch (size) {
default:
case 4:
*((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0);
@@ -3433,7 +2176,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
case 0xf8: /* UA2007/JPS1 Block store primary LE */
case 0xf9: /* UA2007/JPS1 Block store secondary LE */
if (rd & 7) {
- raise_exception(TT_ILL_INSN);
+ helper_raise_exception(env, TT_ILL_INSN);
return;
}
helper_check_align(addr, 0x3f);
@@ -3453,7 +2196,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
case 0x78: /* JPS1 Block load primary LE, user privilege */
case 0x79: /* JPS1 Block load secondary LE, user privilege */
if (rd & 7) {
- raise_exception(TT_ILL_INSN);
+ helper_raise_exception(env, TT_ILL_INSN);
return;
}
helper_check_align(addr, 0x3f);
@@ -3468,7 +2211,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
break;
}
- switch(size) {
+ switch (size) {
default:
case 4:
helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size);
@@ -3497,8 +2240,9 @@ target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
val2 &= 0xffffffffUL;
ret = helper_ld_asi(addr, asi, 4, 0);
ret &= 0xffffffffUL;
- if (val2 == ret)
+ if (val2 == ret) {
helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
+ }
return ret;
}
@@ -3508,30 +2252,13 @@ target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
target_ulong ret;
ret = helper_ld_asi(addr, asi, 8, 0);
- if (val2 == ret)
+ if (val2 == ret) {
helper_st_asi(addr, val1, asi, 8);
+ }
return ret;
}
#endif /* TARGET_SPARC64 */
-#ifndef TARGET_SPARC64
-void helper_rett(void)
-{
- unsigned int cwp;
-
- if (env->psret == 1)
- raise_exception(TT_ILL_INSN);
-
- env->psret = 1;
- cwp = cwp_inc(env->cwp + 1) ;
- if (env->wim & (1 << cwp)) {
- raise_exception(TT_WIN_UNF);
- }
- set_cwp(cwp);
- env->psrs = env->psrps;
-}
-#endif
-
static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
{
int overflow = 0;
@@ -3542,7 +2269,7 @@ static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
x1 = (b & 0xffffffff);
if (x1 == 0) {
- raise_exception(TT_DIV_ZERO);
+ helper_raise_exception(env, TT_DIV_ZERO);
}
x0 = x0 / x1;
@@ -3579,12 +2306,12 @@ static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
x1 = (b & 0xffffffff);
if (x1 == 0) {
- raise_exception(TT_DIV_ZERO);
+ helper_raise_exception(env, TT_DIV_ZERO);
}
x0 = x0 / x1;
if ((int32_t) x0 != x0) {
- x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
+ x0 = x0 < 0 ? 0x80000000 : 0x7fffffff;
overflow = 1;
}
@@ -3658,7 +2385,7 @@ void helper_lddf(target_ulong addr, int mem_idx)
void helper_ldqf(target_ulong addr, int mem_idx)
{
- // XXX add 128 bit load
+ /* XXX add 128 bit load */
CPU_QuadU u;
helper_check_align(addr, 7);
@@ -3694,7 +2421,7 @@ void helper_ldqf(target_ulong addr, int mem_idx)
void helper_stqf(target_ulong addr, int mem_idx)
{
- // XXX add 128 bit store
+ /* XXX add 128 bit store */
CPU_QuadU u;
helper_check_align(addr, 7);
@@ -3728,415 +2455,8 @@ void helper_stqf(target_ulong addr, int mem_idx)
#endif
}
-static inline void set_fsr(void)
-{
- int rnd_mode;
-
- switch (env->fsr & FSR_RD_MASK) {
- case FSR_RD_NEAREST:
- rnd_mode = float_round_nearest_even;
- break;
- default:
- case FSR_RD_ZERO:
- rnd_mode = float_round_to_zero;
- break;
- case FSR_RD_POS:
- rnd_mode = float_round_up;
- break;
- case FSR_RD_NEG:
- rnd_mode = float_round_down;
- break;
- }
- set_float_rounding_mode(rnd_mode, &env->fp_status);
-}
-
-void helper_ldfsr(uint32_t new_fsr)
-{
- env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
- set_fsr();
-}
-
#ifdef TARGET_SPARC64
-void helper_ldxfsr(uint64_t new_fsr)
-{
- env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
- set_fsr();
-}
-#endif
-
-void helper_debug(void)
-{
- env->exception_index = EXCP_DEBUG;
- cpu_loop_exit(env);
-}
-
-#ifndef TARGET_SPARC64
-/* XXX: use another pointer for %iN registers to avoid slow wrapping
- handling ? */
-void helper_save(void)
-{
- uint32_t cwp;
-
- cwp = cwp_dec(env->cwp - 1);
- if (env->wim & (1 << cwp)) {
- raise_exception(TT_WIN_OVF);
- }
- set_cwp(cwp);
-}
-
-void helper_restore(void)
-{
- uint32_t cwp;
-
- cwp = cwp_inc(env->cwp + 1);
- if (env->wim & (1 << cwp)) {
- raise_exception(TT_WIN_UNF);
- }
- set_cwp(cwp);
-}
-
-void helper_wrpsr(target_ulong new_psr)
-{
- if ((new_psr & PSR_CWP) >= env->nwindows) {
- raise_exception(TT_ILL_INSN);
- } else {
- cpu_put_psr(env, new_psr);
- }
-}
-
-target_ulong helper_rdpsr(void)
-{
- return get_psr();
-}
-
-#else
-/* XXX: use another pointer for %iN registers to avoid slow wrapping
- handling ? */
-void helper_save(void)
-{
- uint32_t cwp;
-
- cwp = cwp_dec(env->cwp - 1);
- if (env->cansave == 0) {
- raise_exception(TT_SPILL | (env->otherwin != 0 ?
- (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
- ((env->wstate & 0x7) << 2)));
- } else {
- if (env->cleanwin - env->canrestore == 0) {
- // XXX Clean windows without trap
- raise_exception(TT_CLRWIN);
- } else {
- env->cansave--;
- env->canrestore++;
- set_cwp(cwp);
- }
- }
-}
-
-void helper_restore(void)
-{
- uint32_t cwp;
-
- cwp = cwp_inc(env->cwp + 1);
- if (env->canrestore == 0) {
- raise_exception(TT_FILL | (env->otherwin != 0 ?
- (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
- ((env->wstate & 0x7) << 2)));
- } else {
- env->cansave++;
- env->canrestore--;
- set_cwp(cwp);
- }
-}
-
-void helper_flushw(void)
-{
- if (env->cansave != env->nwindows - 2) {
- raise_exception(TT_SPILL | (env->otherwin != 0 ?
- (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
- ((env->wstate & 0x7) << 2)));
- }
-}
-
-void helper_saved(void)
-{
- env->cansave++;
- if (env->otherwin == 0)
- env->canrestore--;
- else
- env->otherwin--;
-}
-
-void helper_restored(void)
-{
- env->canrestore++;
- if (env->cleanwin < env->nwindows - 1)
- env->cleanwin++;
- if (env->otherwin == 0)
- env->cansave--;
- else
- env->otherwin--;
-}
-
-static target_ulong get_ccr(void)
-{
- target_ulong psr;
-
- psr = get_psr();
-
- return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
-}
-
-target_ulong cpu_get_ccr(CPUState *env1)
-{
- CPUState *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = get_ccr();
- env = saved_env;
- return ret;
-}
-
-static void put_ccr(target_ulong val)
-{
- env->xcc = (val >> 4) << 20;
- env->psr = (val & 0xf) << 20;
- CC_OP = CC_OP_FLAGS;
-}
-
-void cpu_put_ccr(CPUState *env1, target_ulong val)
-{
- CPUState *saved_env;
-
- saved_env = env;
- env = env1;
- put_ccr(val);
- env = saved_env;
-}
-
-static target_ulong get_cwp64(void)
-{
- return env->nwindows - 1 - env->cwp;
-}
-
-target_ulong cpu_get_cwp64(CPUState *env1)
-{
- CPUState *saved_env;
- target_ulong ret;
-
- saved_env = env;
- env = env1;
- ret = get_cwp64();
- env = saved_env;
- return ret;
-}
-
-static void put_cwp64(int cwp)
-{
- if (unlikely(cwp >= env->nwindows || cwp < 0)) {
- cwp %= env->nwindows;
- }
- set_cwp(env->nwindows - 1 - cwp);
-}
-
-void cpu_put_cwp64(CPUState *env1, int cwp)
-{
- CPUState *saved_env;
-
- saved_env = env;
- env = env1;
- put_cwp64(cwp);
- env = saved_env;
-}
-
-target_ulong helper_rdccr(void)
-{
- return get_ccr();
-}
-
-void helper_wrccr(target_ulong new_ccr)
-{
- put_ccr(new_ccr);
-}
-
-// CWP handling is reversed in V9, but we still use the V8 register
-// order.
-target_ulong helper_rdcwp(void)
-{
- return get_cwp64();
-}
-
-void helper_wrcwp(target_ulong new_cwp)
-{
- put_cwp64(new_cwp);
-}
-
-// This function uses non-native bit order
-#define GET_FIELD(X, FROM, TO) \
- ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
-
-// This function uses the order in the manuals, i.e. bit 0 is 2^0
-#define GET_FIELD_SP(X, FROM, TO) \
- GET_FIELD(X, 63 - (TO), 63 - (FROM))
-
-target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
-{
- return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
- (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
- (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
- (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
- (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
- (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
- (((pixel_addr >> 55) & 1) << 4) |
- (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
- GET_FIELD_SP(pixel_addr, 11, 12);
-}
-
-target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
-{
- uint64_t tmp;
-
- tmp = addr + offset;
- env->gsr &= ~7ULL;
- env->gsr |= tmp & 7ULL;
- return tmp & ~7ULL;
-}
-
-target_ulong helper_popc(target_ulong val)
-{
- return ctpop64(val);
-}
-
-static inline uint64_t *get_gregset(uint32_t pstate)
-{
- switch (pstate) {
- default:
- DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
- pstate,
- (pstate & PS_IG) ? " IG" : "",
- (pstate & PS_MG) ? " MG" : "",
- (pstate & PS_AG) ? " AG" : "");
- /* pass through to normal set of global registers */
- case 0:
- return env->bgregs;
- case PS_AG:
- return env->agregs;
- case PS_MG:
- return env->mgregs;
- case PS_IG:
- return env->igregs;
- }
-}
-
-static inline void change_pstate(uint32_t new_pstate)
-{
- uint32_t pstate_regs, new_pstate_regs;
- uint64_t *src, *dst;
-
- if (env->def->features & CPU_FEATURE_GL) {
- // PS_AG is not implemented in this case
- new_pstate &= ~PS_AG;
- }
-
- pstate_regs = env->pstate & 0xc01;
- new_pstate_regs = new_pstate & 0xc01;
-
- if (new_pstate_regs != pstate_regs) {
- DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
- pstate_regs, new_pstate_regs);
- // Switch global register bank
- src = get_gregset(new_pstate_regs);
- dst = get_gregset(pstate_regs);
- memcpy32(dst, env->gregs);
- memcpy32(env->gregs, src);
- }
- else {
- DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
- new_pstate_regs);
- }
- env->pstate = new_pstate;
-}
-
-void helper_wrpstate(target_ulong new_state)
-{
- change_pstate(new_state & 0xf3f);
-
-#if !defined(CONFIG_USER_ONLY)
- if (cpu_interrupts_enabled(env)) {
- cpu_check_irqs(env);
- }
-#endif
-}
-
-void cpu_change_pstate(CPUState *env1, uint32_t new_pstate)
-{
- CPUState *saved_env;
-
- saved_env = env;
- env = env1;
- change_pstate(new_pstate);
- env = saved_env;
-}
-
-void helper_wrpil(target_ulong new_pil)
-{
-#if !defined(CONFIG_USER_ONLY)
- DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
- env->psrpil, (uint32_t)new_pil);
-
- env->psrpil = new_pil;
-
- if (cpu_interrupts_enabled(env)) {
- cpu_check_irqs(env);
- }
-#endif
-}
-
-void helper_done(void)
-{
- trap_state* tsptr = cpu_tsptr(env);
-
- env->pc = tsptr->tnpc;
- env->npc = tsptr->tnpc + 4;
- put_ccr(tsptr->tstate >> 32);
- env->asi = (tsptr->tstate >> 24) & 0xff;
- change_pstate((tsptr->tstate >> 8) & 0xf3f);
- put_cwp64(tsptr->tstate & 0xff);
- env->tl--;
-
- DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
-
-#if !defined(CONFIG_USER_ONLY)
- if (cpu_interrupts_enabled(env)) {
- cpu_check_irqs(env);
- }
-#endif
-}
-
-void helper_retry(void)
-{
- trap_state* tsptr = cpu_tsptr(env);
-
- env->pc = tsptr->tpc;
- env->npc = tsptr->tnpc;
- put_ccr(tsptr->tstate >> 32);
- env->asi = (tsptr->tstate >> 24) & 0xff;
- change_pstate((tsptr->tstate >> 8) & 0xf3f);
- put_cwp64(tsptr->tstate & 0xff);
- env->tl--;
-
- DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
-
-#if !defined(CONFIG_USER_ONLY)
- if (cpu_interrupts_enabled(env)) {
- cpu_check_irqs(env);
- }
-#endif
-}
-
-static void do_modify_softint(const char* operation, uint32_t value)
+static void do_modify_softint(const char *operation, uint32_t value)
{
if (env->softint != value) {
env->softint = value;
@@ -4165,13 +2485,6 @@ void helper_write_softint(uint64_t value)
}
#endif
-#ifdef TARGET_SPARC64
-trap_state* cpu_tsptr(CPUState* env)
-{
- return &env->ts[env->tl & MAXTL_MASK];
-}
-#endif
-
#if !defined(CONFIG_USER_ONLY)
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
@@ -4218,7 +2531,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
"\n", addr, env->pc);
#endif
cpu_restore_state2(retaddr);
- raise_exception(TT_UNALIGNED);
+ helper_raise_exception(env, TT_UNALIGNED);
}
/* try to fill the TLB and return an exception if error. If retaddr is
@@ -4252,29 +2565,34 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
int fault_type;
#ifdef DEBUG_UNASSIGNED
- if (is_asi)
+ if (is_asi) {
printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
" asi 0x%02x from " TARGET_FMT_lx "\n",
is_exec ? "exec" : is_write ? "write" : "read", size,
size == 1 ? "" : "s", addr, is_asi, env->pc);
- else
+ } else {
printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
" from " TARGET_FMT_lx "\n",
is_exec ? "exec" : is_write ? "write" : "read", size,
size == 1 ? "" : "s", addr, env->pc);
+ }
#endif
/* Don't overwrite translation and access faults */
fault_type = (env->mmuregs[3] & 0x1c) >> 2;
if ((fault_type > 4) || (fault_type == 0)) {
env->mmuregs[3] = 0; /* Fault status register */
- if (is_asi)
+ if (is_asi) {
env->mmuregs[3] |= 1 << 16;
- if (env->psrs)
+ }
+ if (env->psrs) {
env->mmuregs[3] |= 1 << 5;
- if (is_exec)
+ }
+ if (is_exec) {
env->mmuregs[3] |= 1 << 6;
- if (is_write)
+ }
+ if (is_write) {
env->mmuregs[3] |= 1 << 7;
+ }
env->mmuregs[3] |= (5 << 2) | 2;
/* SuperSPARC will never place instruction fault addresses in the FAR */
if (!is_exec) {
@@ -4287,10 +2605,11 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
}
if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
- if (is_exec)
- raise_exception(TT_CODE_ACCESS);
- else
- raise_exception(TT_DATA_ACCESS);
+ if (is_exec) {
+ helper_raise_exception(env, TT_CODE_ACCESS);
+ } else {
+ helper_raise_exception(env, TT_DATA_ACCESS);
+ }
}
/* flush neverland mappings created during no-fault mode,
@@ -4303,7 +2622,7 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
#else
#if defined(CONFIG_USER_ONLY)
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
- int is_asi, int size)
+ int is_asi, int size)
#else
static void do_unassigned_access(target_phys_addr_t addr, int is_write,
int is_exec, int is_asi, int size)
@@ -4314,36 +2633,11 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
"\n", addr, env->pc);
#endif
- if (is_exec)
- raise_exception(TT_CODE_ACCESS);
- else
- raise_exception(TT_DATA_ACCESS);
-}
-#endif
-
-
-#ifdef TARGET_SPARC64
-void helper_tick_set_count(void *opaque, uint64_t count)
-{
-#if !defined(CONFIG_USER_ONLY)
- cpu_tick_set_count(opaque, count);
-#endif
-}
-
-uint64_t helper_tick_get_count(void *opaque)
-{
-#if !defined(CONFIG_USER_ONLY)
- return cpu_tick_get_count(opaque);
-#else
- return 0;
-#endif
-}
-
-void helper_tick_set_limit(void *opaque, uint64_t limit)
-{
-#if !defined(CONFIG_USER_ONLY)
- cpu_tick_set_limit(opaque, limit);
-#endif
+ if (is_exec) {
+ helper_raise_exception(env, TT_CODE_ACCESS);
+ } else {
+ helper_raise_exception(env, TT_DATA_ACCESS);
+ }
}
#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index dee67b334f..214252aeb4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -294,7 +294,7 @@ static inline void gen_add_tv(TCGv dst, TCGv src1, TCGv src2)
tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
gen_set_label(l1);
tcg_temp_free(r_temp);
@@ -310,7 +310,7 @@ static inline void gen_tag_tv(TCGv src1, TCGv src2)
tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0x3);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_tmp0, 0, l1);
r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
gen_set_label(l1);
}
@@ -428,7 +428,7 @@ static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
default:
/* We need external help to produce the carry. */
carry_32 = tcg_temp_new_i32();
- gen_helper_compute_C_icc(carry_32);
+ gen_helper_compute_C_icc(carry_32, cpu_env);
break;
}
@@ -492,7 +492,7 @@ static inline void gen_sub_tv(TCGv dst, TCGv src1, TCGv src2)
tcg_gen_andi_tl(r_temp, r_temp, (1ULL << 31));
tcg_gen_brcondi_tl(TCG_COND_EQ, r_temp, 0, l1);
r_const = tcg_const_i32(TT_TOVF);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
gen_set_label(l1);
tcg_temp_free(r_temp);
@@ -567,7 +567,7 @@ static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
default:
/* We need external help to produce the carry. */
carry_32 = tcg_temp_new_i32();
- gen_helper_compute_C_icc(carry_32);
+ gen_helper_compute_C_icc(carry_32, cpu_env);
break;
}
@@ -719,7 +719,7 @@ static inline void gen_trap_ifdivzero_tl(TCGv divisor)
l1 = gen_new_label();
tcg_gen_brcondi_tl(TCG_COND_NE, divisor, 0, l1);
r_const = tcg_const_i32(TT_DIV_ZERO);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
gen_set_label(l1);
}
@@ -1091,7 +1091,7 @@ static inline void save_state(DisasContext *dc, TCGv cond)
/* flush pending conditional evaluations before exposing cpu state */
if (dc->cc_op != CC_OP_FLAGS) {
dc->cc_op = CC_OP_FLAGS;
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
}
save_npc(dc, cond);
}
@@ -1133,7 +1133,7 @@ static inline void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond,
case CC_OP_FLAGS:
break;
default:
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
dc->cc_op = CC_OP_FLAGS;
break;
}
@@ -1405,16 +1405,16 @@ static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
{
switch (fccno) {
case 0:
- gen_helper_fcmps(r_rs1, r_rs2);
+ gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
break;
case 1:
- gen_helper_fcmps_fcc1(r_rs1, r_rs2);
+ gen_helper_fcmps_fcc1(cpu_env, r_rs1, r_rs2);
break;
case 2:
- gen_helper_fcmps_fcc2(r_rs1, r_rs2);
+ gen_helper_fcmps_fcc2(cpu_env, r_rs1, r_rs2);
break;
case 3:
- gen_helper_fcmps_fcc3(r_rs1, r_rs2);
+ gen_helper_fcmps_fcc3(cpu_env, r_rs1, r_rs2);
break;
}
}
@@ -1423,16 +1423,16 @@ static inline void gen_op_fcmpd(int fccno)
{
switch (fccno) {
case 0:
- gen_helper_fcmpd();
+ gen_helper_fcmpd(cpu_env);
break;
case 1:
- gen_helper_fcmpd_fcc1();
+ gen_helper_fcmpd_fcc1(cpu_env);
break;
case 2:
- gen_helper_fcmpd_fcc2();
+ gen_helper_fcmpd_fcc2(cpu_env);
break;
case 3:
- gen_helper_fcmpd_fcc3();
+ gen_helper_fcmpd_fcc3(cpu_env);
break;
}
}
@@ -1441,16 +1441,16 @@ static inline void gen_op_fcmpq(int fccno)
{
switch (fccno) {
case 0:
- gen_helper_fcmpq();
+ gen_helper_fcmpq(cpu_env);
break;
case 1:
- gen_helper_fcmpq_fcc1();
+ gen_helper_fcmpq_fcc1(cpu_env);
break;
case 2:
- gen_helper_fcmpq_fcc2();
+ gen_helper_fcmpq_fcc2(cpu_env);
break;
case 3:
- gen_helper_fcmpq_fcc3();
+ gen_helper_fcmpq_fcc3(cpu_env);
break;
}
}
@@ -1459,16 +1459,16 @@ static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2)
{
switch (fccno) {
case 0:
- gen_helper_fcmpes(r_rs1, r_rs2);
+ gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
break;
case 1:
- gen_helper_fcmpes_fcc1(r_rs1, r_rs2);
+ gen_helper_fcmpes_fcc1(cpu_env, r_rs1, r_rs2);
break;
case 2:
- gen_helper_fcmpes_fcc2(r_rs1, r_rs2);
+ gen_helper_fcmpes_fcc2(cpu_env, r_rs1, r_rs2);
break;
case 3:
- gen_helper_fcmpes_fcc3(r_rs1, r_rs2);
+ gen_helper_fcmpes_fcc3(cpu_env, r_rs1, r_rs2);
break;
}
}
@@ -1477,16 +1477,16 @@ static inline void gen_op_fcmped(int fccno)
{
switch (fccno) {
case 0:
- gen_helper_fcmped();
+ gen_helper_fcmped(cpu_env);
break;
case 1:
- gen_helper_fcmped_fcc1();
+ gen_helper_fcmped_fcc1(cpu_env);
break;
case 2:
- gen_helper_fcmped_fcc2();
+ gen_helper_fcmped_fcc2(cpu_env);
break;
case 3:
- gen_helper_fcmped_fcc3();
+ gen_helper_fcmped_fcc3(cpu_env);
break;
}
}
@@ -1495,16 +1495,16 @@ static inline void gen_op_fcmpeq(int fccno)
{
switch (fccno) {
case 0:
- gen_helper_fcmpeq();
+ gen_helper_fcmpeq(cpu_env);
break;
case 1:
- gen_helper_fcmpeq_fcc1();
+ gen_helper_fcmpeq_fcc1(cpu_env);
break;
case 2:
- gen_helper_fcmpeq_fcc2();
+ gen_helper_fcmpeq_fcc2(cpu_env);
break;
case 3:
- gen_helper_fcmpeq_fcc3();
+ gen_helper_fcmpeq_fcc3(cpu_env);
break;
}
}
@@ -1513,32 +1513,32 @@ static inline void gen_op_fcmpeq(int fccno)
static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2)
{
- gen_helper_fcmps(r_rs1, r_rs2);
+ gen_helper_fcmps(cpu_env, r_rs1, r_rs2);
}
static inline void gen_op_fcmpd(int fccno)
{
- gen_helper_fcmpd();
+ gen_helper_fcmpd(cpu_env);
}
static inline void gen_op_fcmpq(int fccno)
{
- gen_helper_fcmpq();
+ gen_helper_fcmpq(cpu_env);
}
static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2)
{
- gen_helper_fcmpes(r_rs1, r_rs2);
+ gen_helper_fcmpes(cpu_env, r_rs1, r_rs2);
}
static inline void gen_op_fcmped(int fccno)
{
- gen_helper_fcmped();
+ gen_helper_fcmped(cpu_env);
}
static inline void gen_op_fcmpeq(int fccno)
{
- gen_helper_fcmpeq();
+ gen_helper_fcmpeq(cpu_env);
}
#endif
@@ -1549,7 +1549,7 @@ static inline void gen_op_fpexception_im(int fsr_flags)
tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK);
tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags);
r_const = tcg_const_i32(TT_FP_EXCP);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
}
@@ -1561,7 +1561,7 @@ static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
save_state(dc, r_cond);
r_const = tcg_const_i32(TT_NFPU_INSN);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
dc->is_br = 1;
return 1;
@@ -1584,7 +1584,7 @@ static inline void gen_op_clear_ieee_excp_and_FTT(void)
static inline void gen_clear_float_exceptions(void)
{
- gen_helper_clear_float_exceptions();
+ gen_helper_clear_float_exceptions(cpu_env);
}
/* asi moves */
@@ -2038,7 +2038,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_helper_shutdown();
} else {
- gen_helper_raise_exception(cpu_tmp32);
+ gen_helper_raise_exception(cpu_env, cpu_tmp32);
}
} else if (cond != 0) {
TCGv r_cond = tcg_temp_new();
@@ -2068,7 +2068,7 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
- gen_helper_raise_exception(cpu_tmp32);
+ gen_helper_raise_exception(cpu_env, cpu_tmp32);
gen_set_label(l1);
tcg_temp_free(r_cond);
@@ -2106,7 +2106,7 @@ static void disas_sparc_insn(DisasContext * dc)
break;
#ifdef TARGET_SPARC64
case 0x2: /* V9 rdccr */
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
gen_helper_rdccr(cpu_dst);
gen_movl_TN_reg(rd, cpu_dst);
break;
@@ -2182,7 +2182,7 @@ static void disas_sparc_insn(DisasContext * dc)
#ifndef TARGET_SPARC64
if (!supervisor(dc))
goto priv_insn;
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
dc->cc_op = CC_OP_FLAGS;
gen_helper_rdpsr(cpu_dst);
#else
@@ -2383,8 +2383,8 @@ static void disas_sparc_insn(DisasContext * dc)
case 0x29: /* fsqrts */
CHECK_FPU_FEATURE(dc, FSQRT);
gen_clear_float_exceptions();
- gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsqrts(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2392,8 +2392,8 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FSQRT);
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fsqrtd();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsqrtd(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2401,15 +2401,16 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fsqrtq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsqrtq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x41: /* fadds */
gen_clear_float_exceptions();
- gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fadds(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+ cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2417,8 +2418,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_faddd();
- gen_helper_check_ieee_exceptions();
+ gen_helper_faddd(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2427,15 +2428,16 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_QT0(QFPREG(rs1));
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_faddq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_faddq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x45: /* fsubs */
gen_clear_float_exceptions();
- gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsubs(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+ cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2443,8 +2445,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fsubd();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsubd(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2453,16 +2455,17 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_QT0(QFPREG(rs1));
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fsubq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsubq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x49: /* fmuls */
CHECK_FPU_FEATURE(dc, FMUL);
gen_clear_float_exceptions();
- gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fmuls(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+ cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2471,8 +2474,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fmuld();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fmuld(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2482,15 +2485,16 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_QT0(QFPREG(rs1));
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fmulq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fmulq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x4d: /* fdivs */
gen_clear_float_exceptions();
- gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdivs(cpu_tmp32, cpu_env, cpu_fpr[rs1],
+ cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2498,8 +2502,8 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdivd();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdivd(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2508,16 +2512,16 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_QT0(QFPREG(rs1));
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdivq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdivq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x69: /* fsmuld */
CHECK_FPU_FEATURE(dc, FSMULD);
gen_clear_float_exceptions();
- gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fsmuld(cpu_env, cpu_fpr[rs1], cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2526,23 +2530,23 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdmulq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdmulq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0xc4: /* fitos */
gen_clear_float_exceptions();
- gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fitos(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
case 0xc6: /* fdtos */
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdtos(cpu_tmp32);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdtos(cpu_tmp32, cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2550,18 +2554,18 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fqtos(cpu_tmp32);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fqtos(cpu_tmp32, cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
case 0xc8: /* fitod */
- gen_helper_fitod(cpu_fpr[rs2]);
+ gen_helper_fitod(cpu_env, cpu_fpr[rs2]);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0xc9: /* fstod */
- gen_helper_fstod(cpu_fpr[rs2]);
+ gen_helper_fstod(cpu_env, cpu_fpr[rs2]);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2569,42 +2573,42 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fqtod();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fqtod(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0xcc: /* fitoq */
CHECK_FPU_FEATURE(dc, FLOAT128);
- gen_helper_fitoq(cpu_fpr[rs2]);
+ gen_helper_fitoq(cpu_env, cpu_fpr[rs2]);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0xcd: /* fstoq */
CHECK_FPU_FEATURE(dc, FLOAT128);
- gen_helper_fstoq(cpu_fpr[rs2]);
+ gen_helper_fstoq(cpu_env, cpu_fpr[rs2]);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0xce: /* fdtoq */
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fdtoq();
+ gen_helper_fdtoq(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0xd1: /* fstoi */
gen_clear_float_exceptions();
- gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fstoi(cpu_tmp32, cpu_env, cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
case 0xd2: /* fdtoi */
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdtoi(cpu_tmp32);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdtoi(cpu_tmp32, cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2612,8 +2616,8 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fqtoi(cpu_tmp32);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fqtoi(cpu_tmp32, cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
@@ -2637,42 +2641,42 @@ static void disas_sparc_insn(DisasContext * dc)
break;
case 0x6: /* V9 fnegd */
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fnegd();
+ gen_helper_fnegd(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x7: /* V9 fnegq */
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
- gen_helper_fnegq();
+ gen_helper_fnegq(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0xa: /* V9 fabsd */
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fabsd();
+ gen_helper_fabsd(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0xb: /* V9 fabsq */
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
- gen_helper_fabsq();
+ gen_helper_fabsq(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
case 0x81: /* V9 fstox */
gen_clear_float_exceptions();
- gen_helper_fstox(cpu_fpr[rs2]);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fstox(cpu_env, cpu_fpr[rs2]);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x82: /* V9 fdtox */
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fdtox();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fdtox(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2680,24 +2684,24 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT1(QFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fqtox();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fqtox(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x84: /* V9 fxtos */
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fxtos(cpu_tmp32);
- gen_helper_check_ieee_exceptions();
+ gen_helper_fxtos(cpu_tmp32, cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
gen_update_fprs_dirty(rd);
break;
case 0x88: /* V9 fxtod */
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fxtod();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fxtod(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -2705,8 +2709,8 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_DT1(DFPREG(rs2));
gen_clear_float_exceptions();
- gen_helper_fxtoq();
- gen_helper_check_ieee_exceptions();
+ gen_helper_fxtoq(cpu_env);
+ gen_helper_check_ieee_exceptions(cpu_env);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
break;
@@ -3317,7 +3321,7 @@ static void disas_sparc_insn(DisasContext * dc)
dc->cc_op = CC_OP_TSUBTV;
break;
case 0x24: /* mulscc */
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD);
@@ -3828,14 +3832,14 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
cpu_src1 = get_src1(insn, cpu_src1);
gen_movl_reg_TN(rs2, cpu_src2);
- gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x012: /* VIS I array16 */
CHECK_FPU_FEATURE(dc, VIS1);
cpu_src1 = get_src1(insn, cpu_src1);
gen_movl_reg_TN(rs2, cpu_src2);
- gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
tcg_gen_shli_i64(cpu_dst, cpu_dst, 1);
gen_movl_TN_reg(rd, cpu_dst);
break;
@@ -3843,7 +3847,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
cpu_src1 = get_src1(insn, cpu_src1);
gen_movl_reg_TN(rs2, cpu_src2);
- gen_helper_array8(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_array8(cpu_dst, cpu_env, cpu_src1, cpu_src2);
tcg_gen_shli_i64(cpu_dst, cpu_dst, 2);
gen_movl_TN_reg(rd, cpu_dst);
break;
@@ -3851,7 +3855,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
cpu_src1 = get_src1(insn, cpu_src1);
gen_movl_reg_TN(rs2, cpu_src2);
- gen_helper_alignaddr(cpu_dst, cpu_src1, cpu_src2);
+ gen_helper_alignaddr(cpu_dst, cpu_env, cpu_src1, cpu_src2);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x019: /* VIS II bmask */
@@ -3862,63 +3866,63 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmple16(cpu_dst);
+ gen_helper_fcmple16(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x022: /* VIS I fcmpne16 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpne16(cpu_dst);
+ gen_helper_fcmpne16(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x024: /* VIS I fcmple32 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmple32(cpu_dst);
+ gen_helper_fcmple32(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x026: /* VIS I fcmpne32 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpne32(cpu_dst);
+ gen_helper_fcmpne32(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x028: /* VIS I fcmpgt16 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpgt16(cpu_dst);
+ gen_helper_fcmpgt16(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x02a: /* VIS I fcmpeq16 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpeq16(cpu_dst);
+ gen_helper_fcmpeq16(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x02c: /* VIS I fcmpgt32 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpgt32(cpu_dst);
+ gen_helper_fcmpgt32(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x02e: /* VIS I fcmpeq32 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fcmpeq32(cpu_dst);
+ gen_helper_fcmpeq32(cpu_dst, cpu_env);
gen_movl_TN_reg(rd, cpu_dst);
break;
case 0x031: /* VIS I fmul8x16 */
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmul8x16();
+ gen_helper_fmul8x16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3926,7 +3930,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmul8x16au();
+ gen_helper_fmul8x16au(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3934,7 +3938,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmul8x16al();
+ gen_helper_fmul8x16al(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3942,7 +3946,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmul8sux16();
+ gen_helper_fmul8sux16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3950,7 +3954,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmul8ulx16();
+ gen_helper_fmul8ulx16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3958,7 +3962,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmuld8sux16();
+ gen_helper_fmuld8sux16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3966,7 +3970,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fmuld8ulx16();
+ gen_helper_fmuld8ulx16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3980,7 +3984,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_faligndata();
+ gen_helper_faligndata(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3988,7 +3992,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fpmerge();
+ gen_helper_fpmerge(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -3999,7 +4003,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fexpand();
+ gen_helper_fexpand(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
@@ -4007,13 +4011,13 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fpadd16();
+ gen_helper_fpadd16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x051: /* VIS I fpadd16s */
CHECK_FPU_FEATURE(dc, VIS1);
- gen_helper_fpadd16s(cpu_fpr[rd],
+ gen_helper_fpadd16s(cpu_env, cpu_fpr[rd],
cpu_fpr[rs1], cpu_fpr[rs2]);
gen_update_fprs_dirty(rd);
break;
@@ -4021,13 +4025,13 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fpadd32();
+ gen_helper_fpadd32(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x053: /* VIS I fpadd32s */
CHECK_FPU_FEATURE(dc, VIS1);
- gen_helper_fpadd32s(cpu_fpr[rd],
+ gen_helper_fpadd32s(cpu_env, cpu_fpr[rd],
cpu_fpr[rs1], cpu_fpr[rs2]);
gen_update_fprs_dirty(rd);
break;
@@ -4035,13 +4039,13 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fpsub16();
+ gen_helper_fpsub16(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x055: /* VIS I fpsub16s */
CHECK_FPU_FEATURE(dc, VIS1);
- gen_helper_fpsub16s(cpu_fpr[rd],
+ gen_helper_fpsub16s(cpu_env, cpu_fpr[rd],
cpu_fpr[rs1], cpu_fpr[rs2]);
gen_update_fprs_dirty(rd);
break;
@@ -4049,13 +4053,13 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, VIS1);
gen_op_load_fpr_DT0(DFPREG(rs1));
gen_op_load_fpr_DT1(DFPREG(rs2));
- gen_helper_fpsub32();
+ gen_helper_fpsub32(cpu_env);
gen_op_store_DT0_fpr(DFPREG(rd));
gen_update_fprs_dirty(DFPREG(rd));
break;
case 0x057: /* VIS I fpsub32s */
CHECK_FPU_FEATURE(dc, VIS1);
- gen_helper_fpsub32s(cpu_fpr[rd],
+ gen_helper_fpsub32s(cpu_env, cpu_fpr[rd],
cpu_fpr[rs1], cpu_fpr[rs2]);
gen_update_fprs_dirty(rd);
break;
@@ -4413,7 +4417,7 @@ static void disas_sparc_insn(DisasContext * dc)
cpu state */
if (dc->cc_op != CC_OP_FLAGS) {
dc->cc_op = CC_OP_FLAGS;
- gen_helper_compute_psr();
+ gen_helper_compute_psr(cpu_env);
}
cpu_src1 = get_src1(insn, cpu_src1);
if (xop == 0x3c || xop == 0x3e) { // V9 casa/casxa
@@ -4659,16 +4663,16 @@ static void disas_sparc_insn(DisasContext * dc)
gen_address_mask(dc, cpu_addr);
if (rd == 1) {
tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
- gen_helper_ldxfsr(cpu_tmp64);
+ gen_helper_ldxfsr(cpu_env, cpu_tmp64);
} else {
tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
- gen_helper_ldfsr(cpu_tmp32);
+ gen_helper_ldfsr(cpu_env, cpu_tmp32);
}
#else
{
tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
- gen_helper_ldfsr(cpu_tmp32);
+ gen_helper_ldfsr(cpu_env, cpu_tmp32);
}
#endif
break;
@@ -4931,7 +4935,7 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
r_const = tcg_const_i32(TT_ILL_INSN);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
dc->is_br = 1;
}
@@ -4942,7 +4946,7 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
r_const = tcg_const_i32(TT_UNIMP_FLUSH);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
dc->is_br = 1;
}
@@ -4954,7 +4958,7 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
r_const = tcg_const_i32(TT_PRIV_INSN);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free_i32(r_const);
dc->is_br = 1;
}
@@ -4979,7 +4983,7 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
r_const = tcg_const_i32(TT_NCP_INSN);
- gen_helper_raise_exception(r_const);
+ gen_helper_raise_exception(cpu_env, r_const);
tcg_temp_free(r_const);
dc->is_br = 1;
}
@@ -5036,7 +5040,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
if (bp->pc == dc->pc) {
if (dc->pc != pc_start)
save_state(dc, cpu_cond);
- gen_helper_debug();
+ gen_helper_debug(cpu_env);
tcg_gen_exit_tb(0);
dc->is_br = 1;
goto exit_gen_loop;
@@ -5265,6 +5269,6 @@ void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
/* flush pending conditional evaluations before exposing cpu state */
if (CC_OP != CC_OP_FLAGS) {
- helper_compute_psr();
+ helper_compute_psr(env);
}
}
diff --git a/target-sparc/vis_helper.c b/target-sparc/vis_helper.c
new file mode 100644
index 0000000000..a22c10bb43
--- /dev/null
+++ b/target-sparc/vis_helper.c
@@ -0,0 +1,406 @@
+/*
+ * VIS op helpers
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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"
+
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define QT0 (env->qt0)
+#define QT1 (env->qt1)
+
+/* This function uses non-native bit order */
+#define GET_FIELD(X, FROM, TO) \
+ ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
+
+/* This function uses the order in the manuals, i.e. bit 0 is 2^0 */
+#define GET_FIELD_SP(X, FROM, TO) \
+ GET_FIELD(X, 63 - (TO), 63 - (FROM))
+
+target_ulong helper_array8(CPUState *env, target_ulong pixel_addr,
+ target_ulong cubesize)
+{
+ return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
+ (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
+ (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
+ (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
+ (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
+ (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
+ (((pixel_addr >> 55) & 1) << 4) |
+ (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
+ GET_FIELD_SP(pixel_addr, 11, 12);
+}
+
+target_ulong helper_alignaddr(CPUState *env, target_ulong addr,
+ target_ulong offset)
+{
+ uint64_t tmp;
+
+ tmp = addr + offset;
+ env->gsr &= ~7ULL;
+ env->gsr |= tmp & 7ULL;
+ return tmp & ~7ULL;
+}
+
+void helper_faligndata(CPUState *env)
+{
+ uint64_t tmp;
+
+ tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
+ /* on many architectures a shift of 64 does nothing */
+ if ((env->gsr & 7) != 0) {
+ tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
+ }
+ *((uint64_t *)&DT0) = tmp;
+}
+
+#ifdef HOST_WORDS_BIGENDIAN
+#define VIS_B64(n) b[7 - (n)]
+#define VIS_W64(n) w[3 - (n)]
+#define VIS_SW64(n) sw[3 - (n)]
+#define VIS_L64(n) l[1 - (n)]
+#define VIS_B32(n) b[3 - (n)]
+#define VIS_W32(n) w[1 - (n)]
+#else
+#define VIS_B64(n) b[n]
+#define VIS_W64(n) w[n]
+#define VIS_SW64(n) sw[n]
+#define VIS_L64(n) l[n]
+#define VIS_B32(n) b[n]
+#define VIS_W32(n) w[n]
+#endif
+
+typedef union {
+ uint8_t b[8];
+ uint16_t w[4];
+ int16_t sw[4];
+ uint32_t l[2];
+ uint64_t ll;
+ float64 d;
+} VIS64;
+
+typedef union {
+ uint8_t b[4];
+ uint16_t w[2];
+ uint32_t l;
+ float32 f;
+} VIS32;
+
+void helper_fpmerge(CPUState *env)
+{
+ VIS64 s, d;
+
+ s.d = DT0;
+ d.d = DT1;
+
+ /* Reverse calculation order to handle overlap */
+ d.VIS_B64(7) = s.VIS_B64(3);
+ d.VIS_B64(6) = d.VIS_B64(3);
+ d.VIS_B64(5) = s.VIS_B64(2);
+ d.VIS_B64(4) = d.VIS_B64(2);
+ d.VIS_B64(3) = s.VIS_B64(1);
+ d.VIS_B64(2) = d.VIS_B64(1);
+ d.VIS_B64(1) = s.VIS_B64(0);
+ /* d.VIS_B64(0) = d.VIS_B64(0); */
+
+ DT0 = d.d;
+}
+
+void helper_fmul8x16(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_W64(r) = tmp >> 8;
+
+ PMUL(0);
+ PMUL(1);
+ PMUL(2);
+ PMUL(3);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmul8x16al(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_W64(r) = tmp >> 8;
+
+ PMUL(0);
+ PMUL(1);
+ PMUL(2);
+ PMUL(3);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmul8x16au(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_W64(r) = tmp >> 8;
+
+ PMUL(0);
+ PMUL(1);
+ PMUL(2);
+ PMUL(3);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmul8sux16(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_W64(r) = tmp >> 8;
+
+ PMUL(0);
+ PMUL(1);
+ PMUL(2);
+ PMUL(3);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmul8ulx16(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_W64(r) = tmp >> 8;
+
+ PMUL(0);
+ PMUL(1);
+ PMUL(2);
+ PMUL(3);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmuld8sux16(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_L64(r) = tmp;
+
+ /* Reverse calculation order to handle overlap */
+ PMUL(1);
+ PMUL(0);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fmuld8ulx16(CPUState *env)
+{
+ VIS64 s, d;
+ uint32_t tmp;
+
+ s.d = DT0;
+ d.d = DT1;
+
+#define PMUL(r) \
+ tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
+ if ((tmp & 0xff) > 0x7f) { \
+ tmp += 0x100; \
+ } \
+ d.VIS_L64(r) = tmp;
+
+ /* Reverse calculation order to handle overlap */
+ PMUL(1);
+ PMUL(0);
+#undef PMUL
+
+ DT0 = d.d;
+}
+
+void helper_fexpand(CPUState *env)
+{
+ VIS32 s;
+ VIS64 d;
+
+ s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
+ d.d = DT1;
+ d.VIS_W64(0) = s.VIS_B32(0) << 4;
+ d.VIS_W64(1) = s.VIS_B32(1) << 4;
+ d.VIS_W64(2) = s.VIS_B32(2) << 4;
+ d.VIS_W64(3) = s.VIS_B32(3) << 4;
+
+ DT0 = d.d;
+}
+
+#define VIS_HELPER(name, F) \
+ void name##16(CPUState *env) \
+ { \
+ VIS64 s, d; \
+ \
+ s.d = DT0; \
+ d.d = DT1; \
+ \
+ d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
+ d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
+ d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
+ d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
+ \
+ DT0 = d.d; \
+ } \
+ \
+ uint32_t name##16s(CPUState *env, uint32_t src1, \
+ uint32_t src2) \
+ { \
+ VIS32 s, d; \
+ \
+ s.l = src1; \
+ d.l = src2; \
+ \
+ d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
+ d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
+ \
+ return d.l; \
+ } \
+ \
+ void name##32(CPUState *env) \
+ { \
+ VIS64 s, d; \
+ \
+ s.d = DT0; \
+ d.d = DT1; \
+ \
+ d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
+ d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
+ \
+ DT0 = d.d; \
+ } \
+ \
+ uint32_t name##32s(CPUState *env, uint32_t src1, \
+ uint32_t src2) \
+ { \
+ VIS32 s, d; \
+ \
+ s.l = src1; \
+ d.l = src2; \
+ \
+ d.l = F(d.l, s.l); \
+ \
+ return d.l; \
+ }
+
+#define FADD(a, b) ((a) + (b))
+#define FSUB(a, b) ((a) - (b))
+VIS_HELPER(helper_fpadd, FADD)
+VIS_HELPER(helper_fpsub, FSUB)
+
+#define VIS_CMPHELPER(name, F) \
+ uint64_t name##16(CPUState *env) \
+ { \
+ VIS64 s, d; \
+ \
+ s.d = DT0; \
+ d.d = DT1; \
+ \
+ d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0; \
+ d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0; \
+ \
+ return d.ll; \
+ } \
+ \
+ uint64_t name##32(CPUState *env) \
+ { \
+ VIS64 s, d; \
+ \
+ s.d = DT0; \
+ d.d = DT1; \
+ \
+ d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \
+ d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \
+ d.VIS_L64(1) = 0; \
+ \
+ return d.ll; \
+ }
+
+#define FCMPGT(a, b) ((a) > (b))
+#define FCMPEQ(a, b) ((a) == (b))
+#define FCMPLE(a, b) ((a) <= (b))
+#define FCMPNE(a, b) ((a) != (b))
+
+VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
+VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
+VIS_CMPHELPER(helper_fcmple, FCMPLE)
+VIS_CMPHELPER(helper_fcmpne, FCMPNE)
diff --git a/target-sparc/win_helper.c b/target-sparc/win_helper.c
new file mode 100644
index 0000000000..8bf2123e9c
--- /dev/null
+++ b/target-sparc/win_helper.c
@@ -0,0 +1,518 @@
+/*
+ * Helpers for CWP and PSTATE handling
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ *
+ * 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 "helper.h"
+
+//#define DEBUG_PSTATE
+
+#ifdef DEBUG_PSTATE
+#define DPRINTF_PSTATE(fmt, ...) \
+ do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
+#endif
+
+static inline void memcpy32(target_ulong *dst, const target_ulong *src)
+{
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+}
+
+static void set_cwp(int new_cwp)
+{
+ /* put the modified wrap registers at their proper location */
+ if (env->cwp == env->nwindows - 1) {
+ memcpy32(env->regbase, env->regbase + env->nwindows * 16);
+ }
+ env->cwp = new_cwp;
+
+ /* put the wrap registers at their temporary location */
+ if (new_cwp == env->nwindows - 1) {
+ memcpy32(env->regbase + env->nwindows * 16, env->regbase);
+ }
+ env->regwptr = env->regbase + (new_cwp * 16);
+}
+
+void cpu_set_cwp(CPUState *env1, int new_cwp)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ set_cwp(new_cwp);
+ env = saved_env;
+}
+
+static target_ulong get_psr(void)
+{
+ helper_compute_psr(env);
+
+#if !defined(TARGET_SPARC64)
+ return env->version | (env->psr & PSR_ICC) |
+ (env->psref ? PSR_EF : 0) |
+ (env->psrpil << 8) |
+ (env->psrs ? PSR_S : 0) |
+ (env->psrps ? PSR_PS : 0) |
+ (env->psret ? PSR_ET : 0) | env->cwp;
+#else
+ return env->psr & PSR_ICC;
+#endif
+}
+
+target_ulong cpu_get_psr(CPUState *env1)
+{
+ CPUState *saved_env;
+ target_ulong ret;
+
+ saved_env = env;
+ env = env1;
+ ret = get_psr();
+ env = saved_env;
+ return ret;
+}
+
+static void put_psr(target_ulong val)
+{
+ env->psr = val & PSR_ICC;
+#if !defined(TARGET_SPARC64)
+ env->psref = (val & PSR_EF) ? 1 : 0;
+ env->psrpil = (val & PSR_PIL) >> 8;
+#endif
+#if ((!defined(TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
+ cpu_check_irqs(env);
+#endif
+#if !defined(TARGET_SPARC64)
+ env->psrs = (val & PSR_S) ? 1 : 0;
+ env->psrps = (val & PSR_PS) ? 1 : 0;
+ env->psret = (val & PSR_ET) ? 1 : 0;
+ set_cwp(val & PSR_CWP);
+#endif
+ env->cc_op = CC_OP_FLAGS;
+}
+
+void cpu_put_psr(CPUState *env1, target_ulong val)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ put_psr(val);
+ env = saved_env;
+}
+
+static int cwp_inc(int cwp)
+{
+ if (unlikely(cwp >= env->nwindows)) {
+ cwp -= env->nwindows;
+ }
+ return cwp;
+}
+
+int cpu_cwp_inc(CPUState *env1, int cwp)
+{
+ CPUState *saved_env;
+ target_ulong ret;
+
+ saved_env = env;
+ env = env1;
+ ret = cwp_inc(cwp);
+ env = saved_env;
+ return ret;
+}
+
+static int cwp_dec(int cwp)
+{
+ if (unlikely(cwp < 0)) {
+ cwp += env->nwindows;
+ }
+ return cwp;
+}
+
+int cpu_cwp_dec(CPUState *env1, int cwp)
+{
+ CPUState *saved_env;
+ target_ulong ret;
+
+ saved_env = env;
+ env = env1;
+ ret = cwp_dec(cwp);
+ env = saved_env;
+ return ret;
+}
+
+#ifndef TARGET_SPARC64
+void helper_rett(void)
+{
+ unsigned int cwp;
+
+ if (env->psret == 1) {
+ helper_raise_exception(env, TT_ILL_INSN);
+ }
+
+ env->psret = 1;
+ cwp = cwp_inc(env->cwp + 1) ;
+ if (env->wim & (1 << cwp)) {
+ helper_raise_exception(env, TT_WIN_UNF);
+ }
+ set_cwp(cwp);
+ env->psrs = env->psrps;
+}
+
+/* XXX: use another pointer for %iN registers to avoid slow wrapping
+ handling ? */
+void helper_save(void)
+{
+ uint32_t cwp;
+
+ cwp = cwp_dec(env->cwp - 1);
+ if (env->wim & (1 << cwp)) {
+ helper_raise_exception(env, TT_WIN_OVF);
+ }
+ set_cwp(cwp);
+}
+
+void helper_restore(void)
+{
+ uint32_t cwp;
+
+ cwp = cwp_inc(env->cwp + 1);
+ if (env->wim & (1 << cwp)) {
+ helper_raise_exception(env, TT_WIN_UNF);
+ }
+ set_cwp(cwp);
+}
+
+void helper_wrpsr(target_ulong new_psr)
+{
+ if ((new_psr & PSR_CWP) >= env->nwindows) {
+ helper_raise_exception(env, TT_ILL_INSN);
+ } else {
+ cpu_put_psr(env, new_psr);
+ }
+}
+
+target_ulong helper_rdpsr(void)
+{
+ return get_psr();
+}
+
+#else
+/* XXX: use another pointer for %iN registers to avoid slow wrapping
+ handling ? */
+void helper_save(void)
+{
+ uint32_t cwp;
+
+ cwp = cwp_dec(env->cwp - 1);
+ if (env->cansave == 0) {
+ helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+ (TT_WOTHER |
+ ((env->wstate & 0x38) >> 1)) :
+ ((env->wstate & 0x7) << 2)));
+ } else {
+ if (env->cleanwin - env->canrestore == 0) {
+ /* XXX Clean windows without trap */
+ helper_raise_exception(env, TT_CLRWIN);
+ } else {
+ env->cansave--;
+ env->canrestore++;
+ set_cwp(cwp);
+ }
+ }
+}
+
+void helper_restore(void)
+{
+ uint32_t cwp;
+
+ cwp = cwp_inc(env->cwp + 1);
+ if (env->canrestore == 0) {
+ helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ?
+ (TT_WOTHER |
+ ((env->wstate & 0x38) >> 1)) :
+ ((env->wstate & 0x7) << 2)));
+ } else {
+ env->cansave++;
+ env->canrestore--;
+ set_cwp(cwp);
+ }
+}
+
+void helper_flushw(void)
+{
+ if (env->cansave != env->nwindows - 2) {
+ helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
+ (TT_WOTHER |
+ ((env->wstate & 0x38) >> 1)) :
+ ((env->wstate & 0x7) << 2)));
+ }
+}
+
+void helper_saved(void)
+{
+ env->cansave++;
+ if (env->otherwin == 0) {
+ env->canrestore--;
+ } else {
+ env->otherwin--;
+ }
+}
+
+void helper_restored(void)
+{
+ env->canrestore++;
+ if (env->cleanwin < env->nwindows - 1) {
+ env->cleanwin++;
+ }
+ if (env->otherwin == 0) {
+ env->cansave--;
+ } else {
+ env->otherwin--;
+ }
+}
+
+static target_ulong get_ccr(void)
+{
+ target_ulong psr;
+
+ psr = get_psr();
+
+ return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
+}
+
+target_ulong cpu_get_ccr(CPUState *env1)
+{
+ CPUState *saved_env;
+ target_ulong ret;
+
+ saved_env = env;
+ env = env1;
+ ret = get_ccr();
+ env = saved_env;
+ return ret;
+}
+
+static void put_ccr(target_ulong val)
+{
+ env->xcc = (val >> 4) << 20;
+ env->psr = (val & 0xf) << 20;
+ CC_OP = CC_OP_FLAGS;
+}
+
+void cpu_put_ccr(CPUState *env1, target_ulong val)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ put_ccr(val);
+ env = saved_env;
+}
+
+static target_ulong get_cwp64(void)
+{
+ return env->nwindows - 1 - env->cwp;
+}
+
+target_ulong cpu_get_cwp64(CPUState *env1)
+{
+ CPUState *saved_env;
+ target_ulong ret;
+
+ saved_env = env;
+ env = env1;
+ ret = get_cwp64();
+ env = saved_env;
+ return ret;
+}
+
+static void put_cwp64(int cwp)
+{
+ if (unlikely(cwp >= env->nwindows || cwp < 0)) {
+ cwp %= env->nwindows;
+ }
+ set_cwp(env->nwindows - 1 - cwp);
+}
+
+void cpu_put_cwp64(CPUState *env1, int cwp)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ put_cwp64(cwp);
+ env = saved_env;
+}
+
+target_ulong helper_rdccr(void)
+{
+ return get_ccr();
+}
+
+void helper_wrccr(target_ulong new_ccr)
+{
+ put_ccr(new_ccr);
+}
+
+/* CWP handling is reversed in V9, but we still use the V8 register
+ order. */
+target_ulong helper_rdcwp(void)
+{
+ return get_cwp64();
+}
+
+void helper_wrcwp(target_ulong new_cwp)
+{
+ put_cwp64(new_cwp);
+}
+
+static inline uint64_t *get_gregset(uint32_t pstate)
+{
+ switch (pstate) {
+ default:
+ DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
+ pstate,
+ (pstate & PS_IG) ? " IG" : "",
+ (pstate & PS_MG) ? " MG" : "",
+ (pstate & PS_AG) ? " AG" : "");
+ /* pass through to normal set of global registers */
+ case 0:
+ return env->bgregs;
+ case PS_AG:
+ return env->agregs;
+ case PS_MG:
+ return env->mgregs;
+ case PS_IG:
+ return env->igregs;
+ }
+}
+
+static inline void change_pstate(uint32_t new_pstate)
+{
+ uint32_t pstate_regs, new_pstate_regs;
+ uint64_t *src, *dst;
+
+ if (env->def->features & CPU_FEATURE_GL) {
+ /* PS_AG is not implemented in this case */
+ new_pstate &= ~PS_AG;
+ }
+
+ pstate_regs = env->pstate & 0xc01;
+ new_pstate_regs = new_pstate & 0xc01;
+
+ if (new_pstate_regs != pstate_regs) {
+ DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
+ pstate_regs, new_pstate_regs);
+ /* Switch global register bank */
+ src = get_gregset(new_pstate_regs);
+ dst = get_gregset(pstate_regs);
+ memcpy32(dst, env->gregs);
+ memcpy32(env->gregs, src);
+ } else {
+ DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
+ new_pstate_regs);
+ }
+ env->pstate = new_pstate;
+}
+
+void helper_wrpstate(target_ulong new_state)
+{
+ change_pstate(new_state & 0xf3f);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+
+void cpu_change_pstate(CPUState *env1, uint32_t new_pstate)
+{
+ CPUState *saved_env;
+
+ saved_env = env;
+ env = env1;
+ change_pstate(new_pstate);
+ env = saved_env;
+}
+
+void helper_wrpil(target_ulong new_pil)
+{
+#if !defined(CONFIG_USER_ONLY)
+ DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
+ env->psrpil, (uint32_t)new_pil);
+
+ env->psrpil = new_pil;
+
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+
+void helper_done(void)
+{
+ trap_state *tsptr = cpu_tsptr(env);
+
+ env->pc = tsptr->tnpc;
+ env->npc = tsptr->tnpc + 4;
+ put_ccr(tsptr->tstate >> 32);
+ env->asi = (tsptr->tstate >> 24) & 0xff;
+ change_pstate((tsptr->tstate >> 8) & 0xf3f);
+ put_cwp64(tsptr->tstate & 0xff);
+ env->tl--;
+
+ DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+
+void helper_retry(void)
+{
+ trap_state *tsptr = cpu_tsptr(env);
+
+ env->pc = tsptr->tpc;
+ env->npc = tsptr->tnpc;
+ put_ccr(tsptr->tstate >> 32);
+ env->asi = (tsptr->tstate >> 24) & 0xff;
+ change_pstate((tsptr->tstate >> 8) & 0xf3f);
+ put_cwp64(tsptr->tstate & 0xff);
+ env->tl--;
+
+ DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (cpu_interrupts_enabled(env)) {
+ cpu_check_irqs(env);
+ }
+#endif
+}
+#endif