📄 dofloat.c
字号:
#static char sccsid[] = " dofloat.c 4.1 82/05/12 ";/* * Simulate pdp11 floating point for compatability mode programs. * Quick and dirty with no big effort at speed since it takes so * much overhead to get here in the first place. * I make no claims on the completeness of this simulation. * Art Wetzel 3/16/80 */#ifndef NOFPSIM#ifdef DEBUG#include <stdio.h>#endif#include "defs.h"/* output codes */#define NONE 0#define SHORT 01#define LONG 02#define FLOAT 04#define DOUBLE 010#define OUTPUT 020/* parts of fps */#define FD 0200#define FL 0100#define FN 010#define FZ 04#define FV 02#define FC 01/* fis instructions */#define FADD 075000#define FSUB 075010#define FMUL 075020#define FDIV 075030/* fpu instructions */#define ABSD 0170600#define ABSF 0170600#define ADDD 0172000#define ADDF 0172000#define CFCC 0170000#define CLRD 0170400#define CLRF 0170400#define CMPD 0173400#define CMPF 0173400#define DIVD 0174400#define DIVF 0174400#define LDCFD 0177400#define LDCFF 0177400#define LDCLD 0177000#define LDCLF 0177000#define LDCIF 0177000#define LDCID 0177000#define LDEXP 0176400#define LDD 0172400#define LDF 0172400#define LDFPS 0170100#define MODD 0171400#define MODF 0171400#define MULD 0171000#define MULF 0171000#define NEGD 0170700#define NEGF 0170700#define SETF 0170001#define SETD 0170011#define SETI 0170002#define SETL 0170012#define STCDF 0176000#define STCFD 0176000#define STCDL 0175400#define STCDI 0175400#define STCFL 0175400#define STCFI 0175400#define STEXP 0175000#define STD 0174000#define STF 0174000#define STFPS 0170200#define STST 0170300#define SUBD 0173000#define SUBF 0173000#define TSTD 0170500#define TSTF 0170500union alltypes { double d; float f; long l; short s; unsigned short p[4];};/* static storage for floating registers */static union alltypes fregs[6];static union alltypes srcdst;int fps = FD|FL;int dbl = 0;int lng = 0;#endifdofloat(instr) unsigned int instr; {#ifdef NOFPSIM return(-1);#else register unsigned short *wptr; register unsigned int opcode, ac, mode, fac, adjust, output, ccset; unsigned short *locate(); /* indicate what condition codes will be changed by op - assume none */ ccset = 0; /* type of memory output - assume none */ output = NONE; /* default adjust to type */ if(dbl) adjust = DOUBLE; else adjust = FLOAT; /* chop up instruction to get relevent parts */ opcode = instr & 0177700; fac = (instr>>6) & 03; mode = (instr>>3) & 07; ac = instr & 07; /* if the instruction uses a src/dst construct ptr and fetch */ switch(opcode) { case FADD: case CFCC: break; default: wptr = locate(mode, ac); /* special case for mode 0 */ if(mode == 0) switch(opcode & 0177400) { /* special instructions to use cpu regs */ case LDEXP: case STEXP: wptr = ®s[ac]; break; case STCDL: wptr = ®s[ac]; default: break; } if(dbl) srcdst.d = *(double *)wptr; else srcdst.f = *(float *)wptr; /* immediate fetches are 16 bits */ if(ac == 7 && (mode == 2)) { srcdst.p[1] = 0; srcdst.p[2] = 0; srcdst.p[3] = 0; } break; }#ifdef DEBUGfprintf(stderr,"pc %o sp %o instr %o srcdst %o mode %o reg %o fac %o\n", pc-1,regs[6],instr,srcdst.s,mode,ac,fac);#endif switch(opcode) { case FADD: /* catches all fis instructions */ /* last 3 bits are stack pointer register */ ac = instr & 07; /* get pointer to stack words */ wptr = (unsigned short *)regs[ac]; /* getch floating value from stack */ srcdst.f = *(float *)wptr; /* shorten stack */ wptr += 2; /* do appropriate operation */ switch(instr & 0177770) { case FADD: srcdst.f += *(float *)wptr; break; case FSUB: srcdst.f = *(float *)wptr - srcdst.f; break; case FMUL: srcdst.f *= *(float *)wptr; break; case FDIV: srcdst.f = *(float *)wptr / srcdst.f; break; default: return(-1); } /* copy out result */ *(float *)wptr = srcdst.f; /* set up condition codes */ psl &= ~017; if(srcdst.f == 0.) psl |= FZ; if(srcdst.f < 0.) psl |= FN; /* adjust register to reflect stack change */ regs[ac] = (unsigned short)(int)wptr; return(0); case CFCC: switch(instr) { case SETF: dbl = 0; break; case SETD: dbl = 1; break; case SETI: lng = 0; break; case SETL: lng = 1; break; case CFCC: psl &= ~017; psl |= (fps & 017);#ifdef DEBUGfprintf(stderr,"CFCC %o\n",psl);#endif break; default: return(-1); } return(0); case ABSD: if(srcdst.d < 0.0 ) srcdst.d = -srcdst.d; ccset = FZ; if(dbl) output = DOUBLE; else output = FLOAT; break; case CLRD: srcdst.d =0.0; ccset = FZ; if(dbl) output = DOUBLE; else output = FLOAT; break; case LDFPS: adjust = SHORT; fps = srcdst.s; if(fps & FD) dbl = 1; else dbl = 0; if(fps & FL ) lng = 1; else lng = 0; break; case NEGD: srcdst.d = -srcdst.d; ccset = FZ|FN; if(dbl) output = DOUBLE; else output = FLOAT; break; case STFPS: srcdst.s = fps; adjust = output = SHORT; break; case STST: return(0); break; case TSTD: ccset = FZ|FN; break; default: opcode = instr & 0177400; switch(opcode) { case STD: srcdst.d = fregs[fac].d;#ifdef DEBUGfprintf(stderr,"STD %o\n",srcdst.s);#endif if(dbl) output = DOUBLE; else output = FLOAT; break; case LDD:#ifdef DEBUGfprintf(stderr,"LDD %o\n",srcdst.s);#endif fregs[fac].d = srcdst.d; ccset = FZ|FN; break; case ADDD: fregs[fac].d += srcdst.d; ccset = FZ|FN; break; case SUBD: fregs[fac].d -= srcdst.d; ccset = FZ|FN; break; case MULD: fregs[fac].d *= srcdst.d; ccset = FZ|FN; break; case DIVD:#ifdef DEBUGfprintf(stderr,"DIVD %f by %f gives ",fregs[fac].d,srcdst.d);#endif fregs[fac].d /= srcdst.d;#ifdef DEBUGfprintf(stderr,"-> %f\n",fregs[fac].d);#endif ccset = FZ|FN; break; case STCDF: adjust = output = FLOAT; ccset = FZ|FN; break; case LDCFD: adjust = FLOAT; ccset = FZ|FN; break; case LDCLD: if(lng) { adjust = LONG; srcdst.d = srcdst.l; } else { adjust = SHORT; srcdst.d = srcdst.s; } ccset = FZ|FN; break; case CMPD: srcdst.d -= fregs[fac].d; ccset = FZ|FN; break; case LDEXP: srcdst.d = 0.0; srcdst.s = *wptr; srcdst.s <<= 7; srcdst.s += 0200; adjust = SHORT; ccset = FZ|FN;#ifdef DEBUGfprintf(stderr,"LDEXP %o gives %o\n",*wptr,srcdst.s);#endif break; case MODD: srcdst.d *= fregs[fac].d; fregs[fac].d = (double)(long)srcdst.d; if(~fac & 1) fregs[fac + 1].d = fregs[fac].d; srcdst.d -= fregs[fac].d; ccset = FN|FZ; fregs[fac].d = srcdst.d;#ifdef DEBUGfprintf(stderr,"MODD %o %o\n",fregs[fac].s,fregs[fac+1].s);#endif break; case STCDL: if(lng) adjust = output = LONG; else adjust = output = SHORT; if(mode == 0) output = SHORT; srcdst.l = fregs[fac].d;#ifdef DEBUGfprintf(stderr,"STCDL %o\n",srcdst.l);#endif ccset = FZ|FN; break; case STEXP:#ifdef DEBUGfprintf(stderr,"STEXP of %o gives ",srcdst.s);#endif srcdst.s &= 077600; srcdst.s >>= 7; srcdst.s -= 0200; adjust = output = SHORT; ccset = FZ|FN;#ifdef DEBUGfprintf(stderr,"%o\n",srcdst.s);#endif break; default: return(-1); } } if(ccset & FZ) { fps &= ~FZ; if(srcdst.d == 0.0) fps |= FZ; if(!dbl && srcdst.f == 0.0) fps |= FZ; } if(ccset & FN) { fps &= ~FN; if(srcdst.f < 0.0) fps |= FN; } switch(instr & 0177400) { case STCDL: case STEXP: psl &= ~017; psl |= (fps & 017); break; default: break; } switch(output) { case NONE: break; case SHORT: *((short *)wptr) = srcdst.s; srcdst.d = 0.0; break; case LONG: if(mode == 4) wptr--; *((long *)wptr) = longrev(srcdst.l); break; case FLOAT: if(mode == 4) wptr--; *((float *)wptr) = srcdst.f; break; case DOUBLE: if(mode == 4) wptr -= 3; *((double *)wptr) = srcdst.d; break; } switch(mode) { case 0: case 1: break; case 2: switch(adjust) { case SHORT: regs[ac] += 2; break; case LONG: case FLOAT: regs[ac] += 4; break; case DOUBLE: regs[ac] += 8; break; case NONE: break; } if(ac == 7) pc++; break; case 3: regs[ac] += 2; if(ac == 7) pc++; break; case 4: switch(adjust) { case SHORT: regs[ac] -= 2; break; case LONG: case FLOAT: regs[ac] -= 4; break; case DOUBLE: regs[ac] -= 8; break; case NONE: break; } break; case 5: regs[ac] -= 2; break; case 6: case 7: pc++; break; } return(0);#endif}#ifndef NOFPSIMunsigned short *locate(mode, ac) { register unsigned short *wptr; switch(mode) { case 0: /* mode 0 normally implies fregs */ wptr = (unsigned short *)&fregs[ac]; break; case 1: break; case 2: wptr = (unsigned short *)(int)regs[ac]; break; case 3: wptr = (unsigned short *)regs[ac]; wptr = (unsigned short *)*wptr; break; case 4: wptr = (unsigned short *)regs[ac]; wptr--; break; case 5: wptr = (unsigned short *)regs[ac]; wptr--; wptr = (unsigned short *)*wptr; break; case 6: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776); if(ac == 7) wptr++; break; case 7: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776); if(ac == 7) wptr++; wptr = (unsigned short *)*wptr; break; } return(wptr);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -