Subject: Re: MIPS switched to new-toolchain
To: None <thorpej@wasabisystems.com>
From: enami tsugutomo <enami@sm.sony.co.jp>
List: port-hpcmips
Date: 01/10/2002 17:27:45
Jason R Thorpe <thorpej@wasabisystems.com> writes:

> I think this is an FP emulation problem, not a compiler problem.

Actually, it was a bug in fpemu.c.

This is simplified test case:
enami@sigfpe% cat c.c
double e = 20;
int ok;
main()
{

	ok = (e >= 20);
	printf("%d\n", ok);
}
enami@sigfpe%

And whether the bug is appeared or not depends instruction in the
delay slot of `bc1t'.  gcc -O2 emits ``sw'' while -O1 emits ``li''.

When bc1t ...; sw ...; case, finaly update_pc() in fpemu.c is called.
In the function, there is an expression
``curpcb->pcb_fpregs.r_regs[FSR]'' but FSR (defined as FPBASE + 32)
isn't right value to use as an index of r_regs[] here (and constant 32
instead FSR is used in other place!).  And as a result, PC wasn't
updated correctly.

How about following change?

enami.

Index: include/pcb.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/include/pcb.h,v
retrieving revision 1.12
diff -u -r1.12 pcb.h
--- include/pcb.h	2001/10/16 16:31:34	1.12
+++ include/pcb.h	2002/01/10 08:02:16
@@ -67,4 +67,6 @@
 #ifdef _KERNEL
 extern struct pcb *curpcb;			/* the current running pcb */
 extern struct segtab *segbase;			/* current segtab base */
+
+#define	PCB_FSR(pcb)	((pcb)->pcb_fpregs.r_regs[FSR - FPBASE])
 #endif
Index: mips/db_interface.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/db_interface.c,v
retrieving revision 1.38
diff -u -r1.38 db_interface.c
--- mips/db_interface.c	2001/11/14 18:15:21	1.38
+++ mips/db_interface.c	2002/01/10 08:02:16
@@ -550,7 +550,7 @@
 	vaddr_t ra;
 	unsigned fpucsr;
 
-	fpucsr = (curproc) ? curproc->p_addr->u_pcb.pcb_fpregs.r_regs[32] : 0;
+	fpucsr = curproc ? PCB_FSR(&curproc->p_addr->u_pcb) : 0;
 	ra = MachEmulateBranch((struct frame *)regs, pc, fpucsr, 0);
 	return ra;
 }
Index: mips/fpemu.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/fpemu.c,v
retrieving revision 1.7
diff -u -r1.7 fpemu.c
--- mips/fpemu.c	2001/10/16 16:31:36	1.7
+++ mips/fpemu.c	2002/01/10 08:02:16
@@ -85,9 +85,10 @@
 	struct frame *frame;
 	u_int32_t cause;
 {
+
 	if (cause & MIPS_CR_BR_DELAY)
 		frame->f_regs[PC] = MachEmulateBranch(frame, frame->f_regs[PC],
-			curpcb->pcb_fpregs.r_regs[FSR], 0);
+		    PCB_FSR(curpcb), 0);
 	else
 		frame->f_regs[PC] += 4;
 }
Index: mips/trap.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/trap.c,v
retrieving revision 1.166
diff -u -r1.166 trap.c
--- mips/trap.c	2001/12/28 02:13:14	1.166
+++ mips/trap.c	2002/01/10 08:02:18
@@ -749,7 +749,7 @@
 	pc = (vaddr_t)f->f_regs[PC];
 	if (fuiword((void *)pc) != 0) /* not a NOP instruction */
 		va = MachEmulateBranch(f, pc,
-			p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1);
+		    PCB_FSR(&p->p_addr->u_pcb), 1);
 	else
 		va = pc + sizeof(int);
 	p->p_md.md_ss_addr = va;