[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
fmovem.c:46: test 1(0): expected 3ffe0000:b17217f7:d1cf79ac got 3ffe0000:b17217f7:d1cf7800
fmovem.c:47: test 1(0): expected 40000000:c90fdaa2:2168c235 got 40000000:c90fdaa2:2168c000
fmovem.c:48: test 1(0): expected 3ffe0000:b17217f7:d1cf79ac got 3ffe0000:b17217f7:d1cf7800

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

Similar here, bits 28-31 should be read as zero. An interesting question though whether the expectation of the status flags i correct. The code does

 

                       moveq #-1,d0
                       fmove.l d0,fpsr
                       fmove.l fpsr,return_value

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/