xref: /csrg-svn/usr.bin/f77/libF77/trpfpe_.c (revision 13576)
1*13576Sdlw /* #define	OLD_BSD		if you're running < 4.2bsd */
2*13576Sdlw /*
3*13576Sdlw char	id_trpfpe[] = "@(#)trpfpe_.c	1.1";
4*13576Sdlw  *
5*13576Sdlw  *	Fortran floating-point error handler
6*13576Sdlw  *
7*13576Sdlw  *	Synopsis:
8*13576Sdlw  *		call trpfpe (n, retval)
9*13576Sdlw  *			causes floating point faults to be trapped, with the
10*13576Sdlw  *			first 'n' errors getting a message printed.
11*13576Sdlw  *			'retval' is put in place of the bad result.
12*13576Sdlw  *		k = fpecnt()
13*13576Sdlw  *			causes 'k' to get the number of errors since the
14*13576Sdlw  *			last call to trpfpe().
15*13576Sdlw  *
16*13576Sdlw  *		common /fpeflt/ fpflag
17*13576Sdlw  *		logical fpflag
18*13576Sdlw  *			fpflag will become .true. on faults
19*13576Sdlw  *
20*13576Sdlw  *	David Wasley, UCBerkeley, June 1983.
21*13576Sdlw  */
22*13576Sdlw 
23*13576Sdlw 
24*13576Sdlw #include <stdio.h>
25*13576Sdlw #include <signal.h>
26*13576Sdlw #include "opcodes.h"
27*13576Sdlw #include "operand.h"
28*13576Sdlw #include "../libI77/fiodefs.h"
29*13576Sdlw 
30*13576Sdlw #define	SIG_VAL		int (*)()
31*13576Sdlw 
32*13576Sdlw #if	vax		/* only works on VAXen */
33*13576Sdlw 
34*13576Sdlw struct arglist {		/* what AP points to */
35*13576Sdlw 	long	al_numarg;	/* only true in CALLS format */
36*13576Sdlw 	long	al_arg[256];
37*13576Sdlw };
38*13576Sdlw 
39*13576Sdlw struct cframe {			/* VAX call frame */
40*13576Sdlw 	long		cf_handler;
41*13576Sdlw 	unsigned short	cf_psw;
42*13576Sdlw 	unsigned short	cf_mask;
43*13576Sdlw 	struct arglist	*cf_ap;
44*13576Sdlw 	struct cframe	*cf_fp;
45*13576Sdlw 	char		*cf_pc;
46*13576Sdlw };
47*13576Sdlw 
48*13576Sdlw /*
49*13576Sdlw  * bits in the PSW
50*13576Sdlw  */
51*13576Sdlw #define	PSW_V	0x2
52*13576Sdlw #define	PSW_FU	0x40
53*13576Sdlw #define	PSW_IV	0x20
54*13576Sdlw 
55*13576Sdlw /*
56*13576Sdlw  * where the registers are stored as we see them in the handler
57*13576Sdlw  */
58*13576Sdlw struct reg0_6 {
59*13576Sdlw 	long	reg[7];
60*13576Sdlw };
61*13576Sdlw 
62*13576Sdlw struct reg7_11 {
63*13576Sdlw 	long	reg[5];
64*13576Sdlw };
65*13576Sdlw 
66*13576Sdlw #define	iR0	reg0_6->reg[0]
67*13576Sdlw #define	iR1	reg0_6->reg[1]
68*13576Sdlw #define	iR2	reg0_6->reg[2]
69*13576Sdlw #define	iR3	reg0_6->reg[3]
70*13576Sdlw #define	iR4	reg0_6->reg[4]
71*13576Sdlw #define	iR5	reg0_6->reg[5]
72*13576Sdlw #define	iR6	reg0_6->reg[6]
73*13576Sdlw #define	iR7	reg7_11->reg[0]
74*13576Sdlw #define	iR8	reg7_11->reg[1]
75*13576Sdlw #define	iR9	reg7_11->reg[2]
76*13576Sdlw #define	iR10	reg7_11->reg[3]
77*13576Sdlw #define	iR11	reg7_11->reg[4]
78*13576Sdlw 
79*13576Sdlw union objects {		/* for load/store */
80*13576Sdlw 	char	ua_byte;
81*13576Sdlw 	short	ua_word;
82*13576Sdlw 	long	ua_long;
83*13576Sdlw 	float	ua_float;
84*13576Sdlw 	double	ua_double;
85*13576Sdlw 	union objects	*ua_anything;
86*13576Sdlw };
87*13576Sdlw 
88*13576Sdlw typedef union objects	anything;
89*13576Sdlw enum object_type { BYTE, WORD, LONG, FLOAT, QUAD, DOUBLE, UNKNOWN };
90*13576Sdlw 
91*13576Sdlw 
92*13576Sdlw /*
93*13576Sdlw  * assembly language assist
94*13576Sdlw  * There are some things you just can't do in C
95*13576Sdlw  */
96*13576Sdlw asm(".text");
97*13576Sdlw 
98*13576Sdlw struct cframe	*myfp();
99*13576Sdlw asm("_myfp: .word 0x0");
100*13576Sdlw 	asm("movl 12(fp),r0");
101*13576Sdlw 	asm("ret");
102*13576Sdlw 
103*13576Sdlw struct arglist	*myap();
104*13576Sdlw asm("_myap: .word 0x0");
105*13576Sdlw 	asm("movl 8(fp),r0");
106*13576Sdlw 	asm("ret");
107*13576Sdlw 
108*13576Sdlw char	*mysp();
109*13576Sdlw asm("_mysp: .word 0x0");
110*13576Sdlw 	asm("extzv $30,$2,4(fp),r0");
111*13576Sdlw 	asm("addl2 ap,r0");	/* SP in caller is AP+4 here + SPA bits! */
112*13576Sdlw 	asm("addl2 $4,r0");
113*13576Sdlw 	asm("ret");
114*13576Sdlw 
115*13576Sdlw char	*mypc();
116*13576Sdlw asm("_mypc: .word 0x0");
117*13576Sdlw 	asm("movl 16(fp),r0");
118*13576Sdlw 	asm("ret");
119*13576Sdlw 
120*13576Sdlw asm(".data");
121*13576Sdlw 
122*13576Sdlw 
123*13576Sdlw /*
124*13576Sdlw  * Where interrupted objects are
125*13576Sdlw  */
126*13576Sdlw static struct cframe	**ifp;	/* addr of saved FP */
127*13576Sdlw static struct arglist	**iap;	/* addr of saved AP */
128*13576Sdlw static char		 *isp;	/* value of interrupted SP */
129*13576Sdlw static char		**ipc;	/* addr of saved PC */
130*13576Sdlw static struct reg0_6	*reg0_6;/* registers 0-6 are saved on the exception */
131*13576Sdlw static struct reg7_11	*reg7_11;/* we save 7-11 by our entry mask */
132*13576Sdlw static anything		*result_addr;	/* where the dummy result goes */
133*13576Sdlw static enum object_type	 result_type;	/* what kind of object it is */
134*13576Sdlw 
135*13576Sdlw /*
136*13576Sdlw  * some globals
137*13576Sdlw  */
138*13576Sdlw static union {
139*13576Sdlw 	long	rv_long[2];
140*13576Sdlw 	float	rv_float;
141*13576Sdlw 	double	rv_double;
142*13576Sdlw 			} retval; /* the user specified dummy result */
143*13576Sdlw static int	max_messages	= 1;		/* the user can tell us */
144*13576Sdlw static int	fpe_count	= 0;		/* how bad is it ? */
145*13576Sdlw        long	fpeflt_		= 0;	/* fortran "common /fpeflt/ flag" */
146*13576Sdlw static int	(*sigfpe_dfl)()	= SIG_DFL;	/* if we can't fix it ... */
147*13576Sdlw 
148*13576Sdlw /*
149*13576Sdlw  * The fortran unit control table
150*13576Sdlw  */
151*13576Sdlw extern unit units[];
152*13576Sdlw 
153*13576Sdlw /*
154*13576Sdlw  * Fortran message table is in main
155*13576Sdlw  */
156*13576Sdlw struct msgtbl {
157*13576Sdlw 	char	*mesg;
158*13576Sdlw 	int	dummy;
159*13576Sdlw };
160*13576Sdlw extern struct msgtbl	act_fpe[];
161*13576Sdlw 
162*13576Sdlw 
163*13576Sdlw /*
164*13576Sdlw  * Get the address of the (saved) next operand & update saved PC.
165*13576Sdlw  * The major purpose of this is to determine where to store the result.
166*13576Sdlw  * There is one case we can't deal with: -(SP) or (SP)+
167*13576Sdlw  * since we can't change the size of the stack.
168*13576Sdlw  * Let's just hope compilers don't generate that for results.
169*13576Sdlw  */
170*13576Sdlw 
171*13576Sdlw anything *
172*13576Sdlw get_operand (oper_size)
173*13576Sdlw 	int	oper_size;	/* size of operand we expect */
174*13576Sdlw {
175*13576Sdlw 	register int	regnum;
176*13576Sdlw 	register int	operand_code;
177*13576Sdlw 	int		index;
178*13576Sdlw 	anything	*oper_addr;
179*13576Sdlw 	anything	*reg_addr;
180*13576Sdlw 
181*13576Sdlw 	regnum = (**ipc & 0xf);
182*13576Sdlw 	if (regnum == PC)
183*13576Sdlw 		operand_code = (*(*ipc)++ & 0xff);
184*13576Sdlw 	else
185*13576Sdlw 		operand_code = (*(*ipc)++ & 0xf0);
186*13576Sdlw 	if (regnum <= R6)
187*13576Sdlw 		reg_addr = (anything *)&reg0_6->reg[regnum];
188*13576Sdlw 	else if (regnum <= R11)
189*13576Sdlw 		reg_addr = (anything *)&reg7_11->reg[regnum];
190*13576Sdlw 	else if (regnum == AP)
191*13576Sdlw 		reg_addr = (anything *)iap;
192*13576Sdlw 	else if (regnum == FP)
193*13576Sdlw 		reg_addr = (anything *)ifp;
194*13576Sdlw 	else if (regnum == SP)
195*13576Sdlw 		reg_addr = (anything *)&isp;	/* We saved this ourselves */
196*13576Sdlw 	else if (regnum == PC)
197*13576Sdlw 		reg_addr = (anything *)ipc;
198*13576Sdlw 
199*13576Sdlw 
200*13576Sdlw 	switch (operand_code)
201*13576Sdlw 	{
202*13576Sdlw 		case IMMEDIATE:
203*13576Sdlw 			oper_addr = (anything *)(*ipc);
204*13576Sdlw 			*ipc += oper_size;
205*13576Sdlw 			return(oper_addr);
206*13576Sdlw 
207*13576Sdlw 		case ABSOLUTE:
208*13576Sdlw 			oper_addr = (anything *)(**ipc);
209*13576Sdlw 			*ipc += sizeof (anything *);
210*13576Sdlw 			return(oper_addr);
211*13576Sdlw 
212*13576Sdlw 		case LITERAL0:
213*13576Sdlw 		case LITERAL1:
214*13576Sdlw 		case LITERAL2:
215*13576Sdlw 		case LITERAL3:
216*13576Sdlw 			/* we don't care about the address of these */
217*13576Sdlw 			return((anything *)0);
218*13576Sdlw 
219*13576Sdlw 		case INDEXED:
220*13576Sdlw 			index = reg_addr->ua_long * oper_size;
221*13576Sdlw 			oper_addr = (anything *)(get_operand(sizeof (long))->ua_long + index);
222*13576Sdlw 			return(oper_addr);
223*13576Sdlw 
224*13576Sdlw 		case REGISTER:
225*13576Sdlw 			return(reg_addr);
226*13576Sdlw 
227*13576Sdlw 		case REGDEFERED:
228*13576Sdlw 			return(reg_addr->ua_anything);
229*13576Sdlw 
230*13576Sdlw 		case AUTODEC:
231*13576Sdlw 			if (regnum == SP)
232*13576Sdlw 			{
233*13576Sdlw 				fprintf(stderr, "trp: can't fix -(SP) operand\n");
234*13576Sdlw 				exit(1);
235*13576Sdlw 			}
236*13576Sdlw 			reg_addr->ua_long -= oper_size;
237*13576Sdlw 			oper_addr = reg_addr->ua_anything;
238*13576Sdlw 			return(oper_addr);
239*13576Sdlw 
240*13576Sdlw 		case AUTOINC:
241*13576Sdlw 			if (regnum == SP)
242*13576Sdlw 			{
243*13576Sdlw 				fprintf(stderr, "trp: can't fix (SP)+ operand\n");
244*13576Sdlw 				exit(1);
245*13576Sdlw 			}
246*13576Sdlw 			oper_addr = reg_addr->ua_anything;
247*13576Sdlw 			reg_addr->ua_long += oper_size;
248*13576Sdlw 			return(oper_addr);
249*13576Sdlw 
250*13576Sdlw 		case AUTOINCDEF:
251*13576Sdlw 			if (regnum == SP)
252*13576Sdlw 			{
253*13576Sdlw 				fprintf(stderr, "trp: can't fix @(SP)+ operand\n");
254*13576Sdlw 				exit(1);
255*13576Sdlw 			}
256*13576Sdlw 			oper_addr = (reg_addr->ua_anything)->ua_anything;
257*13576Sdlw 			reg_addr->ua_long += sizeof (anything *);
258*13576Sdlw 			return(oper_addr);
259*13576Sdlw 
260*13576Sdlw 		case BYTEDISP:
261*13576Sdlw 		case BYTEREL:
262*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_byte + reg_addr->ua_long);
263*13576Sdlw 			*ipc += sizeof (char);
264*13576Sdlw 			return(oper_addr);
265*13576Sdlw 
266*13576Sdlw 		case BYTEDISPDEF:
267*13576Sdlw 		case BYTERELDEF:
268*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_byte + reg_addr->ua_long);
269*13576Sdlw 			oper_addr = oper_addr->ua_anything;
270*13576Sdlw 			*ipc += sizeof (char);
271*13576Sdlw 			return(oper_addr);
272*13576Sdlw 
273*13576Sdlw 		case WORDDISP:
274*13576Sdlw 		case WORDREL:
275*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_word + reg_addr->ua_long);
276*13576Sdlw 			*ipc += sizeof (short);
277*13576Sdlw 			return(oper_addr);
278*13576Sdlw 
279*13576Sdlw 		case WORDDISPDEF:
280*13576Sdlw 		case WORDRELDEF:
281*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_word + reg_addr->ua_long);
282*13576Sdlw 			oper_addr = oper_addr->ua_anything;
283*13576Sdlw 			*ipc += sizeof (short);
284*13576Sdlw 			return(oper_addr);
285*13576Sdlw 
286*13576Sdlw 		case LONGDISP:
287*13576Sdlw 		case LONGREL:
288*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_long + reg_addr->ua_long);
289*13576Sdlw 			*ipc += sizeof (long);
290*13576Sdlw 			return(oper_addr);
291*13576Sdlw 
292*13576Sdlw 		case LONGDISPDEF:
293*13576Sdlw 		case LONGRELDEF:
294*13576Sdlw 			oper_addr = (anything *)(((anything *)(*ipc))->ua_long + reg_addr->ua_long);
295*13576Sdlw 			oper_addr = oper_addr->ua_anything;
296*13576Sdlw 			*ipc += sizeof (long);
297*13576Sdlw 			return(oper_addr);
298*13576Sdlw 
299*13576Sdlw 		/* NOTREACHED */
300*13576Sdlw 	}
301*13576Sdlw }
302*13576Sdlw 
303*13576Sdlw /*
304*13576Sdlw  * Trap & repair floating exceptions so that a program may proceed.
305*13576Sdlw  * There is no notion of "correctness" here; just the ability to continue.
306*13576Sdlw  *
307*13576Sdlw  * The on_fpe() routine first checks the type code to see if the
308*13576Sdlw  * exception is repairable. If so, it checks the opcode to see if
309*13576Sdlw  * it is one that it knows. If this is true, it then simulates the
310*13576Sdlw  * VAX cpu in retrieving operands in order to increment iPC correctly.
311*13576Sdlw  * It notes where the result of the operation would have been stored
312*13576Sdlw  * and substitutes a previously supplied value.
313*13576Sdlw  */
314*13576Sdlw 
315*13576Sdlw #ifdef	OLD_BSD
316*13576Sdlw on_fpe(signo, code, myaddr, pc, ps)
317*13576Sdlw 	int signo, code, ps;
318*13576Sdlw 	char *myaddr, *pc;
319*13576Sdlw #else
320*13576Sdlw on_fpe(signo, code, sc, grbg)
321*13576Sdlw 	int signo, code;
322*13576Sdlw 	struct sigcontext *sc;
323*13576Sdlw #endif
324*13576Sdlw {
325*13576Sdlw 	/*
326*13576Sdlw 	 * There must be at least 5 register variables here
327*13576Sdlw 	 * so our entry mask will save R11-R7.
328*13576Sdlw 	 */
329*13576Sdlw 	register long	*stk;
330*13576Sdlw 	register long	*sp;
331*13576Sdlw 	register struct arglist	*ap;
332*13576Sdlw 	register struct cframe	*fp;
333*13576Sdlw 	register FILE	*ef;
334*13576Sdlw 
335*13576Sdlw 	ef = units[STDERR].ufd;		/* fortran error stream */
336*13576Sdlw 
337*13576Sdlw 	switch (code)
338*13576Sdlw 	{
339*13576Sdlw 		case FPE_INTOVF_TRAP:	/* integer overflow */
340*13576Sdlw 		case FPE_INTDIV_TRAP:	/* integer divide by zero */
341*13576Sdlw 		case FPE_FLTOVF_TRAP:	/* floating overflow */
342*13576Sdlw 		case FPE_FLTDIV_TRAP:	/* floating/decimal divide by zero */
343*13576Sdlw 		case FPE_FLTUND_TRAP:	/* floating underflow */
344*13576Sdlw 		case FPE_DECOVF_TRAP:	/* decimal overflow */
345*13576Sdlw 		case FPE_SUBRNG_TRAP:	/* subscript out of range */
346*13576Sdlw 		default:
347*13576Sdlw cant_fix:
348*13576Sdlw 			if (sigfpe_dfl > (SIG_VAL)7)	/* user specified */
349*13576Sdlw #ifdef	OLD_BSD
350*13576Sdlw 				return((*sigfpe_dfl)(signo, code, myaddr, pc, ps));
351*13576Sdlw #else
352*13576Sdlw 				return((*sigfpe_dfl)(signo, code, sc, grbg));
353*13576Sdlw #endif
354*13576Sdlw 			else
355*13576Sdlw #ifdef	OLD_BSD
356*13576Sdlw 				sigdie(signo, code, myaddr, pc, ps);
357*13576Sdlw #else
358*13576Sdlw 				sigdie(signo, code, sc, grbg);
359*13576Sdlw #endif
360*13576Sdlw 			/* NOTREACHED */
361*13576Sdlw 
362*13576Sdlw 		case FPE_FLTOVF_FAULT:	/* floating overflow fault */
363*13576Sdlw 		case FPE_FLTDIV_FAULT:	/* divide by zero floating fault */
364*13576Sdlw 		case FPE_FLTUND_FAULT:	/* floating underflow fault */
365*13576Sdlw 			if (++fpe_count <= max_messages) {
366*13576Sdlw 				fprintf(ef, "trpfpe: %s",
367*13576Sdlw 					act_fpe[code-1].mesg);
368*13576Sdlw 				if (fpe_count == max_messages)
369*13576Sdlw 					fprintf(ef, ": No more messages will be printed.\n");
370*13576Sdlw 				else
371*13576Sdlw 					fputc('\n', ef);
372*13576Sdlw 			}
373*13576Sdlw 			fpeflt_ = -1;
374*13576Sdlw 			break;
375*13576Sdlw 	}
376*13576Sdlw 
377*13576Sdlw 	ap = myap();			/* my arglist pointer */
378*13576Sdlw 	fp = myfp();			/* my frame pointer */
379*13576Sdlw 	ifp = &(fp->cf_fp)->cf_fp;	/* user's stored in next frame back */
380*13576Sdlw 	iap = &(fp->cf_fp)->cf_ap;
381*13576Sdlw 	/*
382*13576Sdlw 	 * these are likely to be system dependent
383*13576Sdlw 	 */
384*13576Sdlw 	reg0_6 = (struct reg0_6 *)((char *)fp->cf_fp + sizeof (struct cframe));
385*13576Sdlw 	reg7_11 = (struct reg7_11 *)((char *)fp->cf_fp - sizeof (struct reg7_11));
386*13576Sdlw 
387*13576Sdlw #ifdef	OLD_BSD
388*13576Sdlw 	ipc = &pc;
389*13576Sdlw 	isp = (char *)&ap->al_arg[ap->al_numarg + 2];	/* assumes 2 dummys */
390*13576Sdlw 	ps &= ~(PSW_V|PSW_FU);
391*13576Sdlw #else
392*13576Sdlw 	ipc = (char **)&sc->sc_pc;
393*13576Sdlw 	isp = (char *)&ap->al_arg[ap->al_numarg] + sizeof (struct sigcontext);
394*13576Sdlw 	sc->sc_ps &= ~(PSW_V|PSW_FU);
395*13576Sdlw #endif
396*13576Sdlw 
397*13576Sdlw 
398*13576Sdlw 	switch (*(*ipc)++)
399*13576Sdlw 	{
400*13576Sdlw 		case ADDD3:
401*13576Sdlw 		case DIVD3:
402*13576Sdlw 		case MULD3:
403*13576Sdlw 		case SUBD3:
404*13576Sdlw 			(void) get_operand(sizeof (double));
405*13576Sdlw 			/* intentional fall-thru */
406*13576Sdlw 
407*13576Sdlw 		case ADDD2:
408*13576Sdlw 		case DIVD2:
409*13576Sdlw 		case MULD2:
410*13576Sdlw 		case SUBD2:
411*13576Sdlw 		case MNEGD:
412*13576Sdlw 		case MOVD:
413*13576Sdlw 			(void) get_operand(sizeof (double));
414*13576Sdlw 			result_addr = get_operand(sizeof (double));
415*13576Sdlw 			result_type = DOUBLE;
416*13576Sdlw 			break;
417*13576Sdlw 
418*13576Sdlw 		case ADDF3:
419*13576Sdlw 		case DIVF3:
420*13576Sdlw 		case MULF3:
421*13576Sdlw 		case SUBF3:
422*13576Sdlw 			(void) get_operand(sizeof (float));
423*13576Sdlw 			/* intentional fall-thru */
424*13576Sdlw 
425*13576Sdlw 		case ADDF2:
426*13576Sdlw 		case DIVF2:
427*13576Sdlw 		case MULF2:
428*13576Sdlw 		case SUBF2:
429*13576Sdlw 		case MNEGF:
430*13576Sdlw 		case MOVF:
431*13576Sdlw 			(void) get_operand(sizeof (float));
432*13576Sdlw 			result_addr = get_operand(sizeof (float));
433*13576Sdlw 			result_type = FLOAT;
434*13576Sdlw 			break;
435*13576Sdlw 
436*13576Sdlw 		case CVTDF:
437*13576Sdlw 			(void) get_operand(sizeof (double));
438*13576Sdlw 			result_addr = get_operand(sizeof (float));
439*13576Sdlw 			result_type = FLOAT;
440*13576Sdlw 			break;
441*13576Sdlw 
442*13576Sdlw 		case CVTFD:
443*13576Sdlw 			(void) get_operand(sizeof (float));
444*13576Sdlw 			result_addr = get_operand(sizeof (double));
445*13576Sdlw 			result_type = DOUBLE;
446*13576Sdlw 			break;
447*13576Sdlw 
448*13576Sdlw 		case EMODF:
449*13576Sdlw 		case EMODD:
450*13576Sdlw 			fprintf(ef, "trpfpe: can't fix emod yet\n");
451*13576Sdlw 			goto cant_fix;
452*13576Sdlw 
453*13576Sdlw 		case POLYF:
454*13576Sdlw 		case POLYD:
455*13576Sdlw 			fprintf(ef, "trpfpe: can't fix poly yet\n");
456*13576Sdlw 			goto cant_fix;
457*13576Sdlw 
458*13576Sdlw 		case ACBD:
459*13576Sdlw 		case ACBF:
460*13576Sdlw 		case CMPD:
461*13576Sdlw 		case CMPF:
462*13576Sdlw 		case TSTD:
463*13576Sdlw 		case TSTF:
464*13576Sdlw 		case CVTDB:
465*13576Sdlw 		case CVTDL:
466*13576Sdlw 		case CVTDW:
467*13576Sdlw 		case CVTFB:
468*13576Sdlw 		case CVTFL:
469*13576Sdlw 		case CVTFW:
470*13576Sdlw 		case CVTRDL:
471*13576Sdlw 		case CVTRFL:
472*13576Sdlw 			/* These can generate only reserved operand faults */
473*13576Sdlw 			/* They are shown here for completeness */
474*13576Sdlw 
475*13576Sdlw 		default:
476*13576Sdlw 			fprintf(stderr, "trp: opcode 0x%02x unknown\n",
477*13576Sdlw 				*(--(*ipc)) & 0xff);
478*13576Sdlw 			goto cant_fix;
479*13576Sdlw 			/* NOTREACHED */
480*13576Sdlw 	}
481*13576Sdlw 
482*13576Sdlw 	if (result_type == FLOAT)
483*13576Sdlw 		result_addr->ua_float = retval.rv_float;
484*13576Sdlw 	else
485*13576Sdlw 	{
486*13576Sdlw 		if (result_addr == (anything *)&iR6)
487*13576Sdlw 		{	/*
488*13576Sdlw 			 * special case - the R6/R7 pair is stored apart
489*13576Sdlw 			 */
490*13576Sdlw 			result_addr->ua_long = retval.rv_long[0];
491*13576Sdlw 			((anything *)&iR7)->ua_long = retval.rv_long[1];
492*13576Sdlw 		}
493*13576Sdlw 		else
494*13576Sdlw 			result_addr->ua_double = retval.rv_double;
495*13576Sdlw 	}
496*13576Sdlw 	signal(SIGFPE, on_fpe);
497*13576Sdlw }
498*13576Sdlw #endif	vax
499*13576Sdlw 
500*13576Sdlw trpfpe_ (count, rval)
501*13576Sdlw 	long	*count;	/* how many to announce */
502*13576Sdlw 	double	*rval;	/* dummy return value */
503*13576Sdlw {
504*13576Sdlw #if	vax
505*13576Sdlw 	max_messages = *count;
506*13576Sdlw 	retval.rv_double = *rval;
507*13576Sdlw 	sigfpe_dfl = signal(SIGFPE, on_fpe);
508*13576Sdlw 	fpe_count = 0;
509*13576Sdlw #endif
510*13576Sdlw }
511*13576Sdlw 
512*13576Sdlw long
513*13576Sdlw fpecnt_ ()
514*13576Sdlw {
515*13576Sdlw #if	vax
516*13576Sdlw 	return (fpe_count);
517*13576Sdlw #else
518*13576Sdlw 	return (0L);
519*13576Sdlw #endif
520*13576Sdlw }
521*13576Sdlw 
522