[parisc-linux] unaligned.c changes

LaMont Jones lamont@smallone.fc.hp.com
Tue, 8 Jul 2003 23:18:10 -0600


--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I just committed the following changes to unaligned.c, so that we now
handle unaligned floating point loads/stores, as well as getting a bit
better about noticing 64-bit (pa2.0) general register ops on a 32-bit
kernel.

lamont

--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Description: 2.4 patch
Content-Disposition: attachment; filename="2.4"

Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- arch/parisc/kernel/unaligned.c	26 Jan 2003 20:59:10 -0000	1.15
+++ arch/parisc/kernel/unaligned.c	9 Jul 2003 05:15:20 -0000	1.16
@@ -92,6 +92,15 @@
 #define OPCODE_STWA	OPCODE1(0x03,1,0xe)
 #define OPCODE_STDA	OPCODE1(0x03,1,0xf)
 
+#define OPCODE_FLDWX	OPCODE1(0x09,0,0x0)
+#define OPCODE_FSTWX	OPCODE1(0x09,0,0x4)
+#define OPCODE_FLDWS	OPCODE1(0x09,1,0x0)
+#define OPCODE_FSTWS	OPCODE1(0x09,1,0x4)
+#define OPCODE_FLDDX	OPCODE1(0x0b,0,0x0)
+#define OPCODE_FSTDX	OPCODE1(0x0b,0,0x4)
+#define OPCODE_FLDDS	OPCODE1(0x0b,1,0x0)
+#define OPCODE_FSTDS	OPCODE1(0x0b,1,0x4)
+
 #define OPCODE_LDD_L	OPCODE2(0x14,0)
 #define OPCODE_FLDD_L	OPCODE2(0x14,1)
 #define OPCODE_STD_L	OPCODE2(0x1c,0)
@@ -113,6 +122,7 @@
 #define R1(i) (((i)>>21)&0x1f)
 #define R2(i) (((i)>>16)&0x1f)
 #define R3(i) ((i)&0x1f)
+#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
 #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
 #define IM5_2(i) IM((i)>>16,5)
 #define IM5_3(i) IM((i),5)
@@ -146,7 +156,7 @@
 
 	return 0;
 }
-static int emulate_ldw(struct pt_regs *regs, int toreg)
+static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
 	unsigned long val = 0;
@@ -169,20 +179,26 @@
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		((__u32*)(regs->fr))[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_ldd(struct pt_regs *regs, int toreg)
+static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
-	unsigned long val = 0;
+	__u64 val = 0;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", 
 		regs->isr, regs->ior, toreg);
+#ifdef CONFIG_PA20
 
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__  (
 "	depd,z	%2,60,3,%%r19\n"		/* r19=(ofs&7)*8 */
 "	mtsp	%3, %%sr1\n"
@@ -195,15 +211,36 @@
 	: "=r" (val)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
+#else
+    {
+	unsigned long valh=0,vall=0;
+	__asm__ __volatile__  (
+"	zdep	%4,29,2,%%r19\n"		/* r19=(ofs&3)*8 */
+"	mtsp	%5, %%sr1\n"
+"	dep	%%r0,31,2,%4\n"
+"	ldw	0(%%sr1,%5),%0\n"
+"	ldw	4(%%sr1,%5),%1\n"
+"	ldw	8(%%sr1,%5),%%r20\n"
+"	subi	32,%%r19,%%r19\n"
+"	mtsar	%%r19\n"
+"	vshd	%0,%1,%0\n"
+"	vshd	%1,%%r20,%1\n"
+	: "=r" (valh), "=r" (vall)
+	: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
+	: "r19", "r20" );
+	val=((__u64)valh<<32)|(__u64)vall;
+    }
+#endif
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		regs->fr[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#endif
 
 static int emulate_sth(struct pt_regs *regs, int frreg)
 {
@@ -212,7 +249,7 @@
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
@@ -225,14 +262,19 @@
 
 	return 0;
 }
-static int emulate_stw(struct pt_regs *regs, int frreg)
+static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
+	unsigned long val;
+
+	if (flop)
+		val = ((__u32*)(regs->fr))[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 
 	__asm__ __volatile__ (
@@ -257,17 +299,25 @@
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_std(struct pt_regs *regs, int frreg)
+static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
-		val = 0;
+	__u64 val;
 
-	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+	if (flop)
+		val = regs->fr[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
+		val = 0;
 
+	DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
+		val,  regs->isr, regs->ior);
 
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
 "	depd,z	%1, 60, 3, %%r19\n"
@@ -287,19 +337,45 @@
 	:
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1" );
+#else
+    {
+	unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+	__asm__ __volatile__ (
+"	mtsp	%3, %%sr1\n"
+"	zdep	%1, 29, 2, %%r19\n"
+"	dep	%%r0, 31, 2, %1\n"
+"	mtsar	%%r19\n"
+"	zvdepi	-2, 32, %%r19\n"
+"	ldw	0(%%sr1,%2),%%r20\n"
+"	ldw	8(%%sr1,%2),%%r21\n"
+"	vshd	%0, %1, %%r1\n"
+"	vshd	%%r0, %0, %0\n"
+"	vshd	%1, %%r0, %1\n"
+"	and	%%r20, %%r19, %%r20\n"
+"	andcm	%%r21, %%r19, %%r21\n"
+"	or	%0, %%r20, %0\n"
+"	or	%1, %%r21, %1\n"
+"	stw	%0,0(%%sr1,%2)\n"
+"	stw	%%r1,4(%%sr1,%2)\n"
+"	stw	%1,8(%%sr1,%2)\n"
+	:
+	: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
+	: "r19", "r20", "r21", "r1" );
+    }
+#endif
 
 	return 0;
 }
-#endif
 
 void handle_unaligned(struct pt_regs *regs)
 {
 	unsigned long unaligned_count = 0;
 	unsigned long last_time = 0;
-	unsigned long newbase = regs->gr[R1(regs->iir)];
+        unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
 	int modify = 0;
 	int ret = -1;
 	struct siginfo si;
+	register int flop=0;	/* true if this is a flop */
 
 	/* if the unaligned access is inside the kernel:
 	 *   if the access is caused by a syscall, then we fault the calling
@@ -438,7 +514,7 @@
 	case OPCODE_LDWA_I:
 	case OPCODE_LDW_S:
 	case OPCODE_LDWA_S:
-		ret = emulate_ldw(regs, R3(regs->iir));
+		ret = emulate_ldw(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STH:
@@ -447,23 +523,47 @@
 
 	case OPCODE_STW:
 	case OPCODE_STWA:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	case OPCODE_LDD_I:
 	case OPCODE_LDDA_I:
 	case OPCODE_LDD_S:
 	case OPCODE_LDDA_S:
-		ret = emulate_ldd(regs, R3(regs->iir));
+		ret = emulate_ldd(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STD:
 	case OPCODE_STDA:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
 #endif
 
+	case OPCODE_FLDWX:
+	case OPCODE_FLDWS:
+		flop=1;
+		ret = emulate_ldw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FLDDX:
+	case OPCODE_FLDDS:
+		flop=1;
+		ret = emulate_ldd(regs,R3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTWX:
+	case OPCODE_FSTWS:
+		flop=1;
+		ret = emulate_stw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTDX:
+	case OPCODE_FSTDS:
+		flop=1;
+		ret = emulate_std(regs,R3(regs->iir),1);
+		break;
+
 	case OPCODE_LDCD_I:
 	case OPCODE_LDCW_I:
 	case OPCODE_LDCD_S:
@@ -471,30 +571,44 @@
 		ret = -1;	/* "undefined", but lets kill them. */
 		break;
 	}
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	switch (regs->iir & OPCODE2_MASK)
 	{
-	case OPCODE_LDD_L:
 	case OPCODE_FLDD_L:
-		ret = emulate_ldd(regs, R2(regs->iir));
+		flop=1;
+		ret = emualate_ldd(regs,R2(regs->iir),1);
+		break;
+	case OPCODE_FSTD_L:
+		flop=1;
+		ret = emulate_std(regs, R2(regs->iir),1);
 		break;
 
+#ifdef CONFIG_PA20
+	case OPCODE_LDD_L:
+		ret = emulate_ldd(regs, R2(regs->iir),0);
+		break;
 	case OPCODE_STD_L:
-	case OPCODE_FSTD_L:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
+#endif
 	}
 #endif
 	switch (regs->iir & OPCODE3_MASK)
 	{
-	case OPCODE_LDW_M:
 	case OPCODE_FLDW_L:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		flop=1;
+		ret = emulate_ldw(regs, R2(regs->iir),0);
+		break;
+	case OPCODE_LDW_M:
+		ret = emulate_ldw(regs, R2(regs->iir),1);
 		break;
 
 	case OPCODE_FSTW_L:
+		flop=1;
+		ret = emulate_stw(regs, R2(regs->iir),1);
+		break;
 	case OPCODE_STW_M:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
 	switch (regs->iir & OPCODE4_MASK)
@@ -504,17 +618,16 @@
 		break;
 	case OPCODE_LDW_L:
 	case OPCODE_LDWM:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		ret = emulate_ldw(regs, R2(regs->iir),0);
 		break;
 	case OPCODE_STH_L:
 		ret = emulate_sth(regs, R2(regs->iir));
 		break;
 	case OPCODE_STW_L:
 	case OPCODE_STWM:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
-	/* XXX LJ - need to handle float load/store */
 
 	if (modify && R1(regs->iir))
 		regs->gr[R1(regs->iir)] = newbase;
@@ -540,9 +653,8 @@
 		return;
 	}
 
-	/* else we handled it, advance the PC.... */
-	regs->iaoq[0] = regs->iaoq[1];
-	regs->iaoq[1] = regs->iaoq[0] + 4;
+	/* else we handled it, let life go on. */
+	regs->gr[0]|=PSW_N;
 }
 
 /*

--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Description: 2.5 patch
Content-Disposition: attachment; filename="2.5"

Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- arch/parisc/kernel/unaligned.c	12 Jan 2003 08:24:26 -0000	1.4
+++ arch/parisc/kernel/unaligned.c	9 Jul 2003 05:15:38 -0000	1.5
@@ -92,6 +92,15 @@
 #define OPCODE_STWA	OPCODE1(0x03,1,0xe)
 #define OPCODE_STDA	OPCODE1(0x03,1,0xf)
 
+#define OPCODE_FLDWX	OPCODE1(0x09,0,0x0)
+#define OPCODE_FSTWX	OPCODE1(0x09,0,0x4)
+#define OPCODE_FLDWS	OPCODE1(0x09,1,0x0)
+#define OPCODE_FSTWS	OPCODE1(0x09,1,0x4)
+#define OPCODE_FLDDX	OPCODE1(0x0b,0,0x0)
+#define OPCODE_FSTDX	OPCODE1(0x0b,0,0x4)
+#define OPCODE_FLDDS	OPCODE1(0x0b,1,0x0)
+#define OPCODE_FSTDS	OPCODE1(0x0b,1,0x4)
+
 #define OPCODE_LDD_L	OPCODE2(0x14,0)
 #define OPCODE_FLDD_L	OPCODE2(0x14,1)
 #define OPCODE_STD_L	OPCODE2(0x1c,0)
@@ -113,6 +122,7 @@
 #define R1(i) (((i)>>21)&0x1f)
 #define R2(i) (((i)>>16)&0x1f)
 #define R3(i) ((i)&0x1f)
+#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
 #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
 #define IM5_2(i) IM((i)>>16,5)
 #define IM5_3(i) IM((i),5)
@@ -146,7 +156,7 @@
 
 	return 0;
 }
-static int emulate_ldw(struct pt_regs *regs, int toreg)
+static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
 	unsigned long val = 0;
@@ -169,20 +179,26 @@
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		((__u32*)(regs->fr))[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_ldd(struct pt_regs *regs, int toreg)
+static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 {
 	unsigned long saddr = regs->ior;
-	unsigned long val = 0;
+	__u64 val = 0;
 
 	DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", 
 		regs->isr, regs->ior, toreg);
+#ifdef CONFIG_PA20
 
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__  (
 "	depd,z	%2,60,3,%%r19\n"		/* r19=(ofs&7)*8 */
 "	mtsp	%3, %%sr1\n"
@@ -195,15 +211,36 @@
 	: "=r" (val)
 	: "0" (val), "r" (saddr), "r" (regs->isr)
 	: "r19", "r20" );
+#else
+    {
+	unsigned long valh=0,vall=0;
+	__asm__ __volatile__  (
+"	zdep	%4,29,2,%%r19\n"		/* r19=(ofs&3)*8 */
+"	mtsp	%5, %%sr1\n"
+"	dep	%%r0,31,2,%4\n"
+"	ldw	0(%%sr1,%5),%0\n"
+"	ldw	4(%%sr1,%5),%1\n"
+"	ldw	8(%%sr1,%5),%%r20\n"
+"	subi	32,%%r19,%%r19\n"
+"	mtsar	%%r19\n"
+"	vshd	%0,%1,%0\n"
+"	vshd	%1,%%r20,%1\n"
+	: "=r" (valh), "=r" (vall)
+	: "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
+	: "r19", "r20" );
+	val=((__u64)valh<<32)|(__u64)vall;
+    }
+#endif
 
 	DPRINTF("val = 0x" RFMT "\n", val);
 
-	if (toreg)
+	if (flop)
+		regs->fr[toreg] = val;
+	else if (toreg)
 		regs->gr[toreg] = val;
 
 	return 0;
 }
