|
|
1.1 root 1: #
2: /*
3: * Simulate pdp11 floating point for compatability mode programs.
4: * Quick and dirty with no big effort at speed since it takes so
5: * much overhead to get here in the first place.
6: * I make no claims on the completeness of this simulation.
7: * Art Wetzel 3/16/80
8: */
9: #ifndef NOFPSIM
10: #ifdef DEBUG
11: #include <stdio.h>
12: #endif
13: #include "defs.h"
14: /* output codes */
15: #define NONE 0
16: #define SHORT 01
17: #define LONG 02
18: #define FLOAT 04
19: #define DOUBLE 010
20: #define OUTPUT 020
21: /* parts of fps */
22: #define FD 0200
23: #define FL 0100
24: #define FN 010
25: #define FZ 04
26: #define FV 02
27: #define FC 01
28: /* fis instructions */
29: #define FADD 075000
30: #define FSUB 075010
31: #define FMUL 075020
32: #define FDIV 075030
33: /* fpu instructions */
34: #define ABSD 0170600
35: #define ABSF 0170600
36: #define ADDD 0172000
37: #define ADDF 0172000
38: #define CFCC 0170000
39: #define CLRD 0170400
40: #define CLRF 0170400
41: #define CMPD 0173400
42: #define CMPF 0173400
43: #define DIVD 0174400
44: #define DIVF 0174400
45: #define LDCFD 0177400
46: #define LDCFF 0177400
47: #define LDCLD 0177000
48: #define LDCLF 0177000
49: #define LDCIF 0177000
50: #define LDCID 0177000
51: #define LDEXP 0176400
52: #define LDD 0172400
53: #define LDF 0172400
54: #define LDFPS 0170100
55: #define MODD 0171400
56: #define MODF 0171400
57: #define MULD 0171000
58: #define MULF 0171000
59: #define NEGD 0170700
60: #define NEGF 0170700
61: #define SETF 0170001
62: #define SETD 0170011
63: #define SETI 0170002
64: #define SETL 0170012
65: #define STCDF 0176000
66: #define STCFD 0176000
67: #define STCDL 0175400
68: #define STCDI 0175400
69: #define STCFL 0175400
70: #define STCFI 0175400
71: #define STEXP 0175000
72: #define STD 0174000
73: #define STF 0174000
74: #define STFPS 0170200
75: #define STST 0170300
76: #define SUBD 0173000
77: #define SUBF 0173000
78: #define TSTD 0170500
79: #define TSTF 0170500
80: union alltypes {
81: double d;
82: float f;
83: long l;
84: short s;
85: unsigned short p[4];
86: };
87: /* static storage for floating registers */
88: static union alltypes fregs[6];
89: static union alltypes srcdst;
90: int fps = FD|FL;
91: int dbl = 0;
92: int lng = 0;
93: #endif
94: dofloat(instr) unsigned int instr; {
95: #ifdef NOFPSIM
96: return(-1);
97: #else
98: register unsigned short *wptr;
99: register unsigned int opcode, ac, mode, fac, adjust, output, ccset;
100: unsigned short *locate();
101: /* indicate what condition codes will be changed by op - assume none */
102: ccset = 0;
103: /* type of memory output - assume none */
104: output = NONE;
105: /* default adjust to type */
106: if(dbl)
107: adjust = DOUBLE;
108: else
109: adjust = FLOAT;
110: /* chop up instruction to get relevent parts */
111: opcode = instr & 0177700;
112: fac = (instr>>6) & 03;
113: mode = (instr>>3) & 07;
114: ac = instr & 07;
115: /* if the instruction uses a src/dst construct ptr and fetch */
116: switch(opcode) {
117: case FADD:
118: case CFCC:
119: break;
120: default:
121: wptr = locate(mode, ac);
122: /* special case for mode 0 */
123: if(mode == 0) switch(opcode & 0177400) {
124: /* special instructions to use cpu regs */
125: case LDEXP:
126: case STEXP:
127: wptr = ®s[ac];
128: break;
129: case STCDL:
130: wptr = ®s[ac];
131: default:
132: break;
133: }
134: if(dbl)
135: srcdst.d = *(double *)wptr;
136: else
137: srcdst.f = *(float *)wptr;
138: /* immediate fetches are 16 bits */
139: if(ac == 7 && (mode == 2)) {
140: srcdst.p[1] = 0;
141: srcdst.p[2] = 0;
142: srcdst.p[3] = 0;
143: }
144: break;
145: }
146: #ifdef DEBUG
147: fprintf(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);
148: #endif
149: switch(opcode) {
150: case FADD:
151: /* catches all fis instructions */
152: /* last 3 bits are stack pointer register */
153: ac = instr & 07;
154: /* get pointer to stack words */
155: wptr = (unsigned short *)regs[ac];
156: /* getch floating value from stack */
157: srcdst.f = *(float *)wptr;
158: /* shorten stack */
159: wptr += 2;
160: /* do appropriate operation */
161: switch(instr & 0177770) {
162: case FADD:
163: srcdst.f += *(float *)wptr;
164: break;
165: case FSUB:
166: srcdst.f = *(float *)wptr - srcdst.f;
167: break;
168: case FMUL:
169: srcdst.f *= *(float *)wptr;
170: break;
171: case FDIV:
172: srcdst.f = *(float *)wptr / srcdst.f;
173: break;
174: default:
175: return(-1);
176: }
177: /* copy out result */
178: *(float *)wptr = srcdst.f;
179: /* set up condition codes */
180: psl &= ~017;
181: if(srcdst.f == 0.) psl |= FZ;
182: if(srcdst.f < 0.) psl |= FN;
183: /* adjust register to reflect stack change */
184: regs[ac] = (unsigned short)(int)wptr;
185: return(0);
186: case CFCC:
187: switch(instr) {
188: case SETF:
189: dbl = 0;
190: break;
191: case SETD:
192: dbl = 1;
193: break;
194: case SETI:
195: lng = 0;
196: break;
197: case SETL:
198: lng = 1;
199: break;
200: case CFCC:
201: psl &= ~017;
202: psl |= (fps & 017);
203: #ifdef DEBUG
204: fprintf(stderr,"CFCC %o\n",psl);
205: #endif
206: break;
207: default:
208: return(-1);
209: }
210: return(0);
211: case ABSD:
212: if(srcdst.d < 0.0 ) srcdst.d = -srcdst.d;
213: ccset = FZ;
214: if(dbl)
215: output = DOUBLE;
216: else
217: output = FLOAT;
218: break;
219: case CLRD:
220: srcdst.d =0.0;
221: ccset = FZ;
222: if(dbl)
223: output = DOUBLE;
224: else
225: output = FLOAT;
226: break;
227: case LDFPS:
228: adjust = SHORT;
229: fps = srcdst.s;
230: if(fps & FD)
231: dbl = 1;
232: else
233: dbl = 0;
234: if(fps & FL )
235: lng = 1;
236: else
237: lng = 0;
238: break;
239: case NEGD:
240: srcdst.d = -srcdst.d;
241: ccset = FZ|FN;
242: if(dbl)
243: output = DOUBLE;
244: else
245: output = FLOAT;
246: break;
247: case STFPS:
248: srcdst.s = fps;
249: adjust = output = SHORT;
250: break;
251: case STST:
252: return(0);
253: break;
254: case TSTD:
255: ccset = FZ|FN;
256: break;
257: default:
258: opcode = instr & 0177400;
259: switch(opcode) {
260: case STD:
261: srcdst.d = fregs[fac].d;
262: #ifdef DEBUG
263: fprintf(stderr,"STD %o\n",srcdst.s);
264: #endif
265: if(dbl)
266: output = DOUBLE;
267: else
268: output = FLOAT;
269: break;
270: case LDD:
271: #ifdef DEBUG
272: fprintf(stderr,"LDD %o\n",srcdst.s);
273: #endif
274: fregs[fac].d = srcdst.d;
275: ccset = FZ|FN;
276: break;
277: case ADDD:
278: fregs[fac].d += srcdst.d;
279: ccset = FZ|FN;
280: break;
281: case SUBD:
282: fregs[fac].d -= srcdst.d;
283: ccset = FZ|FN;
284: break;
285: case MULD:
286: fregs[fac].d *= srcdst.d;
287: ccset = FZ|FN;
288: break;
289: case DIVD:
290: #ifdef DEBUG
291: fprintf(stderr,"DIVD %f by %f gives ",fregs[fac].d,srcdst.d);
292: #endif
293: fregs[fac].d /= srcdst.d;
294: #ifdef DEBUG
295: fprintf(stderr,"-> %f\n",fregs[fac].d);
296: #endif
297: ccset = FZ|FN;
298: break;
299: case STCDF:
300: adjust = output = FLOAT;
301: ccset = FZ|FN;
302: break;
303: case LDCFD:
304: adjust = FLOAT;
305: ccset = FZ|FN;
306: break;
307: case LDCLD:
308: if(lng) {
309: adjust = LONG;
310: srcdst.d = srcdst.l;
311: } else {
312: adjust = SHORT;
313: srcdst.d = srcdst.s;
314: }
315: ccset = FZ|FN;
316: break;
317: case CMPD:
318: srcdst.d -= fregs[fac].d;
319: ccset = FZ|FN;
320: break;
321: case LDEXP:
322: srcdst.d = 0.0;
323: srcdst.s = *wptr;
324: srcdst.s <<= 7;
325: srcdst.s += 0200;
326: adjust = SHORT;
327: ccset = FZ|FN;
328: #ifdef DEBUG
329: fprintf(stderr,"LDEXP %o gives %o\n",*wptr,srcdst.s);
330: #endif
331: break;
332: case MODD:
333: srcdst.d *= fregs[fac].d;
334: fregs[fac].d = (double)(long)srcdst.d;
335: if(~fac & 1) fregs[fac + 1].d = fregs[fac].d;
336: srcdst.d -= fregs[fac].d;
337: ccset = FN|FZ;
338: fregs[fac].d = srcdst.d;
339: #ifdef DEBUG
340: fprintf(stderr,"MODD %o %o\n",fregs[fac].s,fregs[fac+1].s);
341: #endif
342: break;
343: case STCDL:
344: if(lng)
345: adjust = output = LONG;
346: else
347: adjust = output = SHORT;
348: if(mode == 0) output = SHORT;
349: srcdst.l = fregs[fac].d;
350: #ifdef DEBUG
351: fprintf(stderr,"STCDL %o\n",srcdst.l);
352: #endif
353: ccset = FZ|FN;
354: break;
355: case STEXP:
356: #ifdef DEBUG
357: fprintf(stderr,"STEXP of %o gives ",srcdst.s);
358: #endif
359: srcdst.s &= 077600;
360: srcdst.s >>= 7;
361: srcdst.s -= 0200;
362: adjust = output = SHORT;
363: ccset = FZ|FN;
364: #ifdef DEBUG
365: fprintf(stderr,"%o\n",srcdst.s);
366: #endif
367: break;
368: default:
369: return(-1);
370: }
371: }
372: if(ccset & FZ) {
373: fps &= ~FZ;
374: if(srcdst.d == 0.0) fps |= FZ;
375: if(!dbl && srcdst.f == 0.0) fps |= FZ;
376: }
377: if(ccset & FN) {
378: fps &= ~FN;
379: if(srcdst.f < 0.0) fps |= FN;
380: }
381: switch(instr & 0177400) {
382: case STCDL:
383: case STEXP:
384: psl &= ~017;
385: psl |= (fps & 017);
386: break;
387: default:
388: break;
389: }
390: switch(output) {
391: case NONE:
392: break;
393: case SHORT:
394: *((short *)wptr) = srcdst.s;
395: srcdst.d = 0.0;
396: break;
397: case LONG:
398: if(mode == 4) wptr--;
399: *((long *)wptr) = longrev(srcdst.l);
400: break;
401: case FLOAT:
402: if(mode == 4) wptr--;
403: *((float *)wptr) = srcdst.f;
404: break;
405: case DOUBLE:
406: if(mode == 4) wptr -= 3;
407: *((double *)wptr) = srcdst.d;
408: break;
409: }
410: switch(mode) {
411: case 0:
412: case 1:
413: break;
414: case 2:
415: switch(adjust) {
416: case SHORT:
417: regs[ac] += 2;
418: break;
419: case LONG:
420: case FLOAT:
421: regs[ac] += 4;
422: break;
423: case DOUBLE:
424: regs[ac] += 8;
425: break;
426: case NONE:
427: break;
428: }
429: if(ac == 7) pc++;
430: break;
431: case 3:
432: regs[ac] += 2;
433: if(ac == 7) pc++;
434: break;
435: case 4:
436: switch(adjust) {
437: case SHORT:
438: regs[ac] -= 2;
439: break;
440: case LONG:
441: case FLOAT:
442: regs[ac] -= 4;
443: break;
444: case DOUBLE:
445: regs[ac] -= 8;
446: break;
447: case NONE:
448: break;
449: }
450: break;
451: case 5:
452: regs[ac] -= 2;
453: break;
454: case 6:
455: case 7:
456: pc++;
457: break;
458: }
459: return(0);
460: #endif
461: }
462: #ifndef NOFPSIM
463: unsigned short *locate(mode, ac) {
464: register unsigned short *wptr;
465: switch(mode) {
466: case 0:
467: /* mode 0 normally implies fregs */
468: wptr = (unsigned short *)&fregs[ac];
469: break;
470: case 1:
471: break;
472: case 2:
473: wptr = (unsigned short *)(int)regs[ac];
474: break;
475: case 3:
476: wptr = (unsigned short *)regs[ac];
477: wptr = (unsigned short *)*wptr;
478: break;
479: case 4:
480: wptr = (unsigned short *)regs[ac];
481: wptr--;
482: break;
483: case 5:
484: wptr = (unsigned short *)regs[ac];
485: wptr--;
486: wptr = (unsigned short *)*wptr;
487: break;
488: case 6:
489: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776);
490: if(ac == 7) wptr++;
491: break;
492: case 7:
493: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776);
494: if(ac == 7) wptr++;
495: wptr = (unsigned short *)*wptr;
496: break;
497: }
498: return(wptr);
499: }
500: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.