| [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/ |