Plan 9 from Bell Labs 2000-10-26
10 files changed, 1037 insertions(+), 14 deletions(-) M bitsy/dat.h M bitsy/fns.h A bitsy/fpi.c A bitsy/fpi.h A bitsy/fpiarm.c A bitsy/fpimem.c M bitsy/main.c M bitsy/screen.c M bitsy/trap.c M port/proc.c
M bitsy/dat.h => bitsy/dat.h +8 -7
@@ 1,4 1,6 @@ typedef struct Conf Conf; typedef struct FPU FPU; typedef struct FPenv FPenv; typedef struct FPsave FPsave; typedef struct Label Label; typedef struct Lock Lock; @@ 34,20 36,19 @@ struct Label }; /* * no floating point, hence nothing to save */ /* * FPsave.status */ enum { FPinit, FPinactive, FPINIT, FPACTIVE, FPINACTIVE, }; struct FPsave { int dummy; ulong status; ulong control; ulong regs[8][3]; /* emulated fp */ }; struct Conf
M bitsy/fns.h => bitsy/fns.h +1 -0
@@ 12,6 12,7 @@ void clockinit(void); void delay(int); void evenaddr(ulong); void flushmmu(void); int fpiarm(Ureg *ur); char* getconf(char*); ulong getfar(void); ulong getfsr(void);
A bitsy/fpi.c => bitsy/fpi.c +300 -0
@@ 0,0 1,300 @@ /* * Floating Point Interpreter. * shamelessly stolen from an original by ark. */ #include "fpi.h" void fpiround(Internal *i) { unsigned long guard; guard = i->l & GuardMask; i->l &= ~GuardMask; if(guard > (LsBit>>1) || (guard == (LsBit>>1) && (i->l & LsBit))){ i->l += LsBit; if(i->l & CarryBit){ i->l &= ~CarryBit; i->h++; if(i->h & CarryBit){ if (i->h & 0x01) i->l |= CarryBit; i->l >>= 1; i->h >>= 1; i->e++; } } } } static void matchexponents(Internal *x, Internal *y) { int count; count = y->e - x->e; x->e = y->e; if(count >= 2*FractBits){ x->l = x->l || x->h; x->h = 0; return; } if(count >= FractBits){ count -= FractBits; x->l = x->h|(x->l != 0); x->h = 0; } while(count > 0){ count--; if(x->h & 0x01) x->l |= CarryBit; if(x->l & 0x01) x->l |= 2; x->l >>= 1; x->h >>= 1; } } static void shift(Internal *i) { i->e--; i->h <<= 1; i->l <<= 1; if(i->l & CarryBit){ i->l &= ~CarryBit; i->h |= 0x01; } } static void normalise(Internal *i) { while((i->h & HiddenBit) == 0) shift(i); } static void renormalise(Internal *i) { if(i->e < -2 * FractBits) i->e = -2 * FractBits; while(i->e < 1){ i->e++; if(i->h & 0x01) i->l |= CarryBit; i->h >>= 1; i->l = (i->l>>1)|(i->l & 0x01); } if(i->e >= ExpInfinity) SetInfinity(i); } void fpinormalise(Internal *x) { if(!IsWeird(x) && !IsZero(x)) normalise(x); } void fpiadd(Internal *x, Internal *y, Internal *i) { Internal *t; i->s = x->s; if(IsWeird(x) || IsWeird(y)){ if(IsNaN(x) || IsNaN(y)) SetQNaN(i); else SetInfinity(i); return; } if(x->e > y->e){ t = x; x = y; y = t; } matchexponents(x, y); i->e = x->e; i->h = x->h + y->h; i->l = x->l + y->l; if(i->l & CarryBit){ i->h++; i->l &= ~CarryBit; } if(i->h & (HiddenBit<<1)){ if(i->h & 0x01) i->l |= CarryBit; i->l = (i->l>>1)|(i->l & 0x01); i->h >>= 1; i->e++; } if(IsWeird(i)) SetInfinity(i); } void fpisub(Internal *x, Internal *y, Internal *i) { Internal *t; if(y->e < x->e || (y->e == x->e && (y->h < x->h || (y->h == x->h && y->l < x->l)))){ t = x; x = y; y = t; } i->s = y->s; if(IsNaN(y)){ SetQNaN(i); return; } if(IsInfinity(y)){ if(IsInfinity(x)) SetQNaN(i); else SetInfinity(i); return; } matchexponents(x, y); i->e = y->e; i->h = y->h - x->h; i->l = y->l - x->l; if(i->l < 0){ i->l += CarryBit; i->h--; } if(i->h == 0 && i->l == 0) SetZero(i); else while(i->e > 1 && (i->h & HiddenBit) == 0) shift(i); } #define CHUNK (FractBits/2) #define CMASK ((1<<CHUNK)-1) #define HI(x) ((short)((x)>>CHUNK) & CMASK) #define LO(x) ((short)(x) & CMASK) #define SPILL(x) ((x)>>CHUNK) #define M(x, y) ((long)a[x]*(long)b[y]) #define C(h, l) (((long)((h) & CMASK)<<CHUNK)|((l) & CMASK)) void fpimul(Internal *x, Internal *y, Internal *i) { long a[4], b[4], c[7], f[4]; i->s = x->s^y->s; if(IsWeird(x) || IsWeird(y)){ if(IsNaN(x) || IsNaN(y) || IsZero(x) || IsZero(y)) SetQNaN(i); else SetInfinity(i); return; } else if(IsZero(x) || IsZero(y)){ SetZero(i); return; } normalise(x); normalise(y); i->e = x->e + y->e - (ExpBias - 1); a[0] = HI(x->h); b[0] = HI(y->h); a[1] = LO(x->h); b[1] = LO(y->h); a[2] = HI(x->l); b[2] = HI(y->l); a[3] = LO(x->l); b[3] = LO(y->l); c[6] = M(3, 3); c[5] = M(2, 3) + M(3, 2) + SPILL(c[6]); c[4] = M(1, 3) + M(2, 2) + M(3, 1) + SPILL(c[5]); c[3] = M(0, 3) + M(1, 2) + M(2, 1) + M(3, 0) + SPILL(c[4]); c[2] = M(0, 2) + M(1, 1) + M(2, 0) + SPILL(c[3]); c[1] = M(0, 1) + M(1, 0) + SPILL(c[2]); c[0] = M(0, 0) + SPILL(c[1]); f[0] = c[0]; f[1] = C(c[1], c[2]); f[2] = C(c[3], c[4]); f[3] = C(c[5], c[6]); if((f[0] & HiddenBit) == 0){ f[0] <<= 1; f[1] <<= 1; f[2] <<= 1; f[3] <<= 1; if(f[1] & CarryBit){ f[0] |= 1; f[1] &= ~CarryBit; } if(f[2] & CarryBit){ f[1] |= 1; f[2] &= ~CarryBit; } if(f[3] & CarryBit){ f[2] |= 1; f[3] &= ~CarryBit; } i->e--; } i->h = f[0]; i->l = f[1]; if(f[2] || f[3]) i->l |= 1; renormalise(i); } void fpidiv(Internal *x, Internal *y, Internal *i) { i->s = x->s^y->s; if(IsNaN(x) || IsNaN(y) || (IsInfinity(x) && IsInfinity(y)) || (IsZero(x) && IsZero(y))){ SetQNaN(i); return; } else if(IsZero(x) || IsInfinity(y)){ SetInfinity(i); return; } else if(IsInfinity(x) || IsZero(y)){ SetZero(i); return; } normalise(x); normalise(y); i->h = 0; i->l = 0; i->e = y->e - x->e + (ExpBias + 2*FractBits - 1); do{ if(y->h > x->h || (y->h == x->h && y->l >= x->l)){ i->l |= 0x01; y->h -= x->h; y->l -= x->l; if(y->l < 0){ y->l += CarryBit; y->h--; } } shift(y); shift(i); }while ((i->h & HiddenBit) == 0); if(y->h || y->l) i->l |= 0x01; renormalise(i); } int fpicmp(Internal *x, Internal *y) { if(IsNaN(x) && IsNaN(y)) return 0; if(IsInfinity(x) && IsInfinity(y)) return y->s - x->s; if(x->e == y->e && x->h == y->h && x->l == y->l) return y->s - x->s; if(x->e < y->e || (x->e == y->e && (x->h < y->h || (x->h == y->h && x->l < y->l)))) return y->s ? 1: -1; return x->s ? -1: 1; }
A bitsy/fpi.h => bitsy/fpi.h +61 -0
@@ 0,0 1,61 @@ typedef long Word; typedef unsigned long Single; typedef struct { unsigned long h; unsigned long l; } Double; enum { FractBits = 28, CarryBit = 0x10000000, HiddenBit = 0x08000000, MsBit = HiddenBit, NGuardBits = 3, GuardMask = 0x07, LsBit = (1<<NGuardBits), SingleExpBias = 127, SingleExpMax = 255, DoubleExpBias = 1023, DoubleExpMax = 2047, ExpBias = DoubleExpBias, ExpInfinity = DoubleExpMax, }; typedef struct { unsigned char s; short e; long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */ long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */ } Internal; #define IsWeird(n) ((n)->e >= ExpInfinity) #define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0) #define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0) #define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l)) #define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \ (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0) #define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0) #define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0) /* * fpi.c */ extern void fpiround(Internal *); extern void fpiadd(Internal *, Internal *, Internal *); extern void fpisub(Internal *, Internal *, Internal *); extern void fpimul(Internal *, Internal *, Internal *); extern void fpidiv(Internal *, Internal *, Internal *); extern int fpicmp(Internal *, Internal *); extern void fpinormalise(Internal*); /* * fpimem.c */ extern void fpis2i(Internal *, void *); extern void fpid2i(Internal *, void *); extern void fpiw2i(Internal *, void *); extern void fpii2s(void *, Internal *); extern void fpii2d(void *, Internal *); extern void fpii2w(Word *, Internal *);
A bitsy/fpiarm.c => bitsy/fpiarm.c +488 -0
@@ 0,0 1,488 @@ /* * this doesn't attempt to implement ARM floating-point properties * that aren't visible in the Inferno environment. * all arithmetic is done in double precision. * the FP trap status isn't updated. */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "fpi.h" #define R13OK /* undef this if correct kernel r13 isn't in Ureg; * check calculation in fpiarm below */ #define REG(x) (*(long*)(((char*)ur)+roff[(x)])) #define FPENV (*ufp) #define FR(x) (*(Internal*)ufp->regs[(x)&7]) /* BUG: check fetch (not worthwhile in Inferno) */ #define getubyte(a) (*(uchar*)(a)) #define getuword(a) (*(ushort*)(a)) #define getulong(a) (*(ulong*)(a)) typedef struct FP2 FP2; typedef struct FP1 FP1; struct FP2 { char* name; void (*f)(Internal, Internal, Internal*); }; struct FP1 { char* name; void (*f)(Internal*, Internal*); }; enum { N = 1<<31, Z = 1<<30, C = 1<<29, V = 1<<28, REGPC = 15, }; int fpemudebug = 0; #undef OFR #define OFR(X) ((ulong)&((Ureg*)0)->X) static int roff[] = { OFR(r0), OFR(r1), OFR(r2), OFR(r3), OFR(r4), OFR(r5), OFR(r6), OFR(r7), OFR(r8), OFR(r9), OFR(r10), OFR(r11), #ifdef R13OK OFR(r12), OFR(r13), OFR(r14), OFR(pc), #else OFR(r12), OFR(type), OFR(r14), OFR(pc), #endif }; static Internal fpconst[8] = { /* indexed by op&7 */ /* s, e, l, h */ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */ {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */ {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */ {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */ {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */ {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */ {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */ }; /* * arm binary operations */ static void fadd(Internal m, Internal n, Internal *d) { (m.s == n.s? fpiadd: fpisub)(&m, &n, d); } static void fsub(Internal m, Internal n, Internal *d) { m.s ^= 1; (m.s == n.s? fpiadd: fpisub)(&m, &n, d); } static void fsubr(Internal m, Internal n, Internal *d) { n.s ^= 1; (n.s == m.s? fpiadd: fpisub)(&n, &m, d); } static void fmul(Internal m, Internal n, Internal *d) { fpimul(&m, &n, d); } static void fdiv(Internal m, Internal n, Internal *d) { fpidiv(&m, &n, d); } static void fdivr(Internal m, Internal n, Internal *d) { fpidiv(&n, &m, d); } /* * arm unary operations */ static void fmov(Internal *m, Internal *d) { *d = *m; } static void fmovn(Internal *m, Internal *d) { *d = *m; d->s ^= 1; } static void fabsf(Internal *m, Internal *d) { *d = *m; d->s = 0; } static void frnd(Internal *m, Internal *d) { short e; (m->s? fsub: fadd)(fpconst[6], *m, d); if(IsWeird(d)) return; fpiround(d); e = (d->e - ExpBias) + 1; if(e <= 0) SetZero(d); else if(e > FractBits){ if(e < 2*FractBits) d->l &= ~((1<<(2*FractBits - e))-1); }else{ d->l = 0; if(e < FractBits) d->h &= ~((1<<(FractBits-e))-1); } } static FP1 optab1[16] = { /* Fd := OP Fm */ [0] {"MOVF", fmov}, [1] {"NEGF", fmovn}, [2] {"ABSF", fabsf}, [3] {"RNDF", frnd}, [4] {"SQTF", /*fsqt*/0}, /* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */ /* URD and NRM aren't implemented */ }; static FP2 optab2[16] = { /* Fd := Fn OP Fm */ [0] {"ADDF", fadd}, [1] {"MULF", fmul}, [2] {"SUBF", fsub}, [3] {"RSUBF", fsubr}, [4] {"DIVF", fdiv}, [5] {"RDIVF", fdivr}, /* POW, RPW deprecated */ [8] {"REMF", /*frem*/0}, [9] {"FMF", fmul}, /* fast multiply */ [10] {"FDV", fdiv}, /* fast divide */ [11] {"FRD", fdivr}, /* fast reverse divide */ /* POL deprecated */ }; static ulong fcmp(Internal *n, Internal *m) { int i; if(IsWeird(m) || IsWeird(n)){ /* BUG: should trap if not masked */ return V|C; } i = fpicmp(n, m); if(i > 0) return C; else if(i == 0) return C|Z; else return N; } static void fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp) { void *mem; mem = (void*)ea; (*f)(&FR(d), mem); if(fpemudebug) print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d); } static void fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp) { Internal tmp; void *mem; mem = (void*)ea; tmp = FR(s); if(fpemudebug) print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea); (*f)(mem, &tmp); } static int condok(int cc, int c) { switch(c){ case 0: /* Z set */ return cc&Z; case 1: /* Z clear */ return (cc&Z) == 0; case 2: /* C set */ return cc&C; case 3: /* C clear */ return (cc&C) == 0; case 4: /* N set */ return cc&N; case 5: /* N clear */ return (cc&N) == 0; case 6: /* V set */ return cc&V; case 7: /* V clear */ return (cc&V) == 0; case 8: /* C set and Z clear */ return cc&C && (cc&Z) == 0; case 9: /* C clear or Z set */ return (cc&C) == 0 || cc&Z; case 10: /* N set and V set, or N clear and V clear */ return (~cc&(N|V))==0 || (cc&(N|V)) == 0; case 11: /* N set and V clear, or N clear and V set */ return (cc&(N|V))==N || (cc&(N|V))==V; case 12: /* Z clear, and either N set and V set or N clear and V clear */ return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0); case 13: /* Z set, or N set and V clear or N clear and V set */ return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V; case 14: /* always */ return 1; case 15: /* never (reserved) */ return 0; } return 0; /* not reached */ } static void unimp(ulong pc, ulong op) { char buf[60]; snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op); if(fpemudebug) print("FPE: %s\n", buf); error(buf); /* no return */ } static void fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp) { int rn, rd, tag, o; long off; ulong ea; Internal tmp, *fm, *fn; /* note: would update fault status here if we noted numeric exceptions */ /* * LDF, STF; 10.1.1 */ if(((op>>25)&7) == 6){ if(op & (1<<22)) unimp(pc, op); /* packed or extended */ rn = (op>>16)&0xF; off = (op&0xFF)<<2; if((op & (1<<23)) == 0) off = -off; ea = REG(rn); if(rn == REGPC) ea += 8; if(op & (1<<24)) ea += off; rd = (op>>12)&7; if(op & (1<<20)){ if(op & (1<<15)) fld(fpid2i, rd, ea, 8, ufp); else fld(fpis2i, rd, ea, 4, ufp); }else{ if(op & (1<<15)) fst(fpii2d, ea, rd, 8, ufp); else fst(fpii2s, ea, rd, 4, ufp); } if((op & (1<<24)) == 0) ea += off; if(op & (1<<21)) REG(rn) = ea; return; } /* * CPRT/transfer, 10.3 */ if(op & (1<<4)){ rd = (op>>12) & 0xF; /* * compare, 10.3.1 */ if(rd == 15 && op & (1<<20)){ rn = (op>>16)&7; fn = &FR(rn); if(op & (1<<3)){ fm = &fpconst[op&7]; tag = 'C'; }else{ fm = &FR(op&7); tag = 'F'; } switch((op>>21)&7){ default: unimp(pc, op); case 4: /* CMF: Fn :: Fm */ case 6: /* CMFE: Fn :: Fm (with exception) */ ur->psr &= ~(N|C|Z|V); ur->psr |= fcmp(fn, fm); break; case 5: /* CNF: Fn :: -Fm */ case 7: /* CNFE: Fn :: -Fm (with exception) */ tmp = *fm; tmp.s ^= 1; ur->psr &= ~(N|C|Z|V); ur->psr |= fcmp(fn, &tmp); break; } if(fpemudebug) print("CMPF %c%d,F%ld =%lux\n", tag, rn, op&7, ur->psr>>28); return; } /* * other transfer, 10.3 */ switch((op>>20)&0xF){ default: unimp(pc, op); case 0: /* FLT */ rn = (op>>16) & 7; fpiw2i(&FR(rn), ®(rd)); if(fpemudebug) print("MOVW[FD] R%d, F%d\n", rd, rn); break; case 1: /* FIX */ if(op & (1<<3)) unimp(pc, op); rn = op & 7; tmp = FR(rn); fpii2w(®(rd), &tmp); if(fpemudebug) print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(rd)); break; case 2: /* FPSR := Rd */ FPENV.status = REG(rd); if(fpemudebug) print("MOVW R%d, FPSR\n", rd); break; case 3: /* Rd := FPSR */ REG(rd) = FPENV.status; if(fpemudebug) print("MOVW FPSR, R%d\n", rd); break; case 4: /* FPCR := Rd */ FPENV.control = REG(rd); if(fpemudebug) print("MOVW R%d, FPCR\n", rd); break; case 5: /* Rd := FPCR */ REG(rd) = FPENV.control; if(fpemudebug) print("MOVW FPCR, R%d\n", rd); break; } return; } /* * arithmetic */ if(op & (1<<3)){ /* constant */ fm = &fpconst[op&7]; tag = 'C'; }else{ fm = &FR(op&7); tag = 'F'; } rd = (op>>12)&7; o = (op>>20)&0xF; if(op & (1<<15)){ /* monadic */ FP1 *fp; fp = &optab1[o]; if(fp->f == nil) unimp(pc, op); if(fpemudebug) print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd); (*fp->f)(fm, &FR(rd)); } else { FP2 *fp; fp = &optab2[o]; if(fp->f == nil) unimp(pc, op); rn = (op>>16)&7; if(fpemudebug) print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd); (*fp->f)(*fm, FR(rn), &FR(rd)); } } /* * returns the number of FP instructions emulated */ int fpiarm(Ureg *ur) { ulong op, o; FPsave *ufp; int n; #ifndef R13OK /* ur->type = &ur->pc+1; /* calculate kernel sp/R13 and put it here for roff[13] */ ur->type = (ulong)(ur + 1); #endif if (up == nil) panic("fpiarm not in a process"); ufp = &up->fpsave; /* because all the state is in the proc structure, * it need not be saved/restored */ if(up->fpstate != FPACTIVE) { up->fpstate = FPACTIVE; ufp->control = 0; ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */ for(n = 0; n < 8; n++) FR(n) = fpconst[0]; } for(n=0;;n++){ op = getulong(ur->pc); o = (op>>24) & 0xF; if(((op>>8) & 0xF) != 1 || o != 0xE && (o&~1) != 0xC) break; if(condok(ur->psr, op>>28)) fpemu(ur->pc, op, ur, ufp); ur->pc += 4; } return n; }
A bitsy/fpimem.c => bitsy/fpimem.c +136 -0
@@ 0,0 1,136 @@ #include "fpi.h" /* * the following routines depend on memory format, not the machine */ void fpis2i(Internal *i, void *v) { Single *s = v; i->s = (*s & 0x80000000) ? 1: 0; if((*s & ~0x80000000) == 0){ SetZero(i); return; } i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias; i->h = (*s & 0x007FFFFF)<<(1+NGuardBits); i->l = 0; if(i->e) i->h |= HiddenBit; else i->e++; } void fpid2i(Internal *i, void *v) { Double *d = v; i->s = (d->h & 0x80000000) ? 1: 0; i->e = (d->h>>20) & 0x07FF; i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F); i->l = (d->l & 0x01FFFFFF)<<NGuardBits; if(i->e) i->h |= HiddenBit; else i->e++; } void fpiw2i(Internal *i, void *v) { Word w, word = *(Word*)v; short e; if(word < 0){ i->s = 1; word = -word; } else i->s = 0; if(word == 0){ SetZero(i); return; } if(word > 0){ for (e = 0, w = word; w; w >>= 1, e++) ; } else e = 32; if(e > FractBits){ i->h = word>>(e - FractBits); i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e); } else { i->h = word<<(FractBits - e); i->l = 0; } i->e = (e - 1) + ExpBias; } void fpii2s(void *v, Internal *i) { short e; Single *s = (Single*)v; fpiround(i); if(i->h & HiddenBit) i->h &= ~HiddenBit; else i->e--; *s = i->s ? 0x80000000: 0; e = i->e; if(e < ExpBias){ if(e <= (ExpBias - SingleExpBias)) return; e = SingleExpBias - (ExpBias - e); } else if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){ *s |= SingleExpMax<<23; return; } else e = SingleExpBias + (e - ExpBias); *s |= (e<<23)|(i->h>>(1+NGuardBits)); } void fpii2d(void *v, Internal *i) { Double *d = (Double*)v; fpiround(i); if(i->h & HiddenBit) i->h &= ~HiddenBit; else i->e--; i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits); i->h >>= NGuardBits; d->h = i->s ? 0x80000000: 0; d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4); d->l = (i->h<<28)|i->l; } void fpii2w(Word *word, Internal *i) { Word w; short e; fpiround(i); e = (i->e - ExpBias) + 1; if(e <= 0) w = 0; else if(e > 31) w = 0x7FFFFFFF; else if(e > FractBits) w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e)); else w = i->h>>(FractBits-e); if(i->s) w = -w; *word = w; }
M bitsy/main.c => bitsy/main.c +1 -1
@@ 229,7 229,7 @@ userinit(void) void procsetup(Proc *p) { p->fpstate = FPinit; p->fpstate = FPINIT; } /*
M bitsy/screen.c => bitsy/screen.c +2 -2
@@ 297,8 297,8 @@ screenwin(void) grey = allocmemimage(Rect(0,0,1,1), RGB16); grey->flags |= Frepl; grey->clipr = gscreen->r; grey->data->bdata[0] = 0x77; grey->data->bdata[1] = 0x77; grey->data->bdata[0] = 0x40; grey->data->bdata[1] = 0xfd; w = memdefont->info[' '].width; h = memdefont->height;
M bitsy/trap.c => bitsy/trap.c +39 -3
@@ 16,7 16,6 @@ struct Intrregs ulong icfp; /* pending FIQs */ ulong dummy1[3]; ulong icpr; /* pending interrupts */ }; struct Intrregs *intrregs; @@ 35,7 34,6 @@ typedef struct Vctl { static Lock vctllock; static Vctl *vctl; /* * Layout at virtual address 0. */ @@ 267,14 265,52 @@ trap(Ureg *ureg) } break; case PsrMund: /* undefined instruction */ #ifdef NOTDEF /* Inferno break handling, something for us? [SJM] */ if(*(ulong*)ureg->pc == BREAK && breakhandler) { int s; Proc *p; p = up; /* if (!waslo(ureg->psr) || (ureg->pc >= (ulong)splhi && ureg->pc < (ulong)islo)) p = 0; */ s = breakhandler(ureg, p); if(s == BrkSched) { c.callsched = 1; sched(); } else if(s == BrkNoSched) { c.callsched = 0; if(up) up->dbgreg = 0; return; } break; } /* End of Inferno break handling [SJM] */ #endif /* start of Inferno code [SJM] */ spllo(); if (waserror()) { warnregs(ureg, "floating point error"); panic("floating point error"); } if (!fpiarm(ureg)) { warnregs(ureg, "illegal instruction"); panic("illegal instruction"); } poperror(); /* end of Inferno code [SJM] */ #ifdef NOTDEF /* We'll see what we do with this later [SJM] */ if(user){ sprint(buf, "sys: undefined instruction: pc 0x%lux\n", sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc); postnote(up, 1, buf, NDebug); }else{ warnregs(ureg, "undefined instruction"); panic("undefined instruction"); } #endif break; }
M port/proc.c => port/proc.c +1 -1