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