xref: /csrg-svn/usr.bin/f77/libF77/trapov_.c (revision 47940)
1*47940Sbostic /*-
2*47940Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47940Sbostic  * All rights reserved.
4*47940Sbostic  *
5*47940Sbostic  * %sccs.include.proprietary.c%
6*47940Sbostic  */
7*47940Sbostic 
8*47940Sbostic #ifndef lint
9*47940Sbostic static char sccsid[] = "@(#)trapov_.c	5.6 (Berkeley) 04/12/91";
10*47940Sbostic #endif /* not lint */
11*47940Sbostic 
128947Sdlw /*
138947Sdlw  *	Fortran/C floating-point overflow handler
148947Sdlw  *
158947Sdlw  *	The idea of these routines is to catch floating-point overflows
168947Sdlw  *	and print an eror message.  When we then get a reserved operand
178947Sdlw  *	exception, we then fix up the value to the highest possible
188947Sdlw  *	number.  Keen, no?
198947Sdlw  *	Messy, yes!
208947Sdlw  *
218947Sdlw  *	Synopsis:
228947Sdlw  *		call trapov(n)
238947Sdlw  *			causes overflows to be trapped, with the first 'n'
248947Sdlw  *			overflows getting an "Overflow!" message printed.
258947Sdlw  *		k = ovcnt(0)
268947Sdlw  *			causes 'k' to get the number of overflows since the
278947Sdlw  *			last call to trapov().
288947Sdlw  *
298947Sdlw  *	Gary Klimowicz, April 17, 1981
308947Sdlw  *	Integerated with libF77: David Wasley, UCB, July 1981.
318947Sdlw  */
328947Sdlw 
338947Sdlw # include <stdio.h>
3439150Sbostic # include <sys/signal.h>
358947Sdlw # include "opcodes.h"
368947Sdlw # include "../libI77/fiodefs.h"
3739150Sbostic # define SIG_VAL	void (*)()
388947Sdlw 
398947Sdlw /*
4029960Smckusick  *	Potential operand values
4129960Smckusick  */
4229960Smckusick typedef	union operand_types {
4329960Smckusick 		char	o_byte;
4429960Smckusick 		short	o_word;
4529960Smckusick 		long	o_long;
4629960Smckusick 		float	o_float;
4729960Smckusick 		long	o_quad[2];
4829960Smckusick 		double	o_double;
4929960Smckusick 	} anyval;
5029960Smckusick 
5129960Smckusick /*
5229960Smckusick  *	the fortran unit control table
5329960Smckusick  */
5429960Smckusick extern unit units[];
5529960Smckusick 
5629960Smckusick /*
5729960Smckusick  * Fortran message table is in main
5829960Smckusick  */
5929960Smckusick struct msgtbl {
6029960Smckusick 	char	*mesg;
6129960Smckusick 	int	dummy;
6229960Smckusick };
6329960Smckusick extern struct msgtbl	act_fpe[];
6429960Smckusick 
6529960Smckusick anyval *get_operand_address(), *addr_of_reg();
6629960Smckusick char *opcode_name();
6729960Smckusick 
6829960Smckusick /*
6929960Smckusick  * trap type codes
7029960Smckusick  */
7129960Smckusick # define INT_OVF_T	1
7229960Smckusick # define INT_DIV_T	2
7329960Smckusick # define FLT_OVF_T	3
7429960Smckusick # define FLT_DIV_T	4
7529960Smckusick # define FLT_UND_T	5
7629960Smckusick # define DEC_OVF_T	6
7729960Smckusick # define SUB_RNG_T	7
7829960Smckusick # define FLT_OVF_F	8
7929960Smckusick # define FLT_DIV_F	9
8029960Smckusick # define FLT_UND_F	10
8129960Smckusick 
8229960Smckusick # define RES_ADR_F	0
8329960Smckusick # define RES_OPC_F	1
8429960Smckusick # define RES_OPR_F	2
8529960Smckusick 
8629960Smckusick #ifdef vax
8729960Smckusick /*
888947Sdlw  *	Operand modes
898947Sdlw  */
908947Sdlw # define LITERAL0	0x0
918947Sdlw # define LITERAL1	0x1
928947Sdlw # define LITERAL2	0x2
938947Sdlw # define LITERAL3	0x3
948947Sdlw # define INDEXED	0x4
958947Sdlw # define REGISTER	0x5
968947Sdlw # define REG_DEF	0x6
978947Sdlw # define AUTO_DEC	0x7
988947Sdlw # define AUTO_INC	0x8
998947Sdlw # define AUTO_INC_DEF	0x9
1008947Sdlw # define BYTE_DISP	0xa
1018947Sdlw # define BYTE_DISP_DEF	0xb
1028947Sdlw # define WORD_DISP	0xc
1038947Sdlw # define WORD_DISP_DEF	0xd
1048947Sdlw # define LONG_DISP	0xe
1058947Sdlw # define LONG_DISP_DEF	0xf
1068947Sdlw 
1078947Sdlw /*
1088947Sdlw  *	Operand value types
1098947Sdlw  */
1108947Sdlw # define F		1
1118947Sdlw # define D		2
1128947Sdlw # define IDUNNO		3
1138947Sdlw 
1148947Sdlw # define PC	0xf
1158947Sdlw # define SP	0xe
1168947Sdlw # define FP	0xd
1178947Sdlw # define AP	0xc
1188947Sdlw 
1198947Sdlw /*
1208947Sdlw  *	GLOBAL VARIABLES (we need a few)
1218947Sdlw  *
1228947Sdlw  *	Actual program counter and locations of registers.
1238947Sdlw  */
1248947Sdlw static char	*pc;
1258947Sdlw static int	*regs0t6;
1268947Sdlw static int	*regs7t11;
1278947Sdlw static int	max_messages;
1288947Sdlw static int	total_overflows;
1298947Sdlw static union	{
1308947Sdlw 	long	v_long[2];
1318947Sdlw 	double	v_double;
1328947Sdlw 	} retrn;
13339150Sbostic static sig_t sigill_default = (SIG_VAL)-1;
13439150Sbostic static sig_t sigfpe_default;
1358947Sdlw 
1368947Sdlw /*
1378947Sdlw  *	This routine sets up the signal handler for the floating-point
1388947Sdlw  *	and reserved operand interrupts.
1398947Sdlw  */
1408947Sdlw 
trapov_(count,rtnval)1418947Sdlw trapov_(count, rtnval)
1428947Sdlw 	int *count;
1438947Sdlw 	double *rtnval;
1448947Sdlw {
14539150Sbostic 	void got_overflow(), got_illegal_instruction();
1468947Sdlw 
14710238Sdlw 	sigfpe_default = signal(SIGFPE, got_overflow);
14810238Sdlw 	if (sigill_default == (SIG_VAL)-1)
14910238Sdlw 		sigill_default = signal(SIGILL, got_illegal_instruction);
1508947Sdlw 	total_overflows = 0;
1518947Sdlw 	max_messages = *count;
1528947Sdlw 	retrn.v_double = *rtnval;
1538947Sdlw }
1548947Sdlw 
1558947Sdlw 
1568947Sdlw 
1578947Sdlw /*
1588947Sdlw  *	got_overflow - routine called when overflow occurs
1598947Sdlw  *
1608947Sdlw  *	This routine just prints a message about the overflow.
1618947Sdlw  *	It is impossible to find the bad result at this point.
1628947Sdlw  *	Instead, we wait until we get the reserved operand exception
1638947Sdlw  *	when we try to use it.  This raises the SIGILL signal.
1648947Sdlw  */
1658947Sdlw 
1668947Sdlw /*ARGSUSED*/
16740065Stef void
got_overflow(signo,codeword,myaddr,pc,ps)1688947Sdlw got_overflow(signo, codeword, myaddr, pc, ps)
1698947Sdlw 	char *myaddr, *pc;
1708947Sdlw {
17110238Sdlw 	int	*sp, i;
17210238Sdlw 	FILE	*ef;
17310238Sdlw 
17410238Sdlw 	signal(SIGFPE, got_overflow);
17510238Sdlw 	ef = units[STDERR].ufd;
17610238Sdlw 	switch (codeword) {
17710238Sdlw 		case INT_OVF_T:
17810238Sdlw 		case INT_DIV_T:
17910238Sdlw 		case FLT_UND_T:
18010238Sdlw 		case DEC_OVF_T:
18110238Sdlw 		case SUB_RNG_T:
18210238Sdlw 		case FLT_OVF_F:
18310238Sdlw 		case FLT_DIV_F:
18410238Sdlw 		case FLT_UND_F:
18539150Sbostic 			if (sigfpe_default > (SIG_VAL)7)
18639150Sbostic 				(*sigfpe_default)(signo, codeword, myaddr,
18739150Sbostic 				    pc, ps);
18839150Sbostic 			else
18939150Sbostic 				sigdie(signo, codeword, myaddr, pc, ps);
19039150Sbostic 				/* NOTREACHED */
19110238Sdlw 
19210238Sdlw 		case FLT_OVF_T:
19310238Sdlw 		case FLT_DIV_T:
19439150Sbostic 			if (++total_overflows <= max_messages) {
19539150Sbostic 				fprintf(ef, "trapov: %s",
19639150Sbostic 					act_fpe[codeword-1].mesg);
19739150Sbostic 				if (total_overflows == max_messages)
19839150Sbostic 					fprintf(ef, ": No more messages will be printed.\n");
19939150Sbostic 				else
20039150Sbostic 					fputc('\n', ef);
20139150Sbostic 			}
20239150Sbostic 			return;
2038947Sdlw 	}
2048947Sdlw }
2058947Sdlw 
2068947Sdlw int
ovcnt_()2078947Sdlw ovcnt_()
2088947Sdlw {
2098947Sdlw 	return total_overflows;
2108947Sdlw }
2118947Sdlw 
2128947Sdlw /*
2138947Sdlw  *	got_illegal_instruction - handle "illegal instruction" signals.
2148947Sdlw  *
2158947Sdlw  *	This really deals only with reserved operand exceptions.
2168947Sdlw  *	Since there is no way to check this directly, we look at the
2178947Sdlw  *	opcode of the instruction we are executing to see if it is a
2188947Sdlw  *	floating-point operation (with floating-point operands, not
2198947Sdlw  *	just results).
2208947Sdlw  *
2218947Sdlw  *	This is complicated by the fact that the registers that will
2228947Sdlw  *	eventually be restored are saved in two places.  registers 7-11
2238947Sdlw  *	are saved by this routine, and are in its call frame. (we have
2248947Sdlw  *	to take special care that these registers are specified in
2258947Sdlw  *	the procedure entry mask here.)
2268947Sdlw  *	Registers 0-6 are saved at interrupt time, and are at a offset
2278947Sdlw  *	-8 from the 'signo' parameter below.
2288947Sdlw  *	There is ane extremely inimate connection between the value of
2298947Sdlw  *	the entry mask set by the 'makefile' script, and the constants
2308947Sdlw  *	used in the register offset calculations below.
2318947Sdlw  *	Can someone think of a better way to do this?
2328947Sdlw  */
2338947Sdlw 
2348947Sdlw /*ARGSUSED*/
23540065Stef void
got_illegal_instruction(signo,codeword,myaddr,trap_pc,ps)2368947Sdlw got_illegal_instruction(signo, codeword, myaddr, trap_pc, ps)
2378947Sdlw 	char *myaddr, *trap_pc;
2388947Sdlw {
2398947Sdlw 	int first_local[1];		/* must be first */
2408947Sdlw 	int i, opcode, type, o_no, no_reserved;
2418947Sdlw 	anyval *opnd;
2428947Sdlw 
2438947Sdlw 	regs7t11 = &first_local[0];
2448947Sdlw 	regs0t6 = &signo - 8;
2458947Sdlw 	pc = trap_pc;
2468947Sdlw 
2478947Sdlw 	opcode = fetch_byte() & 0xff;
2488947Sdlw 	no_reserved = 0;
24910238Sdlw 	if (codeword != RES_OPR_F || !is_floating_operation(opcode)) {
25040065Stef 		if (sigill_default > (SIG_VAL)7) {
25140065Stef 			(*sigill_default)(signo, codeword, myaddr, trap_pc, ps);
25240065Stef 			return;
25340065Stef 		} else
25410238Sdlw 			sigdie(signo, codeword, myaddr, trap_pc, ps);
25510238Sdlw 			/* NOTREACHED */
2568947Sdlw 	}
2578947Sdlw 
2588947Sdlw 	if (opcode == POLYD || opcode == POLYF) {
2598947Sdlw 		got_illegal_poly(opcode);
2608947Sdlw 		return;
2618947Sdlw 	}
2628947Sdlw 
2638947Sdlw 	if (opcode == EMODD || opcode == EMODF) {
2648947Sdlw 		got_illegal_emod(opcode);
2658947Sdlw 		return;
2668947Sdlw 	}
2678947Sdlw 
2688947Sdlw 	/*
2698947Sdlw 	 * This opcode wasn't "unusual".
2708947Sdlw 	 * Look at the operands to try and find a reserved operand.
2718947Sdlw 	 */
2728947Sdlw 	for (o_no = 1; o_no <= no_operands(opcode); ++o_no) {
2738947Sdlw 		type = operand_type(opcode, o_no);
2748947Sdlw 		if (type != F && type != D) {
2758947Sdlw 			advance_pc(type);
2768947Sdlw 			continue;
2778947Sdlw 		}
2788947Sdlw 
2798947Sdlw 		/* F or D operand.  Check it out */
2808947Sdlw 		opnd = get_operand_address(type);
2818947Sdlw 		if (opnd == NULL) {
2828947Sdlw 			fprintf(units[STDERR].ufd, "Can't get operand address: 0x%x, %d\n",
2838947Sdlw 				pc, o_no);
28420186Slibs 			f77_abort();
2858947Sdlw 		}
2868947Sdlw 		if (type == F && opnd->o_long == 0x00008000) {
2878947Sdlw 			/* found one */
2888947Sdlw 			opnd->o_long = retrn.v_long[0];
2898947Sdlw 			++no_reserved;
2908947Sdlw 		} else if (type == D && opnd->o_long == 0x00008000) {
2918947Sdlw 			/* found one here, too! */
2928947Sdlw 			opnd->o_quad[0] = retrn.v_long[0];
2938947Sdlw 			/* Fix next pointer */
2948947Sdlw 			if (opnd == addr_of_reg(6)) opnd = addr_of_reg(7);
2958947Sdlw 			else opnd = (anyval *) ((char *) opnd + 4);
2968947Sdlw 			opnd->o_quad[0] = retrn.v_long[1];
2978947Sdlw 			++no_reserved;
2988947Sdlw 		}
2998947Sdlw 
3008947Sdlw 	}
3018947Sdlw 
3028947Sdlw 	if (no_reserved == 0) {
3038947Sdlw 		fprintf(units[STDERR].ufd, "Can't find any reserved operand!\n");
30420186Slibs 		f77_abort();
3058947Sdlw 	}
3068947Sdlw }
3078947Sdlw /*
3088947Sdlw  * is_floating_exception - was the operation code for a floating instruction?
3098947Sdlw  */
3108947Sdlw 
is_floating_operation(opcode)3118947Sdlw is_floating_operation(opcode)
3128947Sdlw 	int opcode;
3138947Sdlw {
3148947Sdlw 	switch (opcode) {
3158947Sdlw 		case ACBD:	case ACBF:	case ADDD2:	case ADDD3:
3168947Sdlw 		case ADDF2:	case ADDF3:	case CMPD:	case CMPF:
3178947Sdlw 		case CVTDB:	case CVTDF:	case CVTDL:	case CVTDW:
3188947Sdlw 		case CVTFB:	case CVTFD:	case CVTFL:	case CVTFW:
3198947Sdlw 		case CVTRDL:	case CVTRFL:	case DIVD2:	case DIVD3:
3208947Sdlw 		case DIVF2:	case DIVF3:	case EMODD:	case EMODF:
3218947Sdlw 		case MNEGD:	case MNEGF:	case MOVD:	case MOVF:
3228947Sdlw 		case MULD2:	case MULD3:	case MULF2:	case MULF3:
3238947Sdlw 		case POLYD:	case POLYF:	case SUBD2:	case SUBD3:
3248947Sdlw 		case SUBF2:	case SUBF3:	case TSTD:	case TSTF:
3258947Sdlw 			return 1;
3268947Sdlw 
3278947Sdlw 		default:
3288947Sdlw 			return 0;
3298947Sdlw 	}
3308947Sdlw }
3318947Sdlw /*
3328947Sdlw  * got_illegal_poly - handle an illegal POLY[DF] instruction.
3338947Sdlw  *
3348947Sdlw  * We don't do anything here yet.
3358947Sdlw  */
3368947Sdlw 
3378947Sdlw /*ARGSUSED*/
got_illegal_poly(opcode)3388947Sdlw got_illegal_poly(opcode)
3398947Sdlw {
3408947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'poly' instructions yet\n");
34120186Slibs 	f77_abort();
3428947Sdlw }
3438947Sdlw 
3448947Sdlw 
3458947Sdlw 
3468947Sdlw /*
3478947Sdlw  * got_illegal_emod - handle illegal EMOD[DF] instruction.
3488947Sdlw  *
3498947Sdlw  * We don't do anything here yet.
3508947Sdlw  */
3518947Sdlw 
3528947Sdlw /*ARGSUSED*/
got_illegal_emod(opcode)3538947Sdlw got_illegal_emod(opcode)
3548947Sdlw {
3558947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'emod' instructions yet\n");
35620186Slibs 	f77_abort();
3578947Sdlw }
3588947Sdlw 
3598947Sdlw 
3608947Sdlw /*
3618947Sdlw  *	no_operands - determine the number of operands in this instruction.
3628947Sdlw  *
3638947Sdlw  */
3648947Sdlw 
no_operands(opcode)3658947Sdlw no_operands(opcode)
3668947Sdlw {
3678947Sdlw 	switch (opcode) {
3688947Sdlw 		case ACBD:
3698947Sdlw 		case ACBF:
3708947Sdlw 			return 3;
3718947Sdlw 
3728947Sdlw 		case MNEGD:
3738947Sdlw 		case MNEGF:
3748947Sdlw 		case MOVD:
3758947Sdlw 		case MOVF:
3768947Sdlw 		case TSTD:
3778947Sdlw 		case TSTF:
3788947Sdlw 			return 1;
3798947Sdlw 
3808947Sdlw 		default:
3818947Sdlw 			return 2;
3828947Sdlw 	}
3838947Sdlw }
3848947Sdlw 
3858947Sdlw 
3868947Sdlw 
3878947Sdlw /*
3888947Sdlw  *	operand_type - is the operand a D or an F?
3898947Sdlw  *
3908947Sdlw  *	We are only descriminating between Floats and Doubles here.
3918947Sdlw  *	Other operands may be possible on exotic instructions.
3928947Sdlw  */
3938947Sdlw 
3948947Sdlw /*ARGSUSED*/
operand_type(opcode,no)3958947Sdlw operand_type(opcode, no)
3968947Sdlw {
3978947Sdlw 	if (opcode >= 0x40 && opcode <= 0x56) return F;
3988947Sdlw 	if (opcode >= 0x60 && opcode <= 0x76) return D;
3998947Sdlw 	return IDUNNO;
4008947Sdlw }
4018947Sdlw 
4028947Sdlw 
4038947Sdlw 
4048947Sdlw /*
4058947Sdlw  *	advance_pc - Advance the program counter past an operand.
4068947Sdlw  *
4078947Sdlw  *	We just bump the pc by the appropriate values.
4088947Sdlw  */
4098947Sdlw 
advance_pc(type)4108947Sdlw advance_pc(type)
4118947Sdlw {
4128947Sdlw 	register int mode, reg;
4138947Sdlw 
4148947Sdlw 	mode = fetch_byte();
4158947Sdlw 	reg = mode & 0xf;
4168947Sdlw 	mode = (mode >> 4) & 0xf;
4178947Sdlw 	switch (mode) {
4188947Sdlw 		case LITERAL0:
4198947Sdlw 		case LITERAL1:
4208947Sdlw 		case LITERAL2:
4218947Sdlw 		case LITERAL3:
4228947Sdlw 			return;
4238947Sdlw 
4248947Sdlw 		case INDEXED:
4258947Sdlw 			advance_pc(type);
4268947Sdlw 			return;
4278947Sdlw 
4288947Sdlw 		case REGISTER:
4298947Sdlw 		case REG_DEF:
4308947Sdlw 		case AUTO_DEC:
4318947Sdlw 			return;
4328947Sdlw 
4338947Sdlw 		case AUTO_INC:
4348947Sdlw 			if (reg == PC) {
4358947Sdlw 				if (type == F) (void) fetch_long();
4368947Sdlw 				else if (type == D) {
4378947Sdlw 					(void) fetch_long();
4388947Sdlw 					(void) fetch_long();
4398947Sdlw 				} else {
4408947Sdlw 					fprintf(units[STDERR].ufd, "Bad type %d in advance\n",
4418947Sdlw 						type);
44220186Slibs 					f77_abort();
4438947Sdlw 				}
4448947Sdlw 			}
4458947Sdlw 			return;
4468947Sdlw 
4478947Sdlw 		case AUTO_INC_DEF:
4488947Sdlw 			if (reg == PC) (void) fetch_long();
4498947Sdlw 			return;
4508947Sdlw 
4518947Sdlw 		case BYTE_DISP:
4528947Sdlw 		case BYTE_DISP_DEF:
4538947Sdlw 			(void) fetch_byte();
4548947Sdlw 			return;
4558947Sdlw 
4568947Sdlw 		case WORD_DISP:
4578947Sdlw 		case WORD_DISP_DEF:
4588947Sdlw 			(void) fetch_word();
4598947Sdlw 			return;
4608947Sdlw 
4618947Sdlw 		case LONG_DISP:
4628947Sdlw 		case LONG_DISP_DEF:
4638947Sdlw 			(void) fetch_long();
4648947Sdlw 			return;
4658947Sdlw 
4668947Sdlw 		default:
4678947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in op_length()\n", mode);
46820186Slibs 			f77_abort();
4698947Sdlw 	}
4708947Sdlw }
4718947Sdlw 
4728947Sdlw 
4738947Sdlw anyval *
get_operand_address(type)4748947Sdlw get_operand_address(type)
4758947Sdlw {
4768947Sdlw 	register int mode, reg, base;
4778947Sdlw 
4788947Sdlw 	mode = fetch_byte() & 0xff;
4798947Sdlw 	reg = mode & 0xf;
4808947Sdlw 	mode = (mode >> 4) & 0xf;
4818947Sdlw 	switch (mode) {
4828947Sdlw 		case LITERAL0:
4838947Sdlw 		case LITERAL1:
4848947Sdlw 		case LITERAL2:
4858947Sdlw 		case LITERAL3:
4868947Sdlw 			return NULL;
4878947Sdlw 
4888947Sdlw 		case INDEXED:
4898947Sdlw 			base = (int) get_operand_address(type);
4908947Sdlw 			if (base == NULL) return NULL;
4918947Sdlw 			base += contents_of_reg(reg)*type_length(type);
4928947Sdlw 			return (anyval *) base;
4938947Sdlw 
4948947Sdlw 		case REGISTER:
4958947Sdlw 			return addr_of_reg(reg);
4968947Sdlw 
4978947Sdlw 		case REG_DEF:
4988947Sdlw 			return (anyval *) contents_of_reg(reg);
4998947Sdlw 
5008947Sdlw 		case AUTO_DEC:
5018947Sdlw 			return (anyval *) (contents_of_reg(reg)
5028947Sdlw 				- type_length(type));
5038947Sdlw 
5048947Sdlw 		case AUTO_INC:
5058947Sdlw 			return (anyval *) contents_of_reg(reg);
5068947Sdlw 
5078947Sdlw 		case AUTO_INC_DEF:
5088947Sdlw 			return (anyval *) * (long *) contents_of_reg(reg);
5098947Sdlw 
5108947Sdlw 		case BYTE_DISP:
5118947Sdlw 			base = fetch_byte();
5128947Sdlw 			base += contents_of_reg(reg);
5138947Sdlw 			return (anyval *) base;
5148947Sdlw 
5158947Sdlw 		case BYTE_DISP_DEF:
5168947Sdlw 			base = fetch_byte();
5178947Sdlw 			base += contents_of_reg(reg);
5188947Sdlw 			return (anyval *) * (long *) base;
5198947Sdlw 
5208947Sdlw 		case WORD_DISP:
5218947Sdlw 			base = fetch_word();
5228947Sdlw 			base += contents_of_reg(reg);
5238947Sdlw 			return (anyval *) base;
5248947Sdlw 
5258947Sdlw 		case WORD_DISP_DEF:
5268947Sdlw 			base = fetch_word();
5278947Sdlw 			base += contents_of_reg(reg);
5288947Sdlw 			return (anyval *) * (long *) base;
5298947Sdlw 
5308947Sdlw 		case LONG_DISP:
5318947Sdlw 			base = fetch_long();
5328947Sdlw 			base += contents_of_reg(reg);
5338947Sdlw 			return (anyval *) base;
5348947Sdlw 
5358947Sdlw 		case LONG_DISP_DEF:
5368947Sdlw 			base = fetch_long();
5378947Sdlw 			base += contents_of_reg(reg);
5388947Sdlw 			return (anyval *) * (long *) base;
5398947Sdlw 
5408947Sdlw 		default:
5418947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in get_addr()\n", mode);
54220186Slibs 			f77_abort();
5438947Sdlw 	}
5448947Sdlw 	return NULL;
5458947Sdlw }
5468947Sdlw 
5478947Sdlw 
5488947Sdlw 
contents_of_reg(reg)5498947Sdlw contents_of_reg(reg)
5508947Sdlw {
5518947Sdlw 	int value;
5528947Sdlw 
5538947Sdlw 	if (reg == PC) value = (int) pc;
5548947Sdlw 	else if (reg == SP) value = (int) &regs0t6[6];
5558947Sdlw 	else if (reg == FP) value = regs0t6[-2];
5568947Sdlw 	else if (reg == AP) value = regs0t6[-3];
5578947Sdlw 	else if (reg >= 0 && reg <= 6) value = regs0t6[reg];
5588947Sdlw 	else if (reg >= 7 && reg <= 11) value = regs7t11[reg];
5598947Sdlw 	else {
5608947Sdlw 		fprintf(units[STDERR].ufd, "Bad register 0x%x to contents_of()\n", reg);
56120186Slibs 		f77_abort();
5628947Sdlw 		value = -1;
5638947Sdlw 	}
5648947Sdlw 	return value;
5658947Sdlw }
5668947Sdlw 
5678947Sdlw 
5688947Sdlw anyval *
addr_of_reg(reg)5698947Sdlw addr_of_reg(reg)
5708947Sdlw {
5718947Sdlw 	if (reg >= 0 && reg <= 6) {
5728947Sdlw 		return (anyval *) &regs0t6[reg];
5738947Sdlw 	}
5748947Sdlw 	if (reg >= 7 && reg <= 11) {
5758947Sdlw 		return (anyval *) &regs7t11[reg];
5768947Sdlw 	}
5778947Sdlw 	fprintf(units[STDERR].ufd, "Bad reg 0x%x to addr_of()\n", reg);
57820186Slibs 	f77_abort();
5798947Sdlw 	return NULL;
5808947Sdlw }
5818947Sdlw /*
5828947Sdlw  *	fetch_{byte, word, long} - extract values from the PROGRAM area.
5838947Sdlw  *
5848947Sdlw  *	These routines are used in the operand decoding to extract various
5858947Sdlw  *	fields from where the program counter points.  This is because the
5868947Sdlw  *	addressing on the Vax is dynamic: the program counter advances
5878947Sdlw  *	while we are grabbing operands, as well as when we pass instructions.
5888947Sdlw  *	This makes things a bit messy, but I can't help it.
5898947Sdlw  */
fetch_byte()5908947Sdlw fetch_byte()
5918947Sdlw {
5928947Sdlw 	return *pc++;
5938947Sdlw }
5948947Sdlw 
5958947Sdlw 
5968947Sdlw 
fetch_word()5978947Sdlw fetch_word()
5988947Sdlw {
5998947Sdlw 	int *old_pc;
6008947Sdlw 
6018947Sdlw 	old_pc = (int *) pc;
6028947Sdlw 	pc += 2;
6038947Sdlw 	return *old_pc;
6048947Sdlw }
6058947Sdlw 
6068947Sdlw 
6078947Sdlw 
fetch_long()6088947Sdlw fetch_long()
6098947Sdlw {
6108947Sdlw 	long *old_pc;
6118947Sdlw 
6128947Sdlw 	old_pc = (long *) pc;
6138947Sdlw 	pc += 4;
6148947Sdlw 	return *old_pc;
6158947Sdlw }
61620186Slibs 
6178947Sdlw 
type_length(type)6188947Sdlw type_length(type)
6198947Sdlw {
6208947Sdlw 	if (type == F) return 4;
6218947Sdlw 	if (type == D) return 8;
6228947Sdlw 	fprintf(units[STDERR].ufd, "Bad type 0x%x in type_length()\n", type);
62320186Slibs 	f77_abort();
6248947Sdlw 	return -1;
6258947Sdlw }
6268947Sdlw 
6278947Sdlw 
6288947Sdlw 
opcode_name(opcode)6298947Sdlw char *opcode_name(opcode)
6308947Sdlw {
6318947Sdlw 	switch (opcode) {
6328947Sdlw 		case ACBD: 	return "ACBD";
6338947Sdlw 		case ACBF: 	return "ACBF";
6348947Sdlw 		case ADDD2: 	return "ADDD2";
6358947Sdlw 		case ADDD3: 	return "ADDD3";
6368947Sdlw 		case ADDF2: 	return "ADDF2";
6378947Sdlw 		case ADDF3: 	return "ADDF3";
6388947Sdlw 		case CMPD: 	return "CMPD";
6398947Sdlw 		case CMPF: 	return "CMPF";
6408947Sdlw 		case CVTDB: 	return "CVTDB";
6418947Sdlw 		case CVTDF: 	return "CVTDF";
6428947Sdlw 		case CVTDL: 	return "CVTDL";
6438947Sdlw 		case CVTDW: 	return "CVTDW";
6448947Sdlw 		case CVTFB: 	return "CVTFB";
6458947Sdlw 		case CVTFD: 	return "CVTFD";
6468947Sdlw 		case CVTFL: 	return "CVTFL";
6478947Sdlw 		case CVTFW: 	return "CVTFW";
6488947Sdlw 		case CVTRDL: 	return "CVTRDL";
6498947Sdlw 		case CVTRFL: 	return "CVTRFL";
6508947Sdlw 		case DIVD2: 	return "DIVD2";
6518947Sdlw 		case DIVD3: 	return "DIVD3";
6528947Sdlw 		case DIVF2: 	return "DIVF2";
6538947Sdlw 		case DIVF3: 	return "DIVF3";
6548947Sdlw 		case EMODD: 	return "EMODD";
6558947Sdlw 		case EMODF: 	return "EMODF";
6568947Sdlw 		case MNEGD: 	return "MNEGD";
6578947Sdlw 		case MNEGF: 	return "MNEGF";
6588947Sdlw 		case MOVD: 	return "MOVD";
6598947Sdlw 		case MOVF: 	return "MOVF";
6608947Sdlw 		case MULD2: 	return "MULD2";
6618947Sdlw 		case MULD3: 	return "MULD3";
6628947Sdlw 		case MULF2: 	return "MULF2";
6638947Sdlw 		case MULF3: 	return "MULF3";
6648947Sdlw 		case POLYD: 	return "POLYD";
6658947Sdlw 		case POLYF: 	return "POLYF";
6668947Sdlw 		case SUBD2: 	return "SUBD2";
6678947Sdlw 		case SUBD3: 	return "SUBD3";
6688947Sdlw 		case SUBF2: 	return "SUBF2";
6698947Sdlw 		case SUBF3: 	return "SUBF3";
6708947Sdlw 		case TSTD: 	return "TSTD";
6718947Sdlw 		case TSTF: 	return "TSTF";
6728947Sdlw 	}
6738947Sdlw }
6748947Sdlw #endif	vax
67529960Smckusick 
67629960Smckusick #ifdef tahoe
67729960Smckusick /*
67829960Smckusick  *	NO RESERVED OPERAND EXCEPTION ON RESULT OF FP OVERFLOW ON TAHOE.
67929960Smckusick  * 	JUST PRINT THE OVERFLOW MESSAGE. RESULT IS 0 (zero).
68029960Smckusick  */
68129960Smckusick 
68229960Smckusick /*
68329960Smckusick  *	GLOBAL VARIABLES (we need a few)
68429960Smckusick  *
68529960Smckusick  *	Actual program counter and locations of registers.
68629960Smckusick  */
68729960Smckusick static char	*pc;
68829960Smckusick static int	*regs0t1;
68929960Smckusick static int	*regs2t12;
69029960Smckusick static int	max_messages;
69129960Smckusick static int	total_overflows;
69229960Smckusick static union	{
69329960Smckusick 	long	v_long[2];
69429960Smckusick 	double	v_double;
69529960Smckusick 	} retrn;
69639150Sbostic static sig_t sigill_default = (SIG_VAL)-1;
69739150Sbostic static sig_t sigfpe_default;
69829960Smckusick 
69929960Smckusick 
70029960Smckusick /*
70129960Smckusick  *	This routine sets up the signal handler for the floating-point
70229960Smckusick  *	and reserved operand interrupts.
70329960Smckusick  */
70429960Smckusick 
trapov_(count,rtnval)70529960Smckusick trapov_(count, rtnval)
70629960Smckusick 	int *count;
70729960Smckusick 	double *rtnval;
70829960Smckusick {
70939150Sbostic 	void got_overflow();
71029960Smckusick 
71129960Smckusick 	sigfpe_default = signal(SIGFPE, got_overflow);
71229960Smckusick 	total_overflows = 0;
71329960Smckusick 	max_messages = *count;
71429960Smckusick 	retrn.v_double = *rtnval;
71529960Smckusick }
71629960Smckusick 
71729960Smckusick 
71829960Smckusick 
71929960Smckusick /*
72029960Smckusick  *	got_overflow - routine called when overflow occurs
72129960Smckusick  *
72229960Smckusick  *	This routine just prints a message about the overflow.
72329960Smckusick  *	It is impossible to find the bad result at this point.
72429960Smckusick  * 	 NEXT 2 LINES DON'T HOLD FOR TAHOE !
72529960Smckusick  *	Instead, we wait until we get the reserved operand exception
72629960Smckusick  *	when we try to use it.  This raises the SIGILL signal.
72729960Smckusick  */
72829960Smckusick 
72929960Smckusick /*ARGSUSED*/
73039150Sbostic void
got_overflow(signo,codeword,sc)73129960Smckusick got_overflow(signo, codeword, sc)
73229960Smckusick 	int signo, codeword;
73329960Smckusick 	struct sigcontext *sc;
73429960Smckusick {
73529960Smckusick 	int	*sp, i;
73629960Smckusick 	FILE	*ef;
73729960Smckusick 
73829960Smckusick 	signal(SIGFPE, got_overflow);
73929960Smckusick 	ef = units[STDERR].ufd;
74029960Smckusick 	switch (codeword) {
74129960Smckusick 		case INT_OVF_T:
74229960Smckusick 		case INT_DIV_T:
74329960Smckusick 		case FLT_UND_T:
74429960Smckusick 		case FLT_DIV_T:
74539150Sbostic 			if (sigfpe_default > (SIG_VAL)7)
74639150Sbostic 				(*sigfpe_default)(signo, codeword, sc);
74739150Sbostic 			else
74839150Sbostic 				sigdie(signo, codeword, sc);
74939150Sbostic 				/* NOTREACHED */
75029960Smckusick 
75129960Smckusick 		case FLT_OVF_T:
75239150Sbostic 			if (++total_overflows <= max_messages) {
75339150Sbostic 				fprintf(ef, "trapov: %s",
75439150Sbostic 					act_fpe[codeword-1].mesg);
75539150Sbostic 				fprintf(ef, ": Current PC = %X", sc->sc_pc);
75639150Sbostic 				if (total_overflows == max_messages)
75739150Sbostic 					fprintf(ef, ": No more messages will be printed.\n");
75839150Sbostic 				else
75939150Sbostic 					fputc('\n', ef);
76039150Sbostic 			}
76139150Sbostic 			return;
76229960Smckusick 	}
76329960Smckusick }
76429960Smckusick int
ovcnt_()76529960Smckusick ovcnt_()
76629960Smckusick {
76729960Smckusick 	return total_overflows;
76829960Smckusick }
76929960Smckusick #endif tahoe
770