[hatari-devel] FPU status register handling & fmovem.x bugs |
[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]
Hi,
while running some tests, i get some errors when running them on Hatari. The source & binaries are attached. From the fmovem.x in lines 34-49 i get following errors:
fmovem.c:45: test 1(0): expected 40000000:c90fdaa2:2168c235 got 40000000:c90fdaa2:2168c000 Looks like some bits are truncated during the move.
The write/read of fpcr on line 61 gives:
fmovem.c:61: test 2(0): expected 0x0000fff0, got 0x0000ffff According to the manual, bits 0-3 should be read as zero.
And the write/read of the fpsr yields:
fmovem.c:74: test 3(0): expected 0x0fffffff, got 0xffffffff
moveq #-1,d0 that is, it sets all flags for neg/nan/zero/inf. Of course, such a status could never result from some FP operation, since a result cannot be a nan and inf at the same time. Can someone verify what this test yields on real hw?
|
/* * Test:USES_FPU */ #define JIT_LOOPS 1 #include "testdriver.h" #ifndef __HAVE_68881__ #error "must be compiled with FPU support" #endif int numtests; union ld_union pi_ln2[2] = { { { 0x40000000L, 0xc90fdaa2L, 0x2168C235L } }, { { 0x3ffe0000L, 0xb17217f7L, 0xd1cf79acL } } }; int main(void) { int status; union ld_union fp[4]; long a0; long a1; long a2; long d0, fpcr, fpsr, fpiar; int i; status = 0; ++numtests; for (i = 0; i < JIT_LOOPS; i++) { __asm__ __volatile__( "\tmove.l %[a0],%[a1]\n" "\tfmovem.x (%[a0]),%%fp0/%%fp1\n" "\tfmovem.x %%fp0/%%fp1,(%[a2])\n" "\tfmovem.x (%[a0])+,%%fp2/%%fp3\n" "\tfmovem.x %%fp2/%%fp3,24(%[a2])\n" "\tsuba.l %[a1],%[a0]\n" : [a0]"=a"(a0), [a1]"=a"(a1), [a2]"=a"(a2) : "[a0]"(pi_ln2), "[a2]"(fp) : "cc", "fp0", "fp1", "fp2", "fp3", "memory"); EXPECTN(a0, 24L); EXPECT_FPN(fp[0], 0x40000000L, 0xc90fdaa2L, 0x2168C235L); EXPECT_FPN(fp[1], 0x3ffe0000L, 0xb17217f7L, 0xd1cf79acL); EXPECT_FPN(fp[2], 0x40000000L, 0xc90fdaa2L, 0x2168C235L); EXPECT_FPN(fp[3], 0x3ffe0000L, 0xb17217f7L, 0xd1cf79acL); } ++numtests; for (i = 0; i < JIT_LOOPS; i++) { __asm__ __volatile__( "\tmoveq #-1,%[d0]\n" "\tfmove.l %[d0],%%fpcr\n" "\tfmove.l %%fpcr,%[fpcr]\n" : [d0]"=d"(d0), [fpcr]"=d"(fpcr) : : "cc", "memory"); EXPECTN(fpcr, 0xfff0L); } ++numtests; for (i = 0; i < JIT_LOOPS; i++) { __asm__ __volatile__( "\tmoveq #-1,%[d0]\n" "\tfmove.l %[d0],%%fpsr\n" "\tfmove.l %%fpsr,%[fpsr]\n" : [d0]"=d"(d0), [fpsr]"=d"(fpsr) : : "cc", "memory"); EXPECTN(fpsr, 0x0fffffffL); } ++numtests; for (i = 0; i < JIT_LOOPS; i++) { __asm__ __volatile__( "\tgetfpiar:\n" "\tfabs.x %[fp0]\n" "\tlea getfpiar(%%pc),%[a0]\n" "\tfmove.l %%fpiar,%[fpiar]\n" : [fpiar]"=d"(fpiar), [a0]"=a"(a0), [fp0]"=f"(fp[0].d) : : "cc", "memory"); /* * disabled for now; does not work reliable in most emulators, * who cares? */ #if 0 EXPECTN(fpiar, a0); #endif } return status; }
Attachment:
fmovem.ttp
Description: application/wine-extension-ttp
#include <stdio.h> #ifdef LIBCMINI #define CR "\r" #else #define CR #endif /* * set to 1 to allow for small differences in the last few * bits of floating point values, * since at least the JIT compiler cannot guarantee bit exactness * in all cases */ #define ALLOW_INEXACT 1 #ifndef JIT_LOOPS # define JIT_LOOPS 128 #endif union ld_union { unsigned long v[3]; long double d; }; #define CHECK(var) \ if (var) \ { \ fprintf(stderr, "%s:%d: test %d: failed" CR "\n", __FILE__, __LINE__, numtests); \ status |= 1; \ } #define CHECKN(var) \ if (var) \ { \ fprintf(stderr, "%s:%d: test %d(%d): failed" CR "\n", __FILE__, __LINE__, numtests, i); \ status |= 1; \ } #define CHECK_ONCE(var) \ if (var) \ { \ if (!reported) { fprintf(stderr, "%s:%d: test %d: failed" CR "\n", __FILE__, __LINE__, numtests); reported = 1; } \ status |= 1; \ } #define EXPECT_FP(f, v0, v1, v2) \ if (f.v[0] != v0 || f.v[1] != v1 || f.v[2] != v2) \ { \ fprintf(stderr, "%s:%d: test %d: expected %08lx:%08lx:%08lx got %08lx:%08lx:%08lx" CR "\n", __FILE__, __LINE__, numtests, v0, v1, v2, f.v[0], f.v[1], f.v[2]); \ status |= 1; \ } #define EXPECT_FPN(f, v0, v1, v2) \ if (f.v[0] != v0 || f.v[1] != v1 || f.v[2] != v2) \ { \ fprintf(stderr, "%s:%d: test %d(%d): expected %08lx:%08lx:%08lx got %08lx:%08lx:%08lx" CR "\n", __FILE__, __LINE__, numtests, i, v0, v1, v2, f.v[0], f.v[1], f.v[2]); \ status |= 1; \ } #if ALLOW_INEXACT #define EXPECT_FP_INEXACT(f, v0, v1, v2) \ if (f.v[0] != v0 || f.v[1] != v1 || (f.v[2] & 0xFFFFFFFCL) != ((v2) & 0xFFFFFFFCL)) \ { \ fprintf(stderr, "%s:%d: test %d: expected %08lx:%08lx:%08lx got %08lx:%08lx:%08lx" CR "\n", __FILE__, __LINE__, numtests, v0, v1, v2, f.v[0], f.v[1], f.v[2]); \ status |= 1; \ } #define EXPECT_FP_INEXACTN(f, v0, v1, v2) \ if (f.v[0] != v0 || f.v[1] != v1 || (f.v[2] & 0xFFFFFFFCL) != ((v2) & 0xFFFFFFFCL)) \ { \ fprintf(stderr, "%s:%d: test %d(%d): expected %08lx:%08lx:%08lx got %08lx:%08lx:%08lx" CR "\n", __FILE__, __LINE__, numtests, i, v0, v1, v2, f.v[0], f.v[1], f.v[2]); \ status |= 1; \ } #else #define EXPECT_FP_INEXACT(f, v0, v1, v2) EXPECT_FP(f, v0, v1, v2) #define EXPECT_FP_INEXACTN(f, v0, v1, v2) EXPECT_FPN(f, v0, v1, v2) #endif #define EXPECT(r, v) \ if ((r) != (v)) \ { \ fprintf(stderr, "%s:%d: test %d: expected 0x%08lx, got 0x%08lx" CR "\n", __FILE__, __LINE__, numtests, v, r); \ status |= 1; \ } #define EXPECTN(r, v) \ if ((r) != (v)) \ { \ fprintf(stderr, "%s:%d: test %d(%d): expected 0x%08lx, got 0x%08lx" CR "\n", __FILE__, __LINE__, numtests, i, v, r); \ status |= 1; \ } /* * enable: * -1: query only * 0/1: disable/enable * returns: * previous state as 0/1, or -1 if JIT is not available */ static __inline int jit_state(int enable) { register long state __asm__("d0"); __asm__ __volatile__( "\t.dc.w 0x713b\n" /* M68K_EMUL_OP_JIT */ : "=d"(state) : "0"(enable) : "cc", "memory"); return state; }
Mail converted by MHonArc 2.6.19+ | http://listengine.tuxfamily.org/ |