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