5e: added FPA support

This commit is contained in:
aiju 2011-06-25 20:48:25 +02:00
parent 0b22dfd1f6
commit a4436018f1
6 changed files with 166 additions and 2 deletions

View file

@ -19,7 +19,7 @@ enum {
fH = 1<<5,
};
static void
void
invalid(u32int instr)
{
suicide("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4);
@ -467,6 +467,12 @@ step(void)
syscall();
else if((instr & (7<<25)) == (4 << 25))
block(instr);
else if((instr & 0x0E000F00) == 0x0C000100)
fpatransfer(instr);
else if((instr & 0x0E000F10) == 0x0E000100)
fpaoperation(instr);
else if((instr & 0x0E000F10) == 0x0E000110)
fparegtransfer(instr);
else
invalid(instr);
}

View file

@ -32,6 +32,9 @@ struct Process {
Segment *S[SEGNUM]; /* memory */
u32int R[16]; /* general purpose registers / PC (R15) */
u32int CPSR; /* status register */
u32int FPSR;
long double F[8];
char errbuf[ERRMAX];
Fd *fd; /* bitmap of OCEXEC files */

View file

@ -30,3 +30,8 @@ Process *findproc(int);
void donote(char *, ulong);
void addnote(char *);
void dump(void);
void resetfpa(void);
void invalid(u32int);
void fpatransfer(u32int);
void fpaoperation(u32int);
void fparegtransfer(u32int);

148
sys/src/cmd/5e/fpa.c Normal file
View file

@ -0,0 +1,148 @@
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include <mach.h>
#include "dat.h"
#include "fns.h"
void
resetfpa(void)
{
int i;
P->FPSR = 0x81000000;
for(i = 0; i < 8; i++)
P->F[i] = 0;
}
void
fpatransfer(u32int instr)
{
enum {
fP = 1<<24,
fU = 1<<23,
fT1 = 1<<22,
fW = 1<<21,
fL = 1<<20,
fT0 = 1<<15,
};
long double *Fd;
u32int *Rn, addr;
int off;
void *targ;
Segment *seg;
Rn = P->R + ((instr >> 16) & 15);
Fd = P->F + ((instr >> 12) & 7);
if(Rn == P->R + 15)
invalid(instr);
off = (instr & 255) * 4;
if(!(instr & fU))
off = -off;
addr = *Rn;
if(instr & fP)
addr += off;
targ = vaddr(addr, 8, &seg);
switch(instr & (fT0 | fT1 | fL)) {
case 0: *(float *) targ = *Fd; break;
case fL: *Fd = *(float *) targ; break;
case fT0: *(double *) targ = *Fd; break;
case fT0 | fL: *Fd = *(double *) targ; break;
default: invalid(instr);
}
segunlock(seg);
if(!(instr & fP))
addr += off;
if(instr & fW)
*Rn = addr;
}
static long double
fpasecop(u32int instr)
{
switch(instr & 15) {
case 8: return 0.0; break;
case 9: return 1.0; break;
case 10: return 2.0; break;
case 11: return 3.0; break;
case 12: return 4.0; break;
case 13: return 5.0; break;
case 14: return 0.5; break;
case 15: return 10.0; break;
}
return P->F[instr & 7];
}
void
fpaoperation(u32int instr)
{
long double *Fn, *Fd, op, op2, res;
int prec, opc;
Fn = P->F + ((instr >> 16) & 7);
Fd = P->F + ((instr >> 12) & 7);
op2 = fpasecop(instr);
op = *Fn;
prec = ((instr >> 7) & 1) | ((instr >> 18) & 2);
opc = ((instr >> 20) & 15) | ((instr >> 11) & 16);
switch(opc) {
case 0: res = op + op2; break;
case 1: res = op * op2; break;
case 2: res = op - op2; break;
case 3: res = op2 - op; break;
case 4: res = op / op2; break;
case 5: res = op2 / op; break;
case 16: res = op2; break;
case 17: res = - op2; break;
case 18: res = fabs(op2); break;
case 19: res = (vlong) op2; break;
case 20: res = sqrt(op2); break;
default: sysfatal("unimplemented FPA operation %#x @ %8ux", opc, P->R[15] - 4);
}
switch(prec) {
case 0: *Fd = (float) res; break;
case 1: *Fd = (double) res; break;
case 2: *Fd = res; break;
default: invalid(instr);
}
}
void
fparegtransfer(u32int instr)
{
u32int *Rd;
long tmp;
long double *Fn, op, op2;
Rd = P->R + ((instr >> 12) & 15);
Fn = P->F + ((instr >> 16) & 7);
op = fpasecop(instr);
if(Rd == P->R + 15) {
op2 = *Fn;
switch((instr >> 21) & 7) {
case 4: break;
case 5: op = - op; break;
default: invalid(instr);
}
if(op2 < op)
P->CPSR = (P->CPSR & ~FLAGS) | flN;
else if(op2 >= op) {
P->CPSR = (P->CPSR & ~FLAGS) | flC;
if(op2 == op)
P->CPSR |= flZ;
} else
P->CPSR = (P->CPSR & ~FLAGS) | flV;
return;
}
if(instr & (1<<3))
invalid(instr);
switch((instr >> 20) & 15) {
case 0: *Fn = *(long *) Rd; break;
case 1: tmp = op; *Rd = tmp; break;
case 2: P->FPSR = *Rd; break;
case 3: *Rd = P->FPSR; break;
default: invalid(instr);
}
}

View file

@ -1,7 +1,7 @@
</$objtype/mkfile
TARG=5e
OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O
OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O
HFILES=dat.h fns.h
BIN=/$objtype/bin

View file

@ -22,6 +22,7 @@ initproc(void)
plist.next = P;
P->prev = &plist;
P->next = &plist;
resetfpa();
}
void
@ -202,6 +203,7 @@ loadtext(char *file, int argc, char **argv)
close(fd);
fdclear(P->fd);
initstack(argc, argv);
resetfpa();
return 0;
}