/* * 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 voidLines 1–500 of 742. Load more
/* * 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 void popfp(void) { ushort *s; s = &I387.status; *s = (*s & ~0x3800) | ((*s + 0x0800) & 0x3800); } static void pushfp(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 void fldc(Ureg*, int op, void*, Internal*, Internal *d) { *d = fpconst[op&7]; } static void fabs(Ureg*, int, void*, Internal*, Internal *d) { d->s = 0; } static void fchs(Ureg*, int, void*, Internal*, Internal *d) { d->s ^= 1; } static void fadd(Ureg*, int, void*, Internal *s, Internal *d) { Internal l, r; l = *s; r = *d; (l.s == r.s? fpiadd: fpisub)(&l, &r, d); } static void fsub(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 void fsubr(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 void fmul(Ureg*, int, void*, Internal *s, Internal *d) { Internal l, r; l = *s; r = *d; fpimul(&l, &r, d); } static void fdiv(Ureg*, int, void*, Internal *s, Internal *d) { Internal l, r; l = *s; r = *d; fpidiv(&l, &r, d); } static void fdivr(Ureg*, int, void*, Internal *s, Internal *d) { Internal l, r; l = *s; r = *d; fpidiv(&r, &l, d); } static void fcom(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 void fpush(Ureg*, int op, void*, Internal*, Internal*) { Internal *p; p = &ST(op & 7); pushfp(); ST(0) = *p; } static void fmov(Ureg*, int, void*, Internal *s, Internal *d) { *d = *s; } static void fmovr(Ureg*, int, void*, Internal *s, Internal *d) { *s = *d; } static void fxch(Ureg*, int, void*, Internal *s, Internal *d) { Internal t; t = *s; *s = *d; *d = t; } static void frstor(Ureg*, int, void *s, Internal*, Internal*) { validaddr(s, 108, 0); memmove(&I387, s, 108); } static void fsave(Ureg*, int, void *d, Internal*, Internal*) { validaddr(d, 108, 1); memmove(d, &I387, 108); I387.control = 0x037F; I387.status = 0; I387.tag = 0; } static void fstsw(Ureg*, int, void *d, Internal*, Internal*) { validaddr(d, 2, 1); *(short*)d = I387.status; } static void fldenv(Ureg*, int, void *s, Internal*, Internal*) { validaddr(s, 28, 0); memmove(&I387, s, 28); } static void fldcw(Ureg*, int, void *s, Internal*, Internal*) { validaddr(s, 2, 0); I387.control = *(short*)s; } static void fstenv(Ureg*, int, void *d, Internal*, Internal*) { validaddr(d, 4*7, 1); memmove(d, &I387, 4*7); } static void fstcw(Ureg*, int, void *d, Internal*, Internal*) { validaddr(d, 2, 1); *(short*)d = I387.control; } static void fincstp(Ureg*, int, void*, Internal*, Internal*) { popfp(); } static void fdecstp(Ureg*, int, void*, Internal*, Internal*) { pushfp(); } static void fscale(Ureg*, int, void*, Internal *s, Internal *d) { Word w; fpii2w(&w, s); /* should truncate towards zero ... */ d->e += w; } static void fstswax(Ureg *ur, int, void*, Internal*, Internal*) { ur->ax = (ur->ax & ~0xFFFF) | (I387.status & 0xFFFF); } static void ftst(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 void frndint(Ureg*, int, void*, Internal*, Internal *d) { fpiround(d); /* BUG: doesn't look at rounding mode */ } static void fnop(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 void loadr32(void *s, Internal *d) { validaddr(s, 4, 0); fpis2i(d, s); } static void loadi32(void *s, Internal *d) { validaddr(s, 4, 0); fpiw2i(d, s); } static void loadr64(void *s, Internal *d) { validaddr(s, 8, 0); fpid2i(d, s); } static void loadi16(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