742 lines · 13.5 KB · C
RawDownload
/* * Copyright © 1999 Vita Nuova Limited * * this doesn't attempt to implement 387 floating-point properties * that aren't visible in the Inferno environment.  in particular, * all arithmetic is done in double precision, not extended precision. * furthermore, the FP trap status isn't updated. */ #ifdef TEST#include <u.h>#include <libc.h>#include <ureg.h>#include "fpi.h"#include "tst.h"#else#include <u.h>#include	"ureg.h"#include "fpi.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#endif #define	fabs	Fabs typedef struct FPI FPI; struct FPI {	char*	name;	void	(*f)(Ureg*, int, void*, Internal*, Internal*);	int	dstf;}; enum {	RndNearest = 0,	RndDown,	RndUp,	Rnd0, 	C0 = 1<<8,	C1 = 1<<9,	C2 = 1<<10,	C3 = 1<<14,};  int	fpemudebug = 0; static Internal fpconst[7] = {	/* indexed by op&7 */	/* s, e, l, h */	{0, 0x3FF, 0x00000000, 0x08000000},	/* 1 */	{0, 0x400, 0x0BCD1B8A, 0x0D49A784}, /* l2t */	{0, 0x3FF, 0x095C17F0, 0x0B8AA3B2}, /* l2e */	{0, 0x400, 0x022168C2, 0x0C90FDAA},	/* pi */	{0, 0x3FD, 0x04FBCFF7, 0x09A209A8}, /* lg2 */	{0, 0x3FE, 0x07D1CF79, 0x0B17217F}, /* ln2 */	{0, 0x1, 0x00000000, 0x00000000}, /* z */}; static Internal *fpstk(int i);#define ST(x) (*fpstk((x))) #define	I387	(up->env->fpu) /* BUG: check fetch (not worthwhile in Inferno) */#define	getubyte(a) (*(uchar*)(a))#define	getuword(a) (*(ushort*)(a))#define	getulong(a) (*(ulong*)(a)) static voidpopfp(void){	ushort *s; 	s = &I387.status;	*s = (*s & ~0x3800) | ((*s + 0x0800) & 0x3800);} static voidpushfp(void){	ushort *s; 	s = &I387.status;	*s = (*s & ~0x3800) | ((*s + 0x3800) & 0x3800);} static Internal *fpstk(int i){	return (Internal*)I387.istack[(i+(I387.status>>11))&7];} static voidfldc(Ureg*, int op, void*, Internal*, Internal *d){	*d = fpconst[op&7];} static voidfabs(Ureg*, int, void*, Internal*, Internal *d){	d->s = 0;} static voidfchs(Ureg*, int, void*, Internal*, Internal *d){	d->s ^= 1;} static voidfadd(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	(l.s == r.s? fpiadd: fpisub)(&l, &r, d);} static voidfsub(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	l.s ^= 1;	(l.s == r.s? fpiadd: fpisub)(&l, &r, d);} static voidfsubr(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	r.s ^= 1;	(l.s == r.s? fpiadd: fpisub)(&r, &l, d);} static voidfmul(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	fpimul(&l, &r, d);} static voidfdiv(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	fpidiv(&l, &r, d);} static voidfdivr(Ureg*, int, void*, Internal *s, Internal *d){	Internal l, r; 	l = *s;	r = *d;	fpidiv(&r, &l, d);} static voidfcom(Ureg*, int, void*, Internal *s, Internal *d){	int i;	ushort *p; 	p = &I387.status;	if(IsWeird(s) || IsWeird(d)){		*p |= C0|C2|C3;		/* BUG: should trap if not masked */		return;	}	*p &= ~(C0|C2|C3);	i = fpicmp(d, s);	if(i < 0)		*p |= C0;	else if(i == 0)		*p |= C3;} static voidfpush(Ureg*, int op, void*, Internal*, Internal*){	Internal *p; 	p = &ST(op & 7);	pushfp();	ST(0) = *p;} static voidfmov(Ureg*, int, void*, Internal *s, Internal *d){	*d = *s;} static voidfmovr(Ureg*, int, void*, Internal *s, Internal *d){	*s = *d;} static voidfxch(Ureg*, int, void*, Internal *s, Internal *d){	Internal t; 	t = *s; *s = *d; *d = t;} static voidfrstor(Ureg*, int, void *s, Internal*, Internal*){	validaddr(s, 108, 0);	memmove(&I387, s, 108);} static voidfsave(Ureg*, int, void *d, Internal*, Internal*){	validaddr(d, 108, 1);	memmove(d, &I387, 108);	I387.control = 0x037F;	I387.status = 0;	I387.tag = 0;} static voidfstsw(Ureg*, int, void *d, Internal*, Internal*){	validaddr(d, 2, 1);	*(short*)d = I387.status;} static voidfldenv(Ureg*, int, void *s, Internal*, Internal*){	validaddr(s, 28, 0);	memmove(&I387, s, 28);} static voidfldcw(Ureg*, int, void *s, Internal*, Internal*){	validaddr(s, 2, 0);	I387.control = *(short*)s;} static voidfstenv(Ureg*, int, void *d, Internal*, Internal*){	validaddr(d, 4*7, 1);	memmove(d, &I387, 4*7);} static voidfstcw(Ureg*, int, void *d, Internal*, Internal*){	validaddr(d, 2, 1);	*(short*)d = I387.control;} static voidfincstp(Ureg*, int, void*, Internal*, Internal*){	popfp();} static voidfdecstp(Ureg*, int, void*, Internal*, Internal*){	pushfp();} static voidfscale(Ureg*, int, void*, Internal *s, Internal *d) {	Word w; 	fpii2w(&w, s);	/* should truncate towards zero ... */	d->e += w;} static voidfstswax(Ureg *ur, int, void*, Internal*, Internal*){	ur->ax = (ur->ax & ~0xFFFF) | (I387.status & 0xFFFF);} static voidftst(Ureg*, int, void*, Internal*, Internal *d){	ushort *p; 	p = &I387.status;	if(IsWeird(d)){		*p |= C0|C2|C3;		return;	}	*p &= ~(C0|C2|C3);	fpinormalise(d);	if(IsZero(d))		*p |= C3;	else if(d->s)		*p |=C0;} static voidfrndint(Ureg*, int, void*, Internal*, Internal *d){	fpiround(d);	/* BUG: doesn't look at rounding mode */} static voidfnop(Ureg*, int, void*, Internal*, Internal*){} enum {	Fpop1= 1<<0,	Fpop2 = 1<<1,	Fload = 1<<2,}; /* * %e	-	effective address - Mod R/M value * %f	-	floating point register F0-F7 - from Mod R/M register */ static void fload(Ureg*, int, void*, Internal*, Internal*);static void fstore(Ureg*, int, void*, Internal*, Internal*); #define	X(a,b) (((a)<<2)|(b)) static	FPI	optab1[4][4] = {	/* normal mod r/m operand */[0]	{	[0]	{"FLDENV %e", fldenv, 0},	[1]	{"FLDCW %e", fldcw, 0},	[2]	{"FSTENV %e", fstenv, 0},	[3]	{"FSTCW %e", fstcw, 0},	},[1]	{	[1]	{"FMOVX %e,F0", nil, Fload},	[3]	{"FMOVXP F0,%e", nil, Fpop1},	},[2]	{	[0]	{"FRSTOR %e", frstor, 0},	[2]	{"FSAVE %e", fsave, 0},	[3]	{"FSTSW %e", fstsw, 0},	},[3]	{	[0]	{"FMOVB %e", nil, 0},	[1]	{"FMOVV %e,F0", nil, Fload},	[2]	{"FMOVBP %e", nil, Fpop1},	[3]	{"FMOVVP F0,%e", nil, Fpop1},	},}; #undef X static	FPI	optab2a[1<<3] = {	/* A=0 */[0]	{"FADDx %e,F0", fadd, 0},[1]	{"FMULx %e,F0", fmul, 0},[2]	{"FCOMx %e,F0", fcom, 0},[3]	{"FCOMxP %e,F0", fcom, Fpop1},[4]	{"FSUBx %e,F0", fsub, 0},[5]	{"FSUBRx %e,F0", fsubr, 0},	/* ?? */[6]	{"FDIVx %e,F0", fdiv, 0},[7]	{"FDIVRx %e,F0", fdivr, 0},	/* ?? */}; static	FPI	optab2b[1<<2] = {	/* A=1, B=0,2,3 */[0]	{"FMOVx %e,F0", fload, Fload},[2]	{"FMOVx F0,%e", fstore, 0},[3]	{"FMOVxP F0,%e", fstore, Fpop1},}; #define	X(d,P,B) ((d<<4)|(P<<3)|B) static	FPI	optab3a[1<<5] = {	/* A=0 */[X(0,0,0)]	{"FADDD	%f,F0", fadd, 0},[X(1,0,0)]	{"FADDD	F0,%f", fadd, 0},[X(1,1,0)]	{"FADDDP	F0,%f", fadd, Fpop1},[X(0,0,1)]	{"FMULD	%f,F0", fmul, 0},[X(1,0,1)]	{"FMULD	F0,%f", fmul, 0},[X(1,1,1)]	{"FMULDP	F0,%f", fmul, Fpop1},[X(0,0,2)]	{"FCOMD	%f,F0", fcom, 0},[X(0,0,3)]	{"FCOMDP	%f,F0", fcom, Fpop1},[X(1,1,3)]	{"FCOMDPP", fcom, Fpop1|Fpop2},[X(0,0,4)]	{"FSUBD	%f,F0", fsub, 0},[X(1,0,4)]	{"FSUBRD	F0,%f", fsubr, 0},[X(1,1,4)]	{"FSUBRDP F0,%f", fsubr, Fpop1},[X(0,0,5)]	{"FSUBRD	%f,F0", fsubr, 0},[X(1,0,5)]	{"FSUBD	F0,%f", fsub, 0},[X(1,1,5)]	{"FSUBDP	F0,%f", fsub, Fpop1},[X(0,1,5)]	{"FUCOMPP", fcom, Fpop1|Fpop2},[X(0,0,6)]	{"FDIVD	%f,F0", fdiv, 0},[X(1,0,6)]	{"FDIVRD	F0,%f", fdivr, 0},[X(1,1,6)]	{"FDIVRDP F0,%f", fdivr, Fpop1},[X(0,0,7)]	{"FDIVRD	%f,F0", fdivr, 0},[X(1,0,7)]	{"FDIVD	F0,%f", fdiv, 0},[X(1,1,7)]	{"FDIVDP	F0,%f", fdiv, Fpop1},}; static	FPI	optab3b[1<<5] = {	/* A=1 */[X(0,0,0)]	{"FMOVD	%f,F0", fmov, Fload},[X(0,0,1)]	{"FXCHD	%f,F0", fxch, 0},[X(0,0,2)]	{"FNOP", fnop, 0},	/* F0 only */[X(1,0,0)]	{"FFREED	%f", fnop, 0},[X(1,0,2)]	{"FMOVD	F0,%f", fmovr, 0},[X(1,0,3)]	{"FMOVDP	F0,%f", fmovr, Fpop1},[X(1,1,4)]	{"FSTSW	AX", fstswax, 0},[X(1,0,4)]	{"FUCOMD	%f,F0", fcom, 0},[X(1,0,5)]	{"FUCOMDP %f,F0", fcom, Fpop1},}; #undef X static	FPI	optab4[1<<6] = {[0x00]	{"FCHS", fchs, 0},[0x01]	{"FABS", fabs, 0},[0x04]	{"FTST", ftst, 0},[0x05]	{"FXAM", nil, 0},[0x08]	{"FLD1", fldc, Fload},[0x09]	{"FLDL2T", fldc, Fload},[0x0a]	{"FLDL2E", fldc, Fload},[0x0b]	{"FLDPI", fldc, Fload},[0x0c]	{"FLDLG2", fldc, Fload},[0x0d]	{"FLDLN2", fldc, Fload},[0x0e]	{"FLDZ", fldc, Fload},[0x10]	{"F2XM1", nil, 0},[0x11]	{"FYL2X", nil, 0},[0x12]	{"FPTAN", nil, 0},[0x13]	{"FPATAN", nil, 0},[0x14]	{"FXTRACT", nil, 0},[0x15]	{"FPREM1", nil, 0},[0x16]	{"FDECSTP", fdecstp, 0},[0x17]	{"FINCSTP", fincstp, 0},[0x18]	{"FPREM", nil, 0},[0x19]	{"FYL2XP1", nil, 0},[0x1a]	{"FSQRT", nil, 0},[0x1b]	{"FSINCOS", nil, 0},[0x1c]	{"FRNDINT", frndint, 0},[0x1d]	{"FSCALE", fscale, 0},[0x1e]	{"FSIN", nil, 0},[0x1f]	{"FCOS", nil, 0},}; static voidloadr32(void *s, Internal *d){	validaddr(s, 4, 0);	fpis2i(d, s);} static voidloadi32(void *s, Internal *d){	validaddr(s, 4, 0);	fpiw2i(d, s);} static voidloadr64(void *s, Internal *d){	validaddr(s, 8, 0);	fpid2i(d, s);} static voidloadi16(void *s, Internal *d){	Word w; 	validaddr(s, 2, 0);	w = *(short*)s;	fpiw2i(d, &w);} static	void	(*loadf[4])(void*, Internal*) ={	loadr32, loadi32, loadr64, loadi16}; static void

Lines 1–500 of 742.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t