xref: /csrg-svn/usr.bin/f77/libF77/trapov_.c (revision 39150)
18947Sdlw /*
222990Skre  * Copyright (c) 1980 Regents of the University of California.
322990Skre  * All rights reserved.  The Berkeley software License Agreement
422990Skre  * specifies the terms and conditions for redistribution.
58947Sdlw  *
6*39150Sbostic  *	@(#)trapov_.c	5.4	09/15/89
722995Skre  *
88947Sdlw  *	Fortran/C floating-point overflow handler
98947Sdlw  *
108947Sdlw  *	The idea of these routines is to catch floating-point overflows
118947Sdlw  *	and print an eror message.  When we then get a reserved operand
128947Sdlw  *	exception, we then fix up the value to the highest possible
138947Sdlw  *	number.  Keen, no?
148947Sdlw  *	Messy, yes!
158947Sdlw  *
168947Sdlw  *	Synopsis:
178947Sdlw  *		call trapov(n)
188947Sdlw  *			causes overflows to be trapped, with the first 'n'
198947Sdlw  *			overflows getting an "Overflow!" message printed.
208947Sdlw  *		k = ovcnt(0)
218947Sdlw  *			causes 'k' to get the number of overflows since the
228947Sdlw  *			last call to trapov().
238947Sdlw  *
248947Sdlw  *	Gary Klimowicz, April 17, 1981
258947Sdlw  *	Integerated with libF77: David Wasley, UCB, July 1981.
268947Sdlw  */
278947Sdlw 
288947Sdlw # include <stdio.h>
29*39150Sbostic # include <sys/signal.h>
308947Sdlw # include "opcodes.h"
318947Sdlw # include "../libI77/fiodefs.h"
32*39150Sbostic # define SIG_VAL	void (*)()
338947Sdlw 
348947Sdlw /*
3529960Smckusick  *	Potential operand values
3629960Smckusick  */
3729960Smckusick typedef	union operand_types {
3829960Smckusick 		char	o_byte;
3929960Smckusick 		short	o_word;
4029960Smckusick 		long	o_long;
4129960Smckusick 		float	o_float;
4229960Smckusick 		long	o_quad[2];
4329960Smckusick 		double	o_double;
4429960Smckusick 	} anyval;
4529960Smckusick 
4629960Smckusick /*
4729960Smckusick  *	the fortran unit control table
4829960Smckusick  */
4929960Smckusick extern unit units[];
5029960Smckusick 
5129960Smckusick /*
5229960Smckusick  * Fortran message table is in main
5329960Smckusick  */
5429960Smckusick struct msgtbl {
5529960Smckusick 	char	*mesg;
5629960Smckusick 	int	dummy;
5729960Smckusick };
5829960Smckusick extern struct msgtbl	act_fpe[];
5929960Smckusick 
6029960Smckusick anyval *get_operand_address(), *addr_of_reg();
6129960Smckusick char *opcode_name();
6229960Smckusick 
6329960Smckusick /*
6429960Smckusick  * trap type codes
6529960Smckusick  */
6629960Smckusick # define INT_OVF_T	1
6729960Smckusick # define INT_DIV_T	2
6829960Smckusick # define FLT_OVF_T	3
6929960Smckusick # define FLT_DIV_T	4
7029960Smckusick # define FLT_UND_T	5
7129960Smckusick # define DEC_OVF_T	6
7229960Smckusick # define SUB_RNG_T	7
7329960Smckusick # define FLT_OVF_F	8
7429960Smckusick # define FLT_DIV_F	9
7529960Smckusick # define FLT_UND_F	10
7629960Smckusick 
7729960Smckusick # define RES_ADR_F	0
7829960Smckusick # define RES_OPC_F	1
7929960Smckusick # define RES_OPR_F	2
8029960Smckusick 
8129960Smckusick #ifdef vax
8229960Smckusick /*
838947Sdlw  *	Operand modes
848947Sdlw  */
858947Sdlw # define LITERAL0	0x0
868947Sdlw # define LITERAL1	0x1
878947Sdlw # define LITERAL2	0x2
888947Sdlw # define LITERAL3	0x3
898947Sdlw # define INDEXED	0x4
908947Sdlw # define REGISTER	0x5
918947Sdlw # define REG_DEF	0x6
928947Sdlw # define AUTO_DEC	0x7
938947Sdlw # define AUTO_INC	0x8
948947Sdlw # define AUTO_INC_DEF	0x9
958947Sdlw # define BYTE_DISP	0xa
968947Sdlw # define BYTE_DISP_DEF	0xb
978947Sdlw # define WORD_DISP	0xc
988947Sdlw # define WORD_DISP_DEF	0xd
998947Sdlw # define LONG_DISP	0xe
1008947Sdlw # define LONG_DISP_DEF	0xf
1018947Sdlw 
1028947Sdlw /*
1038947Sdlw  *	Operand value types
1048947Sdlw  */
1058947Sdlw # define F		1
1068947Sdlw # define D		2
1078947Sdlw # define IDUNNO		3
1088947Sdlw 
1098947Sdlw # define PC	0xf
1108947Sdlw # define SP	0xe
1118947Sdlw # define FP	0xd
1128947Sdlw # define AP	0xc
1138947Sdlw 
1148947Sdlw /*
1158947Sdlw  *	GLOBAL VARIABLES (we need a few)
1168947Sdlw  *
1178947Sdlw  *	Actual program counter and locations of registers.
1188947Sdlw  */
1198947Sdlw static char	*pc;
1208947Sdlw static int	*regs0t6;
1218947Sdlw static int	*regs7t11;
1228947Sdlw static int	max_messages;
1238947Sdlw static int	total_overflows;
1248947Sdlw static union	{
1258947Sdlw 	long	v_long[2];
1268947Sdlw 	double	v_double;
1278947Sdlw 	} retrn;
128*39150Sbostic static sig_t sigill_default = (SIG_VAL)-1;
129*39150Sbostic static sig_t sigfpe_default;
1308947Sdlw 
1318947Sdlw /*
1328947Sdlw  *	This routine sets up the signal handler for the floating-point
1338947Sdlw  *	and reserved operand interrupts.
1348947Sdlw  */
1358947Sdlw 
1368947Sdlw trapov_(count, rtnval)
1378947Sdlw 	int *count;
1388947Sdlw 	double *rtnval;
1398947Sdlw {
140*39150Sbostic 	void got_overflow(), got_illegal_instruction();
1418947Sdlw 
14210238Sdlw 	sigfpe_default = signal(SIGFPE, got_overflow);
14310238Sdlw 	if (sigill_default == (SIG_VAL)-1)
14410238Sdlw 		sigill_default = signal(SIGILL, got_illegal_instruction);
1458947Sdlw 	total_overflows = 0;
1468947Sdlw 	max_messages = *count;
1478947Sdlw 	retrn.v_double = *rtnval;
1488947Sdlw }
1498947Sdlw 
1508947Sdlw 
1518947Sdlw 
1528947Sdlw /*
1538947Sdlw  *	got_overflow - routine called when overflow occurs
1548947Sdlw  *
1558947Sdlw  *	This routine just prints a message about the overflow.
1568947Sdlw  *	It is impossible to find the bad result at this point.
1578947Sdlw  *	Instead, we wait until we get the reserved operand exception
1588947Sdlw  *	when we try to use it.  This raises the SIGILL signal.
1598947Sdlw  */
1608947Sdlw 
1618947Sdlw /*ARGSUSED*/
1628947Sdlw got_overflow(signo, codeword, myaddr, pc, ps)
1638947Sdlw 	char *myaddr, *pc;
1648947Sdlw {
16510238Sdlw 	int	*sp, i;
16610238Sdlw 	FILE	*ef;
16710238Sdlw 
16810238Sdlw 	signal(SIGFPE, got_overflow);
16910238Sdlw 	ef = units[STDERR].ufd;
17010238Sdlw 	switch (codeword) {
17110238Sdlw 		case INT_OVF_T:
17210238Sdlw 		case INT_DIV_T:
17310238Sdlw 		case FLT_UND_T:
17410238Sdlw 		case DEC_OVF_T:
17510238Sdlw 		case SUB_RNG_T:
17610238Sdlw 		case FLT_OVF_F:
17710238Sdlw 		case FLT_DIV_F:
17810238Sdlw 		case FLT_UND_F:
179*39150Sbostic 			if (sigfpe_default > (SIG_VAL)7)
180*39150Sbostic 				(*sigfpe_default)(signo, codeword, myaddr,
181*39150Sbostic 				    pc, ps);
182*39150Sbostic 			else
183*39150Sbostic 				sigdie(signo, codeword, myaddr, pc, ps);
184*39150Sbostic 				/* NOTREACHED */
18510238Sdlw 
18610238Sdlw 		case FLT_OVF_T:
18710238Sdlw 		case FLT_DIV_T:
188*39150Sbostic 			if (++total_overflows <= max_messages) {
189*39150Sbostic 				fprintf(ef, "trapov: %s",
190*39150Sbostic 					act_fpe[codeword-1].mesg);
191*39150Sbostic 				if (total_overflows == max_messages)
192*39150Sbostic 					fprintf(ef, ": No more messages will be printed.\n");
193*39150Sbostic 				else
194*39150Sbostic 					fputc('\n', ef);
195*39150Sbostic 			}
196*39150Sbostic 			return;
1978947Sdlw 	}
1988947Sdlw }
1998947Sdlw 
2008947Sdlw int
2018947Sdlw ovcnt_()
2028947Sdlw {
2038947Sdlw 	return total_overflows;
2048947Sdlw }
2058947Sdlw 
2068947Sdlw /*
2078947Sdlw  *	got_illegal_instruction - handle "illegal instruction" signals.
2088947Sdlw  *
2098947Sdlw  *	This really deals only with reserved operand exceptions.
2108947Sdlw  *	Since there is no way to check this directly, we look at the
2118947Sdlw  *	opcode of the instruction we are executing to see if it is a
2128947Sdlw  *	floating-point operation (with floating-point operands, not
2138947Sdlw  *	just results).
2148947Sdlw  *
2158947Sdlw  *	This is complicated by the fact that the registers that will
2168947Sdlw  *	eventually be restored are saved in two places.  registers 7-11
2178947Sdlw  *	are saved by this routine, and are in its call frame. (we have
2188947Sdlw  *	to take special care that these registers are specified in
2198947Sdlw  *	the procedure entry mask here.)
2208947Sdlw  *	Registers 0-6 are saved at interrupt time, and are at a offset
2218947Sdlw  *	-8 from the 'signo' parameter below.
2228947Sdlw  *	There is ane extremely inimate connection between the value of
2238947Sdlw  *	the entry mask set by the 'makefile' script, and the constants
2248947Sdlw  *	used in the register offset calculations below.
2258947Sdlw  *	Can someone think of a better way to do this?
2268947Sdlw  */
2278947Sdlw 
2288947Sdlw /*ARGSUSED*/
2298947Sdlw got_illegal_instruction(signo, codeword, myaddr, trap_pc, ps)
2308947Sdlw 	char *myaddr, *trap_pc;
2318947Sdlw {
2328947Sdlw 	int first_local[1];		/* must be first */
2338947Sdlw 	int i, opcode, type, o_no, no_reserved;
2348947Sdlw 	anyval *opnd;
2358947Sdlw 
2368947Sdlw 	regs7t11 = &first_local[0];
2378947Sdlw 	regs0t6 = &signo - 8;
2388947Sdlw 	pc = trap_pc;
2398947Sdlw 
2408947Sdlw 	opcode = fetch_byte() & 0xff;
2418947Sdlw 	no_reserved = 0;
24210238Sdlw 	if (codeword != RES_OPR_F || !is_floating_operation(opcode)) {
24310238Sdlw 		if (sigill_default > (SIG_VAL)7)
24410238Sdlw 			return((*sigill_default)(signo, codeword, myaddr, trap_pc, ps));
24510238Sdlw 		else
24610238Sdlw 			sigdie(signo, codeword, myaddr, trap_pc, ps);
24710238Sdlw 			/* NOTREACHED */
2488947Sdlw 	}
2498947Sdlw 
2508947Sdlw 	if (opcode == POLYD || opcode == POLYF) {
2518947Sdlw 		got_illegal_poly(opcode);
2528947Sdlw 		return;
2538947Sdlw 	}
2548947Sdlw 
2558947Sdlw 	if (opcode == EMODD || opcode == EMODF) {
2568947Sdlw 		got_illegal_emod(opcode);
2578947Sdlw 		return;
2588947Sdlw 	}
2598947Sdlw 
2608947Sdlw 	/*
2618947Sdlw 	 * This opcode wasn't "unusual".
2628947Sdlw 	 * Look at the operands to try and find a reserved operand.
2638947Sdlw 	 */
2648947Sdlw 	for (o_no = 1; o_no <= no_operands(opcode); ++o_no) {
2658947Sdlw 		type = operand_type(opcode, o_no);
2668947Sdlw 		if (type != F && type != D) {
2678947Sdlw 			advance_pc(type);
2688947Sdlw 			continue;
2698947Sdlw 		}
2708947Sdlw 
2718947Sdlw 		/* F or D operand.  Check it out */
2728947Sdlw 		opnd = get_operand_address(type);
2738947Sdlw 		if (opnd == NULL) {
2748947Sdlw 			fprintf(units[STDERR].ufd, "Can't get operand address: 0x%x, %d\n",
2758947Sdlw 				pc, o_no);
27620186Slibs 			f77_abort();
2778947Sdlw 		}
2788947Sdlw 		if (type == F && opnd->o_long == 0x00008000) {
2798947Sdlw 			/* found one */
2808947Sdlw 			opnd->o_long = retrn.v_long[0];
2818947Sdlw 			++no_reserved;
2828947Sdlw 		} else if (type == D && opnd->o_long == 0x00008000) {
2838947Sdlw 			/* found one here, too! */
2848947Sdlw 			opnd->o_quad[0] = retrn.v_long[0];
2858947Sdlw 			/* Fix next pointer */
2868947Sdlw 			if (opnd == addr_of_reg(6)) opnd = addr_of_reg(7);
2878947Sdlw 			else opnd = (anyval *) ((char *) opnd + 4);
2888947Sdlw 			opnd->o_quad[0] = retrn.v_long[1];
2898947Sdlw 			++no_reserved;
2908947Sdlw 		}
2918947Sdlw 
2928947Sdlw 	}
2938947Sdlw 
2948947Sdlw 	if (no_reserved == 0) {
2958947Sdlw 		fprintf(units[STDERR].ufd, "Can't find any reserved operand!\n");
29620186Slibs 		f77_abort();
2978947Sdlw 	}
2988947Sdlw }
2998947Sdlw /*
3008947Sdlw  * is_floating_exception - was the operation code for a floating instruction?
3018947Sdlw  */
3028947Sdlw 
3038947Sdlw is_floating_operation(opcode)
3048947Sdlw 	int opcode;
3058947Sdlw {
3068947Sdlw 	switch (opcode) {
3078947Sdlw 		case ACBD:	case ACBF:	case ADDD2:	case ADDD3:
3088947Sdlw 		case ADDF2:	case ADDF3:	case CMPD:	case CMPF:
3098947Sdlw 		case CVTDB:	case CVTDF:	case CVTDL:	case CVTDW:
3108947Sdlw 		case CVTFB:	case CVTFD:	case CVTFL:	case CVTFW:
3118947Sdlw 		case CVTRDL:	case CVTRFL:	case DIVD2:	case DIVD3:
3128947Sdlw 		case DIVF2:	case DIVF3:	case EMODD:	case EMODF:
3138947Sdlw 		case MNEGD:	case MNEGF:	case MOVD:	case MOVF:
3148947Sdlw 		case MULD2:	case MULD3:	case MULF2:	case MULF3:
3158947Sdlw 		case POLYD:	case POLYF:	case SUBD2:	case SUBD3:
3168947Sdlw 		case SUBF2:	case SUBF3:	case TSTD:	case TSTF:
3178947Sdlw 			return 1;
3188947Sdlw 
3198947Sdlw 		default:
3208947Sdlw 			return 0;
3218947Sdlw 	}
3228947Sdlw }
3238947Sdlw /*
3248947Sdlw  * got_illegal_poly - handle an illegal POLY[DF] instruction.
3258947Sdlw  *
3268947Sdlw  * We don't do anything here yet.
3278947Sdlw  */
3288947Sdlw 
3298947Sdlw /*ARGSUSED*/
3308947Sdlw got_illegal_poly(opcode)
3318947Sdlw {
3328947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'poly' instructions yet\n");
33320186Slibs 	f77_abort();
3348947Sdlw }
3358947Sdlw 
3368947Sdlw 
3378947Sdlw 
3388947Sdlw /*
3398947Sdlw  * got_illegal_emod - handle illegal EMOD[DF] instruction.
3408947Sdlw  *
3418947Sdlw  * We don't do anything here yet.
3428947Sdlw  */
3438947Sdlw 
3448947Sdlw /*ARGSUSED*/
3458947Sdlw got_illegal_emod(opcode)
3468947Sdlw {
3478947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'emod' instructions yet\n");
34820186Slibs 	f77_abort();
3498947Sdlw }
3508947Sdlw 
3518947Sdlw 
3528947Sdlw /*
3538947Sdlw  *	no_operands - determine the number of operands in this instruction.
3548947Sdlw  *
3558947Sdlw  */
3568947Sdlw 
3578947Sdlw no_operands(opcode)
3588947Sdlw {
3598947Sdlw 	switch (opcode) {
3608947Sdlw 		case ACBD:
3618947Sdlw 		case ACBF:
3628947Sdlw 			return 3;
3638947Sdlw 
3648947Sdlw 		case MNEGD:
3658947Sdlw 		case MNEGF:
3668947Sdlw 		case MOVD:
3678947Sdlw 		case MOVF:
3688947Sdlw 		case TSTD:
3698947Sdlw 		case TSTF:
3708947Sdlw 			return 1;
3718947Sdlw 
3728947Sdlw 		default:
3738947Sdlw 			return 2;
3748947Sdlw 	}
3758947Sdlw }
3768947Sdlw 
3778947Sdlw 
3788947Sdlw 
3798947Sdlw /*
3808947Sdlw  *	operand_type - is the operand a D or an F?
3818947Sdlw  *
3828947Sdlw  *	We are only descriminating between Floats and Doubles here.
3838947Sdlw  *	Other operands may be possible on exotic instructions.
3848947Sdlw  */
3858947Sdlw 
3868947Sdlw /*ARGSUSED*/
3878947Sdlw operand_type(opcode, no)
3888947Sdlw {
3898947Sdlw 	if (opcode >= 0x40 && opcode <= 0x56) return F;
3908947Sdlw 	if (opcode >= 0x60 && opcode <= 0x76) return D;
3918947Sdlw 	return IDUNNO;
3928947Sdlw }
3938947Sdlw 
3948947Sdlw 
3958947Sdlw 
3968947Sdlw /*
3978947Sdlw  *	advance_pc - Advance the program counter past an operand.
3988947Sdlw  *
3998947Sdlw  *	We just bump the pc by the appropriate values.
4008947Sdlw  */
4018947Sdlw 
4028947Sdlw advance_pc(type)
4038947Sdlw {
4048947Sdlw 	register int mode, reg;
4058947Sdlw 
4068947Sdlw 	mode = fetch_byte();
4078947Sdlw 	reg = mode & 0xf;
4088947Sdlw 	mode = (mode >> 4) & 0xf;
4098947Sdlw 	switch (mode) {
4108947Sdlw 		case LITERAL0:
4118947Sdlw 		case LITERAL1:
4128947Sdlw 		case LITERAL2:
4138947Sdlw 		case LITERAL3:
4148947Sdlw 			return;
4158947Sdlw 
4168947Sdlw 		case INDEXED:
4178947Sdlw 			advance_pc(type);
4188947Sdlw 			return;
4198947Sdlw 
4208947Sdlw 		case REGISTER:
4218947Sdlw 		case REG_DEF:
4228947Sdlw 		case AUTO_DEC:
4238947Sdlw 			return;
4248947Sdlw 
4258947Sdlw 		case AUTO_INC:
4268947Sdlw 			if (reg == PC) {
4278947Sdlw 				if (type == F) (void) fetch_long();
4288947Sdlw 				else if (type == D) {
4298947Sdlw 					(void) fetch_long();
4308947Sdlw 					(void) fetch_long();
4318947Sdlw 				} else {
4328947Sdlw 					fprintf(units[STDERR].ufd, "Bad type %d in advance\n",
4338947Sdlw 						type);
43420186Slibs 					f77_abort();
4358947Sdlw 				}
4368947Sdlw 			}
4378947Sdlw 			return;
4388947Sdlw 
4398947Sdlw 		case AUTO_INC_DEF:
4408947Sdlw 			if (reg == PC) (void) fetch_long();
4418947Sdlw 			return;
4428947Sdlw 
4438947Sdlw 		case BYTE_DISP:
4448947Sdlw 		case BYTE_DISP_DEF:
4458947Sdlw 			(void) fetch_byte();
4468947Sdlw 			return;
4478947Sdlw 
4488947Sdlw 		case WORD_DISP:
4498947Sdlw 		case WORD_DISP_DEF:
4508947Sdlw 			(void) fetch_word();
4518947Sdlw 			return;
4528947Sdlw 
4538947Sdlw 		case LONG_DISP:
4548947Sdlw 		case LONG_DISP_DEF:
4558947Sdlw 			(void) fetch_long();
4568947Sdlw 			return;
4578947Sdlw 
4588947Sdlw 		default:
4598947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in op_length()\n", mode);
46020186Slibs 			f77_abort();
4618947Sdlw 	}
4628947Sdlw }
4638947Sdlw 
4648947Sdlw 
4658947Sdlw anyval *
4668947Sdlw get_operand_address(type)
4678947Sdlw {
4688947Sdlw 	register int mode, reg, base;
4698947Sdlw 
4708947Sdlw 	mode = fetch_byte() & 0xff;
4718947Sdlw 	reg = mode & 0xf;
4728947Sdlw 	mode = (mode >> 4) & 0xf;
4738947Sdlw 	switch (mode) {
4748947Sdlw 		case LITERAL0:
4758947Sdlw 		case LITERAL1:
4768947Sdlw 		case LITERAL2:
4778947Sdlw 		case LITERAL3:
4788947Sdlw 			return NULL;
4798947Sdlw 
4808947Sdlw 		case INDEXED:
4818947Sdlw 			base = (int) get_operand_address(type);
4828947Sdlw 			if (base == NULL) return NULL;
4838947Sdlw 			base += contents_of_reg(reg)*type_length(type);
4848947Sdlw 			return (anyval *) base;
4858947Sdlw 
4868947Sdlw 		case REGISTER:
4878947Sdlw 			return addr_of_reg(reg);
4888947Sdlw 
4898947Sdlw 		case REG_DEF:
4908947Sdlw 			return (anyval *) contents_of_reg(reg);
4918947Sdlw 
4928947Sdlw 		case AUTO_DEC:
4938947Sdlw 			return (anyval *) (contents_of_reg(reg)
4948947Sdlw 				- type_length(type));
4958947Sdlw 
4968947Sdlw 		case AUTO_INC:
4978947Sdlw 			return (anyval *) contents_of_reg(reg);
4988947Sdlw 
4998947Sdlw 		case AUTO_INC_DEF:
5008947Sdlw 			return (anyval *) * (long *) contents_of_reg(reg);
5018947Sdlw 
5028947Sdlw 		case BYTE_DISP:
5038947Sdlw 			base = fetch_byte();
5048947Sdlw 			base += contents_of_reg(reg);
5058947Sdlw 			return (anyval *) base;
5068947Sdlw 
5078947Sdlw 		case BYTE_DISP_DEF:
5088947Sdlw 			base = fetch_byte();
5098947Sdlw 			base += contents_of_reg(reg);
5108947Sdlw 			return (anyval *) * (long *) base;
5118947Sdlw 
5128947Sdlw 		case WORD_DISP:
5138947Sdlw 			base = fetch_word();
5148947Sdlw 			base += contents_of_reg(reg);
5158947Sdlw 			return (anyval *) base;
5168947Sdlw 
5178947Sdlw 		case WORD_DISP_DEF:
5188947Sdlw 			base = fetch_word();
5198947Sdlw 			base += contents_of_reg(reg);
5208947Sdlw 			return (anyval *) * (long *) base;
5218947Sdlw 
5228947Sdlw 		case LONG_DISP:
5238947Sdlw 			base = fetch_long();
5248947Sdlw 			base += contents_of_reg(reg);
5258947Sdlw 			return (anyval *) base;
5268947Sdlw 
5278947Sdlw 		case LONG_DISP_DEF:
5288947Sdlw 			base = fetch_long();
5298947Sdlw 			base += contents_of_reg(reg);
5308947Sdlw 			return (anyval *) * (long *) base;
5318947Sdlw 
5328947Sdlw 		default:
5338947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in get_addr()\n", mode);
53420186Slibs 			f77_abort();
5358947Sdlw 	}
5368947Sdlw 	return NULL;
5378947Sdlw }
5388947Sdlw 
5398947Sdlw 
5408947Sdlw 
5418947Sdlw contents_of_reg(reg)
5428947Sdlw {
5438947Sdlw 	int value;
5448947Sdlw 
5458947Sdlw 	if (reg == PC) value = (int) pc;
5468947Sdlw 	else if (reg == SP) value = (int) &regs0t6[6];
5478947Sdlw 	else if (reg == FP) value = regs0t6[-2];
5488947Sdlw 	else if (reg == AP) value = regs0t6[-3];
5498947Sdlw 	else if (reg >= 0 && reg <= 6) value = regs0t6[reg];
5508947Sdlw 	else if (reg >= 7 && reg <= 11) value = regs7t11[reg];
5518947Sdlw 	else {
5528947Sdlw 		fprintf(units[STDERR].ufd, "Bad register 0x%x to contents_of()\n", reg);
55320186Slibs 		f77_abort();
5548947Sdlw 		value = -1;
5558947Sdlw 	}
5568947Sdlw 	return value;
5578947Sdlw }
5588947Sdlw 
5598947Sdlw 
5608947Sdlw anyval *
5618947Sdlw addr_of_reg(reg)
5628947Sdlw {
5638947Sdlw 	if (reg >= 0 && reg <= 6) {
5648947Sdlw 		return (anyval *) &regs0t6[reg];
5658947Sdlw 	}
5668947Sdlw 	if (reg >= 7 && reg <= 11) {
5678947Sdlw 		return (anyval *) &regs7t11[reg];
5688947Sdlw 	}
5698947Sdlw 	fprintf(units[STDERR].ufd, "Bad reg 0x%x to addr_of()\n", reg);
57020186Slibs 	f77_abort();
5718947Sdlw 	return NULL;
5728947Sdlw }
5738947Sdlw /*
5748947Sdlw  *	fetch_{byte, word, long} - extract values from the PROGRAM area.
5758947Sdlw  *
5768947Sdlw  *	These routines are used in the operand decoding to extract various
5778947Sdlw  *	fields from where the program counter points.  This is because the
5788947Sdlw  *	addressing on the Vax is dynamic: the program counter advances
5798947Sdlw  *	while we are grabbing operands, as well as when we pass instructions.
5808947Sdlw  *	This makes things a bit messy, but I can't help it.
5818947Sdlw  */
5828947Sdlw fetch_byte()
5838947Sdlw {
5848947Sdlw 	return *pc++;
5858947Sdlw }
5868947Sdlw 
5878947Sdlw 
5888947Sdlw 
5898947Sdlw fetch_word()
5908947Sdlw {
5918947Sdlw 	int *old_pc;
5928947Sdlw 
5938947Sdlw 	old_pc = (int *) pc;
5948947Sdlw 	pc += 2;
5958947Sdlw 	return *old_pc;
5968947Sdlw }
5978947Sdlw 
5988947Sdlw 
5998947Sdlw 
6008947Sdlw fetch_long()
6018947Sdlw {
6028947Sdlw 	long *old_pc;
6038947Sdlw 
6048947Sdlw 	old_pc = (long *) pc;
6058947Sdlw 	pc += 4;
6068947Sdlw 	return *old_pc;
6078947Sdlw }
60820186Slibs 
6098947Sdlw 
6108947Sdlw type_length(type)
6118947Sdlw {
6128947Sdlw 	if (type == F) return 4;
6138947Sdlw 	if (type == D) return 8;
6148947Sdlw 	fprintf(units[STDERR].ufd, "Bad type 0x%x in type_length()\n", type);
61520186Slibs 	f77_abort();
6168947Sdlw 	return -1;
6178947Sdlw }
6188947Sdlw 
6198947Sdlw 
6208947Sdlw 
6218947Sdlw char *opcode_name(opcode)
6228947Sdlw {
6238947Sdlw 	switch (opcode) {
6248947Sdlw 		case ACBD: 	return "ACBD";
6258947Sdlw 		case ACBF: 	return "ACBF";
6268947Sdlw 		case ADDD2: 	return "ADDD2";
6278947Sdlw 		case ADDD3: 	return "ADDD3";
6288947Sdlw 		case ADDF2: 	return "ADDF2";
6298947Sdlw 		case ADDF3: 	return "ADDF3";
6308947Sdlw 		case CMPD: 	return "CMPD";
6318947Sdlw 		case CMPF: 	return "CMPF";
6328947Sdlw 		case CVTDB: 	return "CVTDB";
6338947Sdlw 		case CVTDF: 	return "CVTDF";
6348947Sdlw 		case CVTDL: 	return "CVTDL";
6358947Sdlw 		case CVTDW: 	return "CVTDW";
6368947Sdlw 		case CVTFB: 	return "CVTFB";
6378947Sdlw 		case CVTFD: 	return "CVTFD";
6388947Sdlw 		case CVTFL: 	return "CVTFL";
6398947Sdlw 		case CVTFW: 	return "CVTFW";
6408947Sdlw 		case CVTRDL: 	return "CVTRDL";
6418947Sdlw 		case CVTRFL: 	return "CVTRFL";
6428947Sdlw 		case DIVD2: 	return "DIVD2";
6438947Sdlw 		case DIVD3: 	return "DIVD3";
6448947Sdlw 		case DIVF2: 	return "DIVF2";
6458947Sdlw 		case DIVF3: 	return "DIVF3";
6468947Sdlw 		case EMODD: 	return "EMODD";
6478947Sdlw 		case EMODF: 	return "EMODF";
6488947Sdlw 		case MNEGD: 	return "MNEGD";
6498947Sdlw 		case MNEGF: 	return "MNEGF";
6508947Sdlw 		case MOVD: 	return "MOVD";
6518947Sdlw 		case MOVF: 	return "MOVF";
6528947Sdlw 		case MULD2: 	return "MULD2";
6538947Sdlw 		case MULD3: 	return "MULD3";
6548947Sdlw 		case MULF2: 	return "MULF2";
6558947Sdlw 		case MULF3: 	return "MULF3";
6568947Sdlw 		case POLYD: 	return "POLYD";
6578947Sdlw 		case POLYF: 	return "POLYF";
6588947Sdlw 		case SUBD2: 	return "SUBD2";
6598947Sdlw 		case SUBD3: 	return "SUBD3";
6608947Sdlw 		case SUBF2: 	return "SUBF2";
6618947Sdlw 		case SUBF3: 	return "SUBF3";
6628947Sdlw 		case TSTD: 	return "TSTD";
6638947Sdlw 		case TSTF: 	return "TSTF";
6648947Sdlw 	}
6658947Sdlw }
6668947Sdlw #endif	vax
66729960Smckusick 
66829960Smckusick #ifdef tahoe
66929960Smckusick /*
67029960Smckusick  *	NO RESERVED OPERAND EXCEPTION ON RESULT OF FP OVERFLOW ON TAHOE.
67129960Smckusick  * 	JUST PRINT THE OVERFLOW MESSAGE. RESULT IS 0 (zero).
67229960Smckusick  */
67329960Smckusick 
67429960Smckusick /*
67529960Smckusick  *	GLOBAL VARIABLES (we need a few)
67629960Smckusick  *
67729960Smckusick  *	Actual program counter and locations of registers.
67829960Smckusick  */
67929960Smckusick static char	*pc;
68029960Smckusick static int	*regs0t1;
68129960Smckusick static int	*regs2t12;
68229960Smckusick static int	max_messages;
68329960Smckusick static int	total_overflows;
68429960Smckusick static union	{
68529960Smckusick 	long	v_long[2];
68629960Smckusick 	double	v_double;
68729960Smckusick 	} retrn;
688*39150Sbostic static sig_t sigill_default = (SIG_VAL)-1;
689*39150Sbostic static sig_t sigfpe_default;
69029960Smckusick 
69129960Smckusick 
69229960Smckusick /*
69329960Smckusick  *	This routine sets up the signal handler for the floating-point
69429960Smckusick  *	and reserved operand interrupts.
69529960Smckusick  */
69629960Smckusick 
69729960Smckusick trapov_(count, rtnval)
69829960Smckusick 	int *count;
69929960Smckusick 	double *rtnval;
70029960Smckusick {
701*39150Sbostic 	void got_overflow();
70229960Smckusick 
70329960Smckusick 	sigfpe_default = signal(SIGFPE, got_overflow);
70429960Smckusick 	total_overflows = 0;
70529960Smckusick 	max_messages = *count;
70629960Smckusick 	retrn.v_double = *rtnval;
70729960Smckusick }
70829960Smckusick 
70929960Smckusick 
71029960Smckusick 
71129960Smckusick /*
71229960Smckusick  *	got_overflow - routine called when overflow occurs
71329960Smckusick  *
71429960Smckusick  *	This routine just prints a message about the overflow.
71529960Smckusick  *	It is impossible to find the bad result at this point.
71629960Smckusick  * 	 NEXT 2 LINES DON'T HOLD FOR TAHOE !
71729960Smckusick  *	Instead, we wait until we get the reserved operand exception
71829960Smckusick  *	when we try to use it.  This raises the SIGILL signal.
71929960Smckusick  */
72029960Smckusick 
72129960Smckusick /*ARGSUSED*/
722*39150Sbostic void
72329960Smckusick got_overflow(signo, codeword, sc)
72429960Smckusick 	int signo, codeword;
72529960Smckusick 	struct sigcontext *sc;
72629960Smckusick {
72729960Smckusick 	int	*sp, i;
72829960Smckusick 	FILE	*ef;
72929960Smckusick 
73029960Smckusick 	signal(SIGFPE, got_overflow);
73129960Smckusick 	ef = units[STDERR].ufd;
73229960Smckusick 	switch (codeword) {
73329960Smckusick 		case INT_OVF_T:
73429960Smckusick 		case INT_DIV_T:
73529960Smckusick 		case FLT_UND_T:
73629960Smckusick 		case FLT_DIV_T:
737*39150Sbostic 			if (sigfpe_default > (SIG_VAL)7)
738*39150Sbostic 				(*sigfpe_default)(signo, codeword, sc);
739*39150Sbostic 			else
740*39150Sbostic 				sigdie(signo, codeword, sc);
741*39150Sbostic 				/* NOTREACHED */
74229960Smckusick 
74329960Smckusick 		case FLT_OVF_T:
744*39150Sbostic 			if (++total_overflows <= max_messages) {
745*39150Sbostic 				fprintf(ef, "trapov: %s",
746*39150Sbostic 					act_fpe[codeword-1].mesg);
747*39150Sbostic 				fprintf(ef, ": Current PC = %X", sc->sc_pc);
748*39150Sbostic 				if (total_overflows == max_messages)
749*39150Sbostic 					fprintf(ef, ": No more messages will be printed.\n");
750*39150Sbostic 				else
751*39150Sbostic 					fputc('\n', ef);
752*39150Sbostic 			}
753*39150Sbostic 			return;
75429960Smckusick 	}
75529960Smckusick }
75629960Smckusick int
75729960Smckusick ovcnt_()
75829960Smckusick {
75929960Smckusick 	return total_overflows;
76029960Smckusick }
76129960Smckusick #endif tahoe
762