-#endif
 
 static int emulate_sth(struct pt_regs *regs, int frreg)
 {
@@ -212,7 +249,7 @@
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 2 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
@@ -225,14 +262,19 @@
 
 	return 0;
 }
-static int emulate_stw(struct pt_regs *regs, int frreg)
+static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
+	unsigned long val;
+
+	if (flop)
+		val = ((__u32*)(regs->fr))[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
 		val = 0;
 
 	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 4 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+		val, regs->isr, regs->ior);
 
 
 	__asm__ __volatile__ (
@@ -257,17 +299,25 @@
 
 	return 0;
 }
-#ifdef __LP64__
-static int emulate_std(struct pt_regs *regs, int frreg)
+static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 {
-	unsigned long val = regs->gr[frreg];
-	if (!frreg)
-		val = 0;
+	__u64 val;
 
-	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
-		regs->gr[frreg], regs->isr, regs->ior);
+	if (flop)
+		val = regs->fr[frreg];
+	else if (frreg)
+		val = regs->gr[frreg];
+	else
+		val = 0;
 
+	DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, 
+		val,  regs->isr, regs->ior);
 
+#ifdef CONFIG_PA20
+#ifndef __LP64__
+	if (!flop)
+		return -1;
+#endif
 	__asm__ __volatile__ (
 "	mtsp %2, %%sr1\n"
 "	depd,z	%1, 60, 3, %%r19\n"
@@ -287,19 +337,45 @@
 	:
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1" );
+#else
+    {
+	unsigned long valh=(val>>32),vall=(val&0xffffffffl);
+	__asm__ __volatile__ (
+"	mtsp	%3, %%sr1\n"
+"	zdep	%1, 29, 2, %%r19\n"
+"	dep	%%r0, 31, 2, %1\n"
+"	mtsar	%%r19\n"
+"	zvdepi	-2, 32, %%r19\n"
+"	ldw	0(%%sr1,%2),%%r20\n"
+"	ldw	8(%%sr1,%2),%%r21\n"
+"	vshd	%0, %1, %%r1\n"
+"	vshd	%%r0, %0, %0\n"
+"	vshd	%1, %%r0, %1\n"
+"	and	%%r20, %%r19, %%r20\n"
+"	andcm	%%r21, %%r19, %%r21\n"
+"	or	%0, %%r20, %0\n"
+"	or	%1, %%r21, %1\n"
+"	stw	%0,0(%%sr1,%2)\n"
+"	stw	%%r1,4(%%sr1,%2)\n"
+"	stw	%1,8(%%sr1,%2)\n"
+	:
+	: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
+	: "r19", "r20", "r21", "r1" );
+    }
+#endif
 
 	return 0;
 }
