sync to release 4.1
[unix-history] / usr / src / old / games.vax / compat / dofloat.c
CommitLineData
cf108512 1#
c6dd5f9e 2static char sccsid[] = " dofloat.c 4.1 82/05/12 ";
cf108512
RH
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
81union 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 */
89static union alltypes fregs[6];
90static union alltypes srcdst;
91int fps = FD|FL;
92int dbl = 0;
93int lng = 0;
94#endif
95dofloat(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 = &regs[ac];
129 break;
130 case STCDL:
131 wptr = &regs[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
148fprintf(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
205fprintf(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
264fprintf(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
273fprintf(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
292fprintf(stderr,"DIVD %f by %f gives ",fregs[fac].d,srcdst.d);
293#endif
294 fregs[fac].d /= srcdst.d;
295#ifdef DEBUG
296fprintf(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
330fprintf(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
341fprintf(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
352fprintf(stderr,"STCDL %o\n",srcdst.l);
353#endif
354 ccset = FZ|FN;
355 break;
356 case STEXP:
357#ifdef DEBUG
358fprintf(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
366fprintf(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
464unsigned 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