[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] Patch: Basic Sparc Floating point support
From: |
Blue Swirl |
Subject: |
[Qemu-devel] Patch: Basic Sparc Floating point support |
Date: |
Wed, 04 Aug 2004 20:43:44 +0200 |
Hi,
Implemented most Sparc single and double FP ops using PPC as reference. Also
includes the Sparc-specific signals and open flags. Missing: quad ops,
exceptions. There are known bugs, so please don't use this for your finance
management.
diff -ru qemu-0.6.0.orig/Makefile.target qemu-0.6.0/Makefile.target
--- qemu-0.6.0.orig/Makefile.target 2004-07-10 20:20:09.000000000 +0200
+++ qemu-0.6.0/Makefile.target 2004-08-03 20:27:27.000000000 +0200
@@ -198,6 +218,10 @@
LIBOBJS+= op_helper.o helper.o
endif
+ifeq ($(TARGET_ARCH), sparc)
+LIBOBJS+= op_helper.o
+endif
+
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
diff -ru qemu-0.6.0.orig/linux-user/syscall_defs.h
qemu-0.6.0/linux-user/syscall_defs.h
--- qemu-0.6.0.orig/linux-user/syscall_defs.h 2004-07-10 20:20:09.000000000
+0200
+++ qemu-0.6.0/linux-user/syscall_defs.h 2004-07-15 21:46:08.000000000
+0200
@@ -294,6 +294,7 @@
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) ||
defined(TARGET_PPC)
+#if !defined(TARGET_SPARC)
#define TARGET_SA_NOCLDSTOP 0x00000001
#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
#define TARGET_SA_SIGINFO 0x00000004
@@ -302,6 +303,15 @@
#define TARGET_SA_NODEFER 0x40000000
#define TARGET_SA_RESETHAND 0x80000000
#define TARGET_SA_RESTORER 0x04000000
+#else /* TARGET_SPARC */
+#define TARGET_SA_NOCLDSTOP 8u
+#define TARGET_SA_NOCLDWAIT 0x100u
+#define TARGET_SA_SIGINFO 0x200u
+#define TARGET_SA_ONSTACK 1u
+#define TARGET_SA_RESTART 2u
+#define TARGET_SA_NODEFER 0x20u
+#define TARGET_SA_RESETHAND 4u
+#endif
#define TARGET_SIGHUP 1
#define TARGET_SIGINT 2
@@ -310,36 +320,72 @@
#define TARGET_SIGTRAP 5
#define TARGET_SIGABRT 6
#define TARGET_SIGIOT 6
+#if !defined(TARGET_SPARC)
#define TARGET_SIGBUS 7
+#else /* TARGET_SPARC */
+#define TARGET_SIGSTKFLT 7 /* actually EMT */
+#endif
#define TARGET_SIGFPE 8
#define TARGET_SIGKILL 9
+#if !defined(TARGET_SPARC)
#define TARGET_SIGUSR1 10
+#else /* TARGET_SPARC */
+#define TARGET_SIGBUS 10
+#endif
#define TARGET_SIGSEGV 11
+#if !defined(TARGET_SPARC)
#define TARGET_SIGUSR2 12
+#else /* TARGET_SPARC */
+#define TARGET_SIGSYS 12
+#endif
#define TARGET_SIGPIPE 13
#define TARGET_SIGALRM 14
#define TARGET_SIGTERM 15
+#if !defined(TARGET_SPARC)
#define TARGET_SIGSTKFLT 16
#define TARGET_SIGCHLD 17
#define TARGET_SIGCONT 18
#define TARGET_SIGSTOP 19
#define TARGET_SIGTSTP 20
+#else /* TARGET_SPARC */
+#define TARGET_SIGURG 16
+#define TARGET_SIGSTOP 17
+#define TARGET_SIGTSTP 18
+#define TARGET_SIGCONT 19
+#define TARGET_SIGCHLD 20
+#endif
#define TARGET_SIGTTIN 21
#define TARGET_SIGTTOU 22
+#if !defined(TARGET_SPARC)
#define TARGET_SIGURG 23
+#else /* TARGET_SPARC */
+#define TARGET_SIGIO 23
+#endif
#define TARGET_SIGXCPU 24
#define TARGET_SIGXFSZ 25
#define TARGET_SIGVTALRM 26
#define TARGET_SIGPROF 27
#define TARGET_SIGWINCH 28
+#if !defined(TARGET_SPARC)
#define TARGET_SIGIO 29
#define TARGET_SIGPWR 30
#define TARGET_SIGSYS 31
+#else /* TARGET_SPARC */
+#define TARGET_SIGPWR 29
+#define TARGET_SIGUSR1 30
+#define TARGET_SIGUSR2 31
+#endif
#define TARGET_SIGRTMIN 32
+#if !defined(TARGET_SPARC)
#define TARGET_SIG_BLOCK 0 /* for blocking signals */
#define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */
#define TARGET_SIG_SETMASK 2 /* for setting the signal mask */
+#else /* TARGET_SPARC */
+#define TARGET_SIG_BLOCK 0x01 /* for blocking signals */
+#define TARGET_SIG_UNBLOCK 0x02 /* for unblocking signals */
+#define TARGET_SIG_SETMASK 0x04 /* for setting the signal mask */
+#endif
struct target_old_sigaction {
target_ulong _sa_handler;
@@ -954,6 +1024,24 @@
#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */
#define TARGET_O_LARGEFILE 0200000
#define TARGET_O_DIRECT 0400000 /* direct disk access hint */
+#elif defined (TARGET_SPARC)
+#define TARGET_O_RDONLY 0x0000
+#define TARGET_O_WRONLY 0x0001
+#define TARGET_O_RDWR 0x0002
+#define TARGET_O_ACCMODE 0x0003
+#define TARGET_O_APPEND 0x0008
+#define TARGET_FASYNC 0x0040 /* fcntl, for BSD compatibility */
+#define TARGET_O_CREAT 0x0200 /* not fcntl */
+#define TARGET_O_TRUNC 0x0400 /* not fcntl */
+#define TARGET_O_EXCL 0x0800 /* not fcntl */
+#define TARGET_O_SYNC 0x2000
+#define TARGET_O_NONBLOCK 0x4000
+#define TARGET_O_NDELAY (0x0004 | O_NONBLOCK)
+#define TARGET_O_NOCTTY 0x8000 /* not fcntl */
+#define TARGET_O_DIRECTORY 0x10000 /* must be a directory */
+#define TARGET_O_NOFOLLOW 0x20000 /* don't follow links */
+#define TARGET_O_LARGEFILE 0x40000
+#define TARGET_O_DIRECT 0x100000 /* direct disk access hint */
#else
#define TARGET_O_ACCMODE 0003
#define TARGET_O_RDONLY 00
diff -ru qemu-0.6.0.orig/target-sparc/cpu.h qemu-0.6.0/target-sparc/cpu.h
--- qemu-0.6.0.orig/target-sparc/cpu.h 2004-07-10 20:20:09.000000000 +0200
+++ qemu-0.6.0/target-sparc/cpu.h 2004-08-04 16:46:40.000000000 +0200
@@ -19,17 +19,22 @@
#define PSR_OVF (1<<21)
#define PSR_CARRY (1<<20)
+/* Fcc */
+#define FSR_FCC1 (1<<11)
+#define FSR_FCC0 (1<<10)
+
#define NWINDOWS 32
typedef struct CPUSPARCState {
uint32_t gregs[8]; /* general registers */
uint32_t *regwptr; /* pointer to current register window */
- double *regfptr; /* floating point registers */
+ float fpr[32]; /* floating point registers */
uint32_t pc; /* program counter */
uint32_t npc; /* next program counter */
uint32_t sp; /* stack pointer */
uint32_t y; /* multiply/divide register */
uint32_t psr; /* processor state register */
+ uint32_t fsr; /* FPU state register */
uint32_t T2;
uint32_t cwp; /* index of current register window (extracted
from PSR) */
@@ -51,6 +56,9 @@
written */
unsigned long mem_write_vaddr; /* target virtual addr at which the
memory was written */
+ /* temporary float registers */
+ float ft0, ft1, ft2;
+ double dt0, dt1, dt2;
} CPUSPARCState;
CPUSPARCState *cpu_sparc_init(void);
diff -ru qemu-0.6.0.orig/target-sparc/exec.h qemu-0.6.0/target-sparc/exec.h
--- qemu-0.6.0.orig/target-sparc/exec.h 2004-07-10 20:20:09.000000000 +0200
+++ qemu-0.6.0/target-sparc/exec.h 2004-08-04 16:46:08.000000000 +0200
@@ -6,6 +6,12 @@
register uint32_t T0 asm(AREG1);
register uint32_t T1 asm(AREG2);
register uint32_t T2 asm(AREG3);
+#define FT0 (env->ft0)
+#define FT1 (env->ft1)
+#define FT2 (env->ft2)
+#define DT0 (env->dt0)
+#define DT1 (env->dt1)
+#define DT2 (env->dt2)
#include "cpu.h"
#include "exec-all.h"
@@ -14,4 +20,10 @@
void cpu_unlock(void);
void cpu_loop_exit(void);
void helper_flush(target_ulong addr);
+void do_fabss(void);
+void do_fsqrts(void);
+void do_fsqrtd(void);
+void do_fcmps(void);
+void do_fcmpd(void);
+
#endif
diff -ru qemu-0.6.0.orig/target-sparc/op.c qemu-0.6.0/target-sparc/op.c
--- qemu-0.6.0.orig/target-sparc/op.c 2004-07-10 20:20:09.000000000 +0200
+++ qemu-0.6.0/target-sparc/op.c 2004-08-03 21:48:46.000000000 +0200
@@ -117,9 +117,108 @@
#define REGNAME o7
#define REG (env->regwptr[7])
#include "op_template.h"
+
+#define REGNAME f0
+#define REG (env->fpr[0])
+#include "op_template.h"
+#define REGNAME f1
+#define REG (env->fpr[1])
+#include "op_template.h"
+#define REGNAME f2
+#define REG (env->fpr[2])
+#include "op_template.h"
+#define REGNAME f3
+#define REG (env->fpr[3])
+#include "op_template.h"
+#define REGNAME f4
+#define REG (env->fpr[4])
+#include "op_template.h"
+#define REGNAME f5
+#define REG (env->fpr[5])
+#include "op_template.h"
+#define REGNAME f6
+#define REG (env->fpr[6])
+#include "op_template.h"
+#define REGNAME f7
+#define REG (env->fpr[7])
+#include "op_template.h"
+#define REGNAME f8
+#define REG (env->fpr[8])
+#include "op_template.h"
+#define REGNAME f9
+#define REG (env->fpr[9])
+#include "op_template.h"
+#define REGNAME f10
+#define REG (env->fpr[10])
+#include "op_template.h"
+#define REGNAME f11
+#define REG (env->fpr[11])
+#include "op_template.h"
+#define REGNAME f12
+#define REG (env->fpr[12])
+#include "op_template.h"
+#define REGNAME f13
+#define REG (env->fpr[13])
+#include "op_template.h"
+#define REGNAME f14
+#define REG (env->fpr[14])
+#include "op_template.h"
+#define REGNAME f15
+#define REG (env->fpr[15])
+#include "op_template.h"
+#define REGNAME f16
+#define REG (env->fpr[16])
+#include "op_template.h"
+#define REGNAME f17
+#define REG (env->fpr[17])
+#include "op_template.h"
+#define REGNAME f18
+#define REG (env->fpr[18])
+#include "op_template.h"
+#define REGNAME f19
+#define REG (env->fpr[19])
+#include "op_template.h"
+#define REGNAME f20
+#define REG (env->fpr[20])
+#include "op_template.h"
+#define REGNAME f21
+#define REG (env->fpr[21])
+#include "op_template.h"
+#define REGNAME f22
+#define REG (env->fpr[22])
+#include "op_template.h"
+#define REGNAME f23
+#define REG (env->fpr[23])
+#include "op_template.h"
+#define REGNAME f24
+#define REG (env->fpr[24])
+#include "op_template.h"
+#define REGNAME f25
+#define REG (env->fpr[25])
+#include "op_template.h"
+#define REGNAME f26
+#define REG (env->fpr[26])
+#include "op_template.h"
+#define REGNAME f27
+#define REG (env->fpr[27])
+#include "op_template.h"
+#define REGNAME f28
+#define REG (env->fpr[28])
+#include "op_template.h"
+#define REGNAME f29
+#define REG (env->fpr[29])
+#include "op_template.h"
+#define REGNAME f30
+#define REG (env->fpr[30])
+#include "op_template.h"
+#define REGNAME f31
+#define REG (env->fpr[31])
+#include "op_template.h"
+
#define EIP (env->pc)
#define FLAG_SET(x) (env->psr&x)?1:0
+#define FFLAG_SET(x) (env->fsr&x)?1:0
void OPPROTO op_movl_T0_0(void)
{
@@ -440,6 +539,38 @@
T0 = ldl((void *) (T0 + 4));
}
+void OPPROTO op_stf(void)
+{
+ stfl((void *) T0, FT0);
+}
+
+void OPPROTO op_stdf(void)
+{
+ stfq((void *) T0, FT0);
+}
+
+void OPPROTO op_ldf(void)
+{
+ FT0 = ldfl((void *) T0);
+}
+
+void OPPROTO op_lddf(void)
+{
+ FT0 = ldfq((void *) T0);
+}
+
+void OPPROTO op_ldfsr(void)
+{
+ env->fsr = *((uint32_t *) &FT0);
+ FORCE_RET();
+}
+
+void OPPROTO op_stfsr(void)
+{
+ *((uint32_t *) &FT0) = env->fsr;
+ FORCE_RET();
+}
+
void OPPROTO op_wry(void)
{
env->y = T0;
@@ -612,6 +743,78 @@
T2 = !(env->psr & PSR_OVF);
}
+/* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */
+
+void OPPROTO op_eval_fbne(void)
+{
+ T2 = !(FFLAG_SET(FSR_FCC1) | FFLAG_SET(FSR_FCC0)); /* L or G or U */
+}
+
+void OPPROTO op_eval_fblg(void)
+{
+ T2 = FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbul(void)
+{
+ T2 = FFLAG_SET(FSR_FCC1);
+}
+
+void OPPROTO op_eval_fbl(void)
+{
+ T2 = FFLAG_SET(FSR_FCC1) & !FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbug(void)
+{
+ T2 = FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbg(void)
+{
+ T2 = !FFLAG_SET(FSR_FCC1) & FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbu(void)
+{
+ T2 = FFLAG_SET(FSR_FCC1) & FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbe(void)
+{
+ T2 = !FFLAG_SET(FSR_FCC1) & !FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbue(void)
+{
+ T2 = !(FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0));
+}
+
+void OPPROTO op_eval_fbge(void)
+{
+ T2 = !FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbuge(void)
+{
+ T2 = !FFLAG_SET(FSR_FCC1) & FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fble(void)
+{
+ T2 = !FFLAG_SET(FSR_FCC1);
+}
+
+void OPPROTO op_eval_fbule(void)
+{
+ T2 = FFLAG_SET(FSR_FCC0);
+}
+
+void OPPROTO op_eval_fbo(void)
+{
+ T2 = !(FFLAG_SET(FSR_FCC1) & FFLAG_SET(FSR_FCC0));
+}
+
void OPPROTO op_movl_T2_0(void)
{
T2 = 0;
@@ -687,3 +890,103 @@
{
helper_flush(T0);
}
+
+void OPPROTO op_fnegs(void)
+{
+ FT0 = -FT1;
+}
+
+void OPPROTO op_fabss(void)
+{
+ do_fabss();
+}
+
+void OPPROTO op_fsqrts(void)
+{
+ do_fsqrts();
+}
+
+void OPPROTO op_fsqrtd(void)
+{
+ do_fsqrtd();
+}
+
+void OPPROTO op_fmuls(void)
+{
+ FT0 *= FT1;
+}
+
+void OPPROTO op_fmuld(void)
+{
+ DT0 *= DT1;
+}
+
+void OPPROTO op_fadds(void)
+{
+ FT0 += FT1;
+}
+
+void OPPROTO op_faddd(void)
+{
+ DT0 += DT1;
+}
+
+void OPPROTO op_fsubs(void)
+{
+ FT0 -= FT1;
+}
+
+void OPPROTO op_fsubd(void)
+{
+ DT0 -= DT1;
+}
+
+void OPPROTO op_fdivs(void)
+{
+ FT0 /= FT1;
+}
+
+void OPPROTO op_fdivd(void)
+{
+ DT0 /= DT1;
+}
+
+void OPPROTO op_fcmps(void)
+{
+ do_fcmps();
+}
+
+void OPPROTO op_fcmpd(void)
+{
+ do_fcmpd();
+}
+
+void OPPROTO op_fitos(void)
+{
+ FT0 = (float) *((int32_t *)&FT1);
+}
+
+void OPPROTO op_fdtos(void)
+{
+ FT0 = (float) DT1;
+}
+
+void OPPROTO op_fitod(void)
+{
+ DT0 = (double) *((int32_t *)&FT1);
+}
+
+void OPPROTO op_fstod(void)
+{
+ DT0 = (double) FT1;
+}
+
+void OPPROTO op_fstoi(void)
+{
+ *((int32_t *)&FT0) = (int32_t) FT1;
+}
+
+void OPPROTO op_fdtoi(void)
+{
+ *((int32_t *)&FT0) = (int32_t) DT1;
+}
diff -ru qemu-0.6.0.orig/target-sparc/op_template.h
qemu-0.6.0/target-sparc/op_template.h
--- qemu-0.6.0.orig/target-sparc/op_template.h 2004-07-10 20:20:09.000000000
+0200
+++ qemu-0.6.0/target-sparc/op_template.h 2004-08-03 21:14:04.000000000
+0200
@@ -44,5 +44,67 @@
REG = T1;
}
+/* floating point registers moves */
+void OPPROTO glue(op_load_fpr_FT0_fpr, REGNAME)(void)
+{
+ FT0 = REG;
+}
+
+void OPPROTO glue(op_store_FT0_fpr_fpr, REGNAME)(void)
+{
+ REG = FT0;
+}
+
+void OPPROTO glue(op_load_fpr_FT1_fpr, REGNAME)(void)
+{
+ FT1 = REG;
+}
+
+void OPPROTO glue(op_store_FT1_fpr_fpr, REGNAME)(void)
+{
+ REG = FT1;
+}
+
+void OPPROTO glue(op_load_fpr_FT2_fpr, REGNAME)(void)
+{
+ FT2 = REG;
+}
+
+void OPPROTO glue(op_store_FT2_fpr_fpr, REGNAME)(void)
+{
+ REG = FT2;
+}
+
+/* double floating point registers moves */
+void OPPROTO glue(op_load_fpr_DT0_fpr, REGNAME)(void)
+{
+ DT0 = *((double *) ®);
+}
+
+void OPPROTO glue(op_store_DT0_fpr_fpr, REGNAME)(void)
+{
+ *((double *) ®) = DT0;
+}
+
+void OPPROTO glue(op_load_fpr_DT1_fpr, REGNAME)(void)
+{
+ DT1 = *((double *) ®);
+}
+
+void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
+{
+ *((double *) ®) = DT1;
+}
+
+void OPPROTO glue(op_load_fpr_DT2_fpr, REGNAME)(void)
+{
+ DT2 = *((double *) ®);
+}
+
+void OPPROTO glue(op_store_DT2_fpr_fpr, REGNAME)(void)
+{
+ *((double *) ®) = DT2;
+}
+
#undef REG
#undef REGNAME
diff -ru qemu-0.6.0.orig/target-sparc/translate.c
qemu-0.6.0/target-sparc/translate.c
--- qemu-0.6.0.orig/target-sparc/translate.c 2004-07-10 20:20:09.000000000
+0200
+++ qemu-0.6.0/target-sparc/translate.c 2004-08-03 21:58:12.000000000 +0200
@@ -257,6 +257,37 @@
gen_op_movl_T2_im
};
+#define GEN32(func, NAME) \
+static GenOpFunc *NAME ## _table [32] = {
\
+NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,
\
+NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,
\
+NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,
\
+NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,
\
+NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,
\
+NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,
\
+NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,
\
+NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,
\
+};
\
+static inline void func(int n)
\
+{
\
+ NAME ## _table[n]();
\
+}
+
+/* floating point registers moves */
+GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
+GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
+GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fprf);
+GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
+GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
+GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fprf);
+
+GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
+GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
+GEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fprf);
+GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
+GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
+GEN32(gen_op_store_DT2_fpr, gen_op_store_DT2_fpr_fprf);
+
static inline void gen_movl_imm_TN(int reg, int imm)
{
gen_op_movl_TN_im[reg] (imm);
@@ -391,6 +422,60 @@
}
}
+static void gen_fcond(int cond)
+{
+ switch (cond) {
+ case 0x0:
+ gen_op_movl_T2_0();
+ break;
+ case 0x1:
+ gen_op_eval_fbne();
+ break;
+ case 0x2:
+ gen_op_eval_fblg();
+ break;
+ case 0x3:
+ gen_op_eval_fbul();
+ break;
+ case 0x4:
+ gen_op_eval_fbl();
+ break;
+ case 0x5:
+ gen_op_eval_fbug();
+ break;
+ case 0x6:
+ gen_op_eval_fbg();
+ break;
+ case 0x7:
+ gen_op_eval_fbu();
+ break;
+ case 0x8:
+ gen_op_movl_T2_1();
+ break;
+ case 0x9:
+ gen_op_eval_fbe();
+ break;
+ case 0xa:
+ gen_op_eval_fbue();
+ break;
+ case 0xb:
+ gen_op_eval_fbge();
+ break;
+ case 0xc:
+ gen_op_eval_fbuge();
+ break;
+ case 0xd:
+ gen_op_eval_fble();
+ break;
+ case 0xe:
+ gen_op_eval_fbule();
+ break;
+ default:
+ case 0xf:
+ gen_op_eval_fbo();
+ break;
+ }
+}
static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
{
@@ -429,6 +514,43 @@
}
}
+static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn)
+{
+ unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
+ target += (uint32_t) dc->pc;
+ if (cond == 0x0) {
+ /* unconditional not taken */
+ if (a) {
+ dc->pc = dc->npc + 4;
+ dc->npc = dc->pc + 4;
+ } else {
+ dc->pc = dc->npc;
+ dc->npc = dc->pc + 4;
+ }
+ } else if (cond == 0x8) {
+ /* unconditional taken */
+ if (a) {
+ dc->pc = target;
+ dc->npc = dc->pc + 4;
+ } else {
+ dc->pc = dc->npc;
+ dc->npc = target;
+ }
+ } else {
+ flush_T2(dc);
+ gen_fcond(cond);
+ if (a) {
+ gen_op_branch_a((long)dc->tb, target, dc->npc);
+ dc->is_br = 1;
+ } else {
+ dc->pc = dc->npc;
+ dc->jump_pc[0] = target;
+ dc->jump_pc[1] = dc->npc + 4;
+ dc->npc = JUMP_PC;
+ }
+ }
+}
+
#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
static int sign_extend(int x, int len)
@@ -463,7 +585,12 @@
goto jmp_insn;
}
case 0x3: /* FBN+x */
- break;
+ {
+ target <<= 2;
+ target = sign_extend(target, 22);
+ do_fbranch(dc, target, insn);
+ goto jmp_insn;
+ }
case 0x4: /* SETHI */
gen_movl_imm_T0(target << 10);
gen_movl_T0_reg(rd);
@@ -518,7 +645,135 @@
goto illegal_insn;
}
} else if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
- goto illegal_insn;
+ rs1 = GET_FIELD(insn, 13, 17);
+ rs2 = GET_FIELD(insn, 27, 31);
+ xop = GET_FIELD(insn, 18, 26);
+ switch (xop) {
+ case 0x1: /* fmovs */
+ gen_op_load_fpr_FT0(rs2);
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x5: /* fnegs */
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fnegs();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x8: /* fabss */
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fabss();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x29: /* fsqrts */
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fsqrts();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x2a: /* fsqrtd */
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fsqrtd();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0x41:
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fadds();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x42:
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_faddd();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0x45:
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fsubs();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x46:
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fsubd();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0x49:
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fmuls();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x4a:
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fmuld();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0x4d:
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fdivs();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0x4e:
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fdivd();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0x51:
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fcmps();
+ break;
+ case 0x52:
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fcmpd();
+ break;
+ case 0x55: /* fcmpes */
+ gen_op_load_fpr_FT0(rs1);
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fcmps(); /* XXX */
+ break;
+ case 0x56: /* fcmped */
+ gen_op_load_fpr_DT0(rs1);
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fcmpd(); /* XXX */
+ break;
+ case 0xc4:
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fitos();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0xc6:
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fdtos();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0xc8:
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fitod();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0xc9:
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fstod();
+ gen_op_store_DT0_fpr(rd);
+ break;
+ case 0xd1:
+ gen_op_load_fpr_FT1(rs2);
+ gen_op_fstoi();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ case 0xd2:
+ gen_op_load_fpr_DT1(rs2);
+ gen_op_fdtoi();
+ gen_op_store_FT0_fpr(rd);
+ break;
+ default:
+ goto illegal_insn;
+ }
} else {
rs1 = GET_FIELD(insn, 13, 17);
gen_movl_reg_T0(rs1);
@@ -685,7 +940,7 @@
gen_movl_reg_T1(rs2);
}
gen_op_add_T1_T0();
- if (xop < 4 || xop > 7) {
+ if (xop < 4 || (xop > 7 && xop < 0x20)) {
switch (xop) {
case 0x0: /* load word */
gen_op_ld();
@@ -714,6 +969,20 @@
break;
}
gen_movl_T1_reg(rd);
+ } else if (xop >= 0x20 && xop < 0x24) {
+ switch (xop) {
+ case 0x20: /* load fpreg */
+ gen_op_ldf();
+ break;
+ case 0x21: /* load fsr */
+ gen_op_ldfsr();
+ break;
+ case 0x23: /* load double fpreg */
+ gen_op_lddf();
+ gen_op_store_FT1_fpr(rd + 1);
+ break;
+ }
+ gen_op_store_FT0_fpr(rd);
} else if (xop < 8) {
gen_movl_reg_T1(rd);
switch (xop) {
@@ -732,7 +1001,21 @@
gen_op_std();
break;
}
- }
+ } else if (xop > 0x23 && xop < 0x28) {
+ gen_op_load_fpr_FT0(rd);
+ switch (xop) {
+ case 0x24:
+ gen_op_stf();
+ break;
+ case 0x25:
+ gen_op_stfsr();
+ break;
+ case 0x27:
+ gen_op_load_fpr_FT1(rd+1);
+ gen_op_stdf();
+ break;
+ }
+ }
}
}
/* default case for non jump instructions */
@@ -857,6 +1140,24 @@
fprintf(f, "\n");
for (; i < 8; i++)
fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]);
+ fprintf(f, "\nFloating Point Registers:\n");
+ for (i = 0; i < 32; i++) {
+ if ((i & 3) == 0)
+ fprintf(f, "%%f%02d:", i);
+ fprintf(f, " %016llx", *((uint64_t *)&env->fpr[i]));
+ if ((i & 3) == 3)
+ fprintf(f, "\n");
+ }
+ for (i = 0; i < 32; i++) {
+ if ((i & 3) == 0)
+ fprintf(f, "%%f%02d:", i);
+ fprintf(f, " %016lf", env->fpr[i]);
+ if ((i & 3) == 3)
+ fprintf(f, "\n");
+ }
+ fprintf(f, "\nFloating Point Temp: %016llx %016llx %016llx\n",
*((uint64_t *)&env->ft0), *((uint64_t *)&env->ft1), *((uint64_t
*)&env->ft2));
+ fprintf(f, "%016F %016F %016F\n", env->ft0, env->ft1, env->ft2);
+
fprintf(f, "\nCurrent Register Window:\n");
for (x = 0; x < 3; x++) {
for (i = 0; i < 4; i++)
@@ -874,6 +1175,7 @@
GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
env->wim);
+ fprintf(f, "fsr: 0x%08x\n", env->fsr);
}
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
--- qemu-0.6.0.orig/target-sparc/op_helper.c 1970-01-01 01:00:00.000000000
+0100
+++ qemu-0.6.0/target-sparc/op_helper.c 2004-08-03 21:48:51.000000000 +0200
@@ -0,0 +1,46 @@
+#include <math.h>
+#include "exec.h"
+
+void OPPROTO do_fabss(void)
+{
+ FT0 = fabsf(FT1);
+}
+
+void OPPROTO do_fsqrts(void)
+{
+ FT0 = sqrtf(FT1);
+}
+
+void OPPROTO do_fsqrtd(void)
+{
+ DT0 = sqrt(DT1);
+}
+
+void OPPROTO do_fcmps (void)
+{
+ if (isnan(FT0) || isnan(FT1)) {
+ T0 = FSR_FCC1 | FSR_FCC0;
+ } else if (FT0 < FT1) {
+ T0 = FSR_FCC0;
+ } else if (FT0 > FT1) {
+ T0 = FSR_FCC1;
+ } else {
+ T0 = 0;
+ }
+ env->fsr = T0;
+}
+
+void OPPROTO do_fcmpd (void)
+{
+ if (isnan(DT0) || isnan(DT1)) {
+ T0 = FSR_FCC1 | FSR_FCC0;
+ } else if (DT0 < DT1) {
+ T0 = FSR_FCC0;
+ } else if (DT0 > DT1) {
+ T0 = FSR_FCC1;
+ } else {
+ T0 = 0;
+ }
+ env->fsr = T0;
+}
+
_________________________________________________________________
Add photos to your e-mail with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] Patch: Basic Sparc Floating point support,
Blue Swirl <=