-#endif
 
 void handle_unaligned(struct pt_regs *regs)
 {
 	unsigned long unaligned_count = 0;
 	unsigned long last_time = 0;
-	unsigned long newbase = regs->gr[R1(regs->iir)];
+	unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
 	int modify = 0;
 	int ret = -1;
 	struct siginfo si;
+	register int flop=0;	/* true if this is a flop */
 
 	/* if the unaligned access is inside the kernel:
 	 *   if the access is caused by a syscall, then we fault the calling
@@ -383,9 +459,9 @@
 				case OPCODE_LDDA_I:
 					shift= 3; break;
 				}
-				newbase += regs->gr[R2(regs->iir)]<<shift;
+				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0)<<shift;
 			} else				/* simple indexed */
-				newbase += regs->gr[R2(regs->iir)];
+				newbase += (R2(regs->iir)?regs->gr[R2(regs->iir)]:0);
 		}
 		break;
 	case 0x13:
@@ -438,7 +514,7 @@
 	case OPCODE_LDWA_I:
 	case OPCODE_LDW_S:
 	case OPCODE_LDWA_S:
-		ret = emulate_ldw(regs, R3(regs->iir));
+		ret = emulate_ldw(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STH:
@@ -447,23 +523,47 @@
 
 	case OPCODE_STW:
 	case OPCODE_STWA:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	case OPCODE_LDD_I:
 	case OPCODE_LDDA_I:
 	case OPCODE_LDD_S:
 	case OPCODE_LDDA_S:
-		ret = emulate_ldd(regs, R3(regs->iir));
+		ret = emulate_ldd(regs, R3(regs->iir),0);
 		break;
 
 	case OPCODE_STD:
 	case OPCODE_STDA:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
 #endif
 
+	case OPCODE_FLDWX:
+	case OPCODE_FLDWS:
+		flop=1;
+		ret = emulate_ldw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FLDDX:
+	case OPCODE_FLDDS:
+		flop=1;
+		ret = emulate_ldd(regs,R3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTWX:
+	case OPCODE_FSTWS:
+		flop=1;
+		ret = emulate_stw(regs,FR3(regs->iir),1);
+		break;
+
+	case OPCODE_FSTDX:
+	case OPCODE_FSTDS:
+		flop=1;
+		ret = emulate_std(regs,R3(regs->iir),1);
+		break;
+
 	case OPCODE_LDCD_I:
 	case OPCODE_LDCW_I:
 	case OPCODE_LDCD_S:
@@ -471,30 +571,44 @@
 		ret = -1;	/* "undefined", but lets kill them. */
 		break;
 	}
-#ifdef __LP64__
+#ifdef CONFIG_PA20
 	switch (regs->iir & OPCODE2_MASK)
 	{
-	case OPCODE_LDD_L:
 	case OPCODE_FLDD_L:
-		ret = emulate_ldd(regs, R2(regs->iir));
+		flop=1;
+		ret = emualate_ldd(regs,R2(regs->iir),1);
+		break;
+	case OPCODE_FSTD_L:
+		flop=1;
+		ret = emulate_std(regs, R2(regs->iir),1);
 		break;
 
+#ifdef CONFIG_PA20
+	case OPCODE_LDD_L:
+		ret = emulate_ldd(regs, R2(regs->iir),0);
+		break;
 	case OPCODE_STD_L:
-	case OPCODE_FSTD_L:
-		ret = emulate_std(regs, R2(regs->iir));
+		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
+#endif
 	}
 #endif
 	switch (regs->iir & OPCODE3_MASK)
 	{
-	case OPCODE_LDW_M:
 	case OPCODE_FLDW_L:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		flop=1;
+		ret = emulate_ldw(regs, R2(regs->iir),0);
+		break;
+	case OPCODE_LDW_M:
+		ret = emulate_ldw(regs, R2(regs->iir),1);
 		break;
 
 	case OPCODE_FSTW_L:
+		flop=1;
+		ret = emulate_stw(regs, R2(regs->iir),1);
+		break;
 	case OPCODE_STW_M:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
 	switch (regs->iir & OPCODE4_MASK)
@@ -504,19 +618,18 @@
 		break;
 	case OPCODE_LDW_L:
 	case OPCODE_LDWM:
-		ret = emulate_ldw(regs, R2(regs->iir));
+		ret = emulate_ldw(regs, R2(regs->iir),0);
 		break;
 	case OPCODE_STH_L:
 		ret = emulate_sth(regs, R2(regs->iir));
 		break;
 	case OPCODE_STW_L:
 	case OPCODE_STWM:
-		ret = emulate_stw(regs, R2(regs->iir));
+		ret = emulate_stw(regs, R2(regs->iir),0);
 		break;
 	}
-	/* XXX LJ - need to handle float load/store */
 
-	if (modify)
+	if (modify && R1(regs->iir))
 		regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -540,9 +653,8 @@
 		return;
 	}
 
-	/* else we handled it, advance the PC.... */
-	regs->iaoq[0] = regs->iaoq[1];
-	regs->iaoq[1] = regs->iaoq[0] + 4;
+	/* else we handled it, let life go on. */
+	regs->gr[0]|=PSW_N;
 }
 
 /*

--GvXjxJ+pjyke8COw--