shithub: riscv

Download patch

ref: 0dbde06bc74732e844879e11fff12b033ca28e65
parent: 408f1beaa2f4ea5de1657cfdc4a9062aeeaeab07
parent: f166778ce3ae398fee849be40d8d60dd577e21ad
author: cinap_lenrek <[email protected]>
date: Mon Jun 10 16:43:35 EDT 2013

merge with jpathy

--- a/sys/src/cmd/5e/5e.c
+++ b/sys/src/cmd/5e/5e.c
@@ -48,7 +48,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: 5e [-npb] text [...]\n");
+	fprint(2, "usage: 5e [-npbf] text [...]\n");
 	exits(nil);
 }
 
@@ -103,6 +103,7 @@
 	case 'n': nflag++; break;
 	case 'p': pflag++; break;
 	case 'b': bflag++; break;
+	case 'f': vfp = 1; break;
 	default: usage();
 	} ARGEND;
 	if(argc < 1)
--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -473,6 +473,12 @@
 		fpaoperation(instr);
 	else if((instr & 0x0E000F10) == 0x0E000110)
 		fparegtransfer(instr);
+	else if(vfp && ((instr & 0x0F000A10) == 0x0E000A00))
+		vfpoperation(instr);
+	else if(vfp && ((instr & 0x0F000F10) == 0x0E000A10))
+		vfpregtransfer(instr);
+	else if(vfp && ((instr & 0x0F000A00) == 0x0D000A00))
+		vfprmtransfer(instr);
 	else
 		invalid(instr);
 }
--- a/sys/src/cmd/5e/dat.h
+++ b/sys/src/cmd/5e/dat.h
@@ -8,6 +8,7 @@
 	NAMEMAX = 27,
 	NNOTE = 5,
 	SEGNUM = 8,
+	Nfpregs = 16,
 
 	flN = 1<<31,
 	flZ = 1<<30,
@@ -34,7 +35,7 @@
 	u32int CPSR;		/* status register */
 	
 	u32int FPSR;
-	long double F[8];
+	long double F[Nfpregs];
 
 	char errbuf[ERRMAX];
 	Fd *fd;			/* bitmap of OCEXEC files */
@@ -46,6 +47,8 @@
 	char notes[ERRMAX][NNOTE];
 	long notein, noteout;
 };
+
+int vfp;
 
 extern void **_privates;
 extern int _nprivates;
--- a/sys/src/cmd/5e/fns.h
+++ b/sys/src/cmd/5e/fns.h
@@ -35,4 +35,8 @@
 void fpatransfer(u32int);
 void fpaoperation(u32int);
 void fparegtransfer(u32int);
+void resetvfp(void);
+void vfpregtransfer(u32int);
+void vfprmtransfer(u32int);
+void vfpoperation(u32int);
 void inittos(void);
--- a/sys/src/cmd/5e/mkfile
+++ b/sys/src/cmd/5e/mkfile
@@ -1,7 +1,7 @@
 </$objtype/mkfile
 
 TARG=5e
-OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O
+OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O vfp.$O
 HFILES=dat.h fns.h
 BIN=/$objtype/bin
 
--- a/sys/src/cmd/5e/proc.c
+++ b/sys/src/cmd/5e/proc.c
@@ -22,7 +22,10 @@
 	plist.next = P;
 	P->prev = &plist;
 	P->next = &plist;
-	resetfpa();
+	if(vfp)
+		resetvfp();
+	else
+		resetfpa();
 }
 
 void
@@ -211,7 +214,10 @@
 	close(fd);
 	fdclear(P->fd);
 	initstack(argc, argv);
-	resetfpa();
+	if(vfp)
+		resetvfp();
+	else
+		resetfpa();
 	return 0;
 }
 
