qemu-devel
[Top][All Lists]
Advanced

[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 *) &REG);
+}
+
+void OPPROTO glue(op_store_DT0_fpr_fpr, REGNAME)(void)
+{
+    *((double *) &REG) = DT0;
+}
+
+void OPPROTO glue(op_load_fpr_DT1_fpr, REGNAME)(void)
+{
+    DT1 = *((double *) &REG);
+}
+
+void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
+{
+    *((double *) &REG) = DT1;
+}
+
+void OPPROTO glue(op_load_fpr_DT2_fpr, REGNAME)(void)
+{
+    DT2 = *((double *) &REG);
+}
+
+void OPPROTO glue(op_store_DT2_fpr_fpr, REGNAME)(void)
+{
+    *((double *) &REG) = 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]