--- /dev/null
+++ b/sys/src/cmd/5e/vfp.c
@@ -1,0 +1,160 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+#include <mach.h>
+#include "dat.h"
+#include "fns.h"
+
+void
+resetvfp(void)
+{
+	int i;
+
+	P->FPSR = 0x00000000;
+	for(i = 0; i < Nfpregs; i++)
+		P->F[i] = 0;
+}
+
+void
+vfpregtransfer(u32int instr)
+{
+	u32int *Rt;
+	long double *Fn;
+	Rt = P->R + ((instr>>12)&0xF);
+	Fn = P->F + ((instr>>16)&0xF);
+
+	switch((instr>>20)&0xF){
+	case 0:
+		*((int*)Fn) = *Rt; break;
+	case 1:
+		*Rt = *((int*)Fn); break;
+	case 14:
+		P->FPSR = *Rt; break;
+	case 15:
+		if(Rt == (P->R + 15))
+			P->CPSR = P->FPSR;
+		else
+			*Rt = P->FPSR;
+		break;
+	default:
+		sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
+	}
+}
+
+void
+vfprmtransfer(u32int instr)
+{
+	int n, d, off, sz;
+	void* ea;
+	Segment *seg;
+
+	n = (instr>>16) & 0xF;
+	d = (instr>>12) & 0xF;
+	off = (instr & 0xFF) << 2;
+	sz = instr & (1<<8);
+	if((instr & (1<<23)) == 0)
+		off = -off;
+	ea = vaddr(P->R[n] + off, 8, &seg);
+
+	switch((instr>>20)&0x3){
+	case 0:
+		if(sz)
+			*(double*)ea = P->F[d];
+		else
+			*(float*)ea = P->F[d];
+		break;
+	case 1:
+		if(sz)
+			P->F[d] = *(double*)ea;
+		else
+			P->F[d] = *(float*)ea;
+		break;
+	default:
+		sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
+	}
+	segunlock(seg);
+}
+
+void
+vfparithop(int opc, u32int instr)
+{
+	int o;
+	long double *Fd, *Fn, *Fm;
+	Fd = P->F + ((instr>>12)&0xF);
+	Fn = P->F + ((instr>>16)&0xF);
+	Fm = P->F + (instr&0xF);
+	o = ((opc&0x3)<<1) | (opc&0x8) | ((instr>>6)&0x1);
+
+	switch(o){
+	case 4:
+		*Fd = *Fn * *Fm; break;
+	case 6:
+		*Fd = *Fn + *Fm; break;
+	case 7:
+		*Fd = *Fn - *Fm; break;
+	case 8:
+		*Fd = *Fn / *Fm; break;
+	default:
+		sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
+	}
+}
+
+void
+vfpotherop(u32int instr)
+{
+	int o2, o3;
+	long double *Fd, *Fm, F0;
+	Fd = P->F + ((instr>>12)&0xF);
+	Fm = P->F + (instr&0xF);
+	F0 = 0.0;
+	o2 = (instr>>16) & 0xF;
+	o3 = (instr>>6) & 0x3;
+
+	if((o3&1) == 0)
+		sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
+	switch(o2){
+	case 0x5:
+		Fm = &F0;
+	case 0x4:
+		if(*Fd < *Fm)
+			P->FPSR = (P->FPSR & ~FLAGS) | flN;
+		else if(*Fd >= *Fm) {
+			P->FPSR = (P->FPSR & ~FLAGS) | flC;
+			if(*Fd == *Fm)
+				P->FPSR |= flZ;
+		} else
+			P->FPSR = (P->FPSR & ~FLAGS) | flV | flC;
+		break;
+	case 0x8:
+		*Fd = *((int*)Fm); break;
+	case 0xD:
+		*((int*)Fd) = (int)*Fm; break;
+	default:
+		switch((o2<<1)|(o3>>1)){
+		case 0:
+		case 15:
+			*Fd = *Fm; break;
+		case 1:
+			*Fd = fabs(*Fm); break;
+		case 2:
+			*Fd = -*Fm; break;
+		case 3:
+			*Fd = sqrt(*Fm); break;
+		default:
+			sysfatal("unimplemented VFP instruction %8ux @ %8ux", instr, P->R[15] - 4);
+		}
+	}
+}
+
+void
+vfpoperation(u32int instr)
+{
+	int o1;
+	o1 = (instr>>20) & 0xF;
+	if(o1 == 0xB)
+		vfpotherop(instr);
+	else
+		vfparithop(o1, instr);
+}
+