xref: /csrg-svn/usr.bin/f77/libF77/trapov_.c (revision 20186)
18947Sdlw /*
2*20186Slibs char	id_trapov[] = "@(#)trapov_.c	1.3";
38947Sdlw  *
48947Sdlw  *	Fortran/C floating-point overflow handler
58947Sdlw  *
68947Sdlw  *	The idea of these routines is to catch floating-point overflows
78947Sdlw  *	and print an eror message.  When we then get a reserved operand
88947Sdlw  *	exception, we then fix up the value to the highest possible
98947Sdlw  *	number.  Keen, no?
108947Sdlw  *	Messy, yes!
118947Sdlw  *
128947Sdlw  *	Synopsis:
138947Sdlw  *		call trapov(n)
148947Sdlw  *			causes overflows to be trapped, with the first 'n'
158947Sdlw  *			overflows getting an "Overflow!" message printed.
168947Sdlw  *		k = ovcnt(0)
178947Sdlw  *			causes 'k' to get the number of overflows since the
188947Sdlw  *			last call to trapov().
198947Sdlw  *
208947Sdlw  *	Gary Klimowicz, April 17, 1981
218947Sdlw  *	Integerated with libF77: David Wasley, UCB, July 1981.
228947Sdlw  */
238947Sdlw 
248947Sdlw # include <stdio.h>
258947Sdlw # include <signal.h>
268947Sdlw # include "opcodes.h"
278947Sdlw # include "../libI77/fiodefs.h"
2810238Sdlw # define SIG_VAL	int (*)()
298947Sdlw 
308947Sdlw /*
318947Sdlw  *	Operand modes
328947Sdlw  */
338947Sdlw # define LITERAL0	0x0
348947Sdlw # define LITERAL1	0x1
358947Sdlw # define LITERAL2	0x2
368947Sdlw # define LITERAL3	0x3
378947Sdlw # define INDEXED	0x4
388947Sdlw # define REGISTER	0x5
398947Sdlw # define REG_DEF	0x6
408947Sdlw # define AUTO_DEC	0x7
418947Sdlw # define AUTO_INC	0x8
428947Sdlw # define AUTO_INC_DEF	0x9
438947Sdlw # define BYTE_DISP	0xa
448947Sdlw # define BYTE_DISP_DEF	0xb
458947Sdlw # define WORD_DISP	0xc
468947Sdlw # define WORD_DISP_DEF	0xd
478947Sdlw # define LONG_DISP	0xe
488947Sdlw # define LONG_DISP_DEF	0xf
498947Sdlw 
508947Sdlw /*
518947Sdlw  *	Operand value types
528947Sdlw  */
538947Sdlw # define F		1
548947Sdlw # define D		2
558947Sdlw # define IDUNNO		3
568947Sdlw 
578947Sdlw # define PC	0xf
588947Sdlw # define SP	0xe
598947Sdlw # define FP	0xd
608947Sdlw # define AP	0xc
618947Sdlw 
628947Sdlw /*
6310238Sdlw  * trap type codes
6410238Sdlw  */
6510238Sdlw # define INT_OVF_T	1
6610238Sdlw # define INT_DIV_T	2
6710238Sdlw # define FLT_OVF_T	3
6810238Sdlw # define FLT_DIV_T	4
6910238Sdlw # define FLT_UND_T	5
7010238Sdlw # define DEC_OVF_T	6
7110238Sdlw # define SUB_RNG_T	7
7210238Sdlw # define FLT_OVF_F	8
7310238Sdlw # define FLT_DIV_F	9
7410238Sdlw # define FLT_UND_F	10
7510238Sdlw 
7610238Sdlw # define RES_ADR_F	0
7710238Sdlw # define RES_OPC_F	1
7810238Sdlw # define RES_OPR_F	2
7910238Sdlw 
8010238Sdlw /*
818947Sdlw  *	Potential operand values
828947Sdlw  */
838947Sdlw typedef	union operand_types {
848947Sdlw 		char	o_byte;
858947Sdlw 		short	o_word;
868947Sdlw 		long	o_long;
878947Sdlw 		float	o_float;
888947Sdlw 		long	o_quad[2];
898947Sdlw 		double	o_double;
908947Sdlw 	} anyval;
918947Sdlw 
928947Sdlw /*
938947Sdlw  *	GLOBAL VARIABLES (we need a few)
948947Sdlw  *
958947Sdlw  *	Actual program counter and locations of registers.
968947Sdlw  */
9710238Sdlw #if	vax
988947Sdlw static char	*pc;
998947Sdlw static int	*regs0t6;
1008947Sdlw static int	*regs7t11;
1018947Sdlw static int	max_messages;
1028947Sdlw static int	total_overflows;
1038947Sdlw static union	{
1048947Sdlw 	long	v_long[2];
1058947Sdlw 	double	v_double;
1068947Sdlw 	} retrn;
10710238Sdlw static int	(*sigill_default)() = (SIG_VAL)-1;
10810238Sdlw static int	(*sigfpe_default)();
10910238Sdlw #endif	vax
1108947Sdlw 
1118947Sdlw /*
1128947Sdlw  *	the fortran unit control table
1138947Sdlw  */
1148947Sdlw extern unit units[];
1158947Sdlw 
11610238Sdlw /*
11710238Sdlw  * Fortran message table is in main
11810238Sdlw  */
11910238Sdlw struct msgtbl {
12010238Sdlw 	char	*mesg;
12110238Sdlw 	int	dummy;
12210238Sdlw };
12310238Sdlw extern struct msgtbl	act_fpe[];
12410238Sdlw 
12510238Sdlw 
12610238Sdlw 
1278947Sdlw anyval *get_operand_address(), *addr_of_reg();
1288947Sdlw char *opcode_name();
1298947Sdlw 
1308947Sdlw /*
1318947Sdlw  *	This routine sets up the signal handler for the floating-point
1328947Sdlw  *	and reserved operand interrupts.
1338947Sdlw  */
1348947Sdlw 
1358947Sdlw trapov_(count, rtnval)
1368947Sdlw 	int *count;
1378947Sdlw 	double *rtnval;
1388947Sdlw {
1398947Sdlw #if	vax
1408947Sdlw 	extern 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:
17910238Sdlw 				if (sigfpe_default > (SIG_VAL)7)
18010238Sdlw 					return((*sigfpe_default)(signo, codeword, myaddr, pc, ps));
18110238Sdlw 				else
18210238Sdlw 					sigdie(signo, codeword, myaddr, pc, ps);
18310238Sdlw 					/* NOTREACHED */
18410238Sdlw 
18510238Sdlw 		case FLT_OVF_T:
18610238Sdlw 		case FLT_DIV_T:
18710238Sdlw 				if (++total_overflows <= max_messages) {
18810238Sdlw 					fprintf(ef, "trapov: %s",
18910238Sdlw 						act_fpe[codeword-1].mesg);
19010238Sdlw 					if (total_overflows == max_messages)
19110238Sdlw 						fprintf(ef, ": No more messages will be printed.\n");
19210238Sdlw 					else
19310238Sdlw 						fputc('\n', ef);
19410238Sdlw 				}
19510238Sdlw 				return;
1968947Sdlw 	}
1978947Sdlw #endif	vax
1988947Sdlw }
1998947Sdlw 
2008947Sdlw int
2018947Sdlw ovcnt_()
2028947Sdlw {
2038947Sdlw 	return total_overflows;
2048947Sdlw }
2058947Sdlw 
2068947Sdlw #if	vax
2078947Sdlw /*
2088947Sdlw  *	got_illegal_instruction - handle "illegal instruction" signals.
2098947Sdlw  *
2108947Sdlw  *	This really deals only with reserved operand exceptions.
2118947Sdlw  *	Since there is no way to check this directly, we look at the
2128947Sdlw  *	opcode of the instruction we are executing to see if it is a
2138947Sdlw  *	floating-point operation (with floating-point operands, not
2148947Sdlw  *	just results).
2158947Sdlw  *
2168947Sdlw  *	This is complicated by the fact that the registers that will
2178947Sdlw  *	eventually be restored are saved in two places.  registers 7-11
2188947Sdlw  *	are saved by this routine, and are in its call frame. (we have
2198947Sdlw  *	to take special care that these registers are specified in
2208947Sdlw  *	the procedure entry mask here.)
2218947Sdlw  *	Registers 0-6 are saved at interrupt time, and are at a offset
2228947Sdlw  *	-8 from the 'signo' parameter below.
2238947Sdlw  *	There is ane extremely inimate connection between the value of
2248947Sdlw  *	the entry mask set by the 'makefile' script, and the constants
2258947Sdlw  *	used in the register offset calculations below.
2268947Sdlw  *	Can someone think of a better way to do this?
2278947Sdlw  */
2288947Sdlw 
2298947Sdlw /*ARGSUSED*/
2308947Sdlw got_illegal_instruction(signo, codeword, myaddr, trap_pc, ps)
2318947Sdlw 	char *myaddr, *trap_pc;
2328947Sdlw {
2338947Sdlw 	int first_local[1];		/* must be first */
2348947Sdlw 	int i, opcode, type, o_no, no_reserved;
2358947Sdlw 	anyval *opnd;
2368947Sdlw 
2378947Sdlw 	regs7t11 = &first_local[0];
2388947Sdlw 	regs0t6 = &signo - 8;
2398947Sdlw 	pc = trap_pc;
2408947Sdlw 
2418947Sdlw 	opcode = fetch_byte() & 0xff;
2428947Sdlw 	no_reserved = 0;
24310238Sdlw 	if (codeword != RES_OPR_F || !is_floating_operation(opcode)) {
24410238Sdlw 		if (sigill_default > (SIG_VAL)7)
24510238Sdlw 			return((*sigill_default)(signo, codeword, myaddr, trap_pc, ps));
24610238Sdlw 		else
24710238Sdlw 			sigdie(signo, codeword, myaddr, trap_pc, ps);
24810238Sdlw 			/* NOTREACHED */
2498947Sdlw 	}
2508947Sdlw 
2518947Sdlw 	if (opcode == POLYD || opcode == POLYF) {
2528947Sdlw 		got_illegal_poly(opcode);
2538947Sdlw 		return;
2548947Sdlw 	}
2558947Sdlw 
2568947Sdlw 	if (opcode == EMODD || opcode == EMODF) {
2578947Sdlw 		got_illegal_emod(opcode);
2588947Sdlw 		return;
2598947Sdlw 	}
2608947Sdlw 
2618947Sdlw 	/*
2628947Sdlw 	 * This opcode wasn't "unusual".
2638947Sdlw 	 * Look at the operands to try and find a reserved operand.
2648947Sdlw 	 */
2658947Sdlw 	for (o_no = 1; o_no <= no_operands(opcode); ++o_no) {
2668947Sdlw 		type = operand_type(opcode, o_no);
2678947Sdlw 		if (type != F && type != D) {
2688947Sdlw 			advance_pc(type);
2698947Sdlw 			continue;
2708947Sdlw 		}
2718947Sdlw 
2728947Sdlw 		/* F or D operand.  Check it out */
2738947Sdlw 		opnd = get_operand_address(type);
2748947Sdlw 		if (opnd == NULL) {
2758947Sdlw 			fprintf(units[STDERR].ufd, "Can't get operand address: 0x%x, %d\n",
2768947Sdlw 				pc, o_no);
277*20186Slibs 			f77_abort();
2788947Sdlw 		}
2798947Sdlw 		if (type == F && opnd->o_long == 0x00008000) {
2808947Sdlw 			/* found one */
2818947Sdlw 			opnd->o_long = retrn.v_long[0];
2828947Sdlw 			++no_reserved;
2838947Sdlw 		} else if (type == D && opnd->o_long == 0x00008000) {
2848947Sdlw 			/* found one here, too! */
2858947Sdlw 			opnd->o_quad[0] = retrn.v_long[0];
2868947Sdlw 			/* Fix next pointer */
2878947Sdlw 			if (opnd == addr_of_reg(6)) opnd = addr_of_reg(7);
2888947Sdlw 			else opnd = (anyval *) ((char *) opnd + 4);
2898947Sdlw 			opnd->o_quad[0] = retrn.v_long[1];
2908947Sdlw 			++no_reserved;
2918947Sdlw 		}
2928947Sdlw 
2938947Sdlw 	}
2948947Sdlw 
2958947Sdlw 	if (no_reserved == 0) {
2968947Sdlw 		fprintf(units[STDERR].ufd, "Can't find any reserved operand!\n");
297*20186Slibs 		f77_abort();
2988947Sdlw 	}
2998947Sdlw }
3008947Sdlw /*
3018947Sdlw  * is_floating_exception - was the operation code for a floating instruction?
3028947Sdlw  */
3038947Sdlw 
3048947Sdlw is_floating_operation(opcode)
3058947Sdlw 	int opcode;
3068947Sdlw {
3078947Sdlw 	switch (opcode) {
3088947Sdlw 		case ACBD:	case ACBF:	case ADDD2:	case ADDD3:
3098947Sdlw 		case ADDF2:	case ADDF3:	case CMPD:	case CMPF:
3108947Sdlw 		case CVTDB:	case CVTDF:	case CVTDL:	case CVTDW:
3118947Sdlw 		case CVTFB:	case CVTFD:	case CVTFL:	case CVTFW:
3128947Sdlw 		case CVTRDL:	case CVTRFL:	case DIVD2:	case DIVD3:
3138947Sdlw 		case DIVF2:	case DIVF3:	case EMODD:	case EMODF:
3148947Sdlw 		case MNEGD:	case MNEGF:	case MOVD:	case MOVF:
3158947Sdlw 		case MULD2:	case MULD3:	case MULF2:	case MULF3:
3168947Sdlw 		case POLYD:	case POLYF:	case SUBD2:	case SUBD3:
3178947Sdlw 		case SUBF2:	case SUBF3:	case TSTD:	case TSTF:
3188947Sdlw 			return 1;
3198947Sdlw 
3208947Sdlw 		default:
3218947Sdlw 			return 0;
3228947Sdlw 	}
3238947Sdlw }
3248947Sdlw /*
3258947Sdlw  * got_illegal_poly - handle an illegal POLY[DF] instruction.
3268947Sdlw  *
3278947Sdlw  * We don't do anything here yet.
3288947Sdlw  */
3298947Sdlw 
3308947Sdlw /*ARGSUSED*/
3318947Sdlw got_illegal_poly(opcode)
3328947Sdlw {
3338947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'poly' instructions yet\n");
334*20186Slibs 	f77_abort();
3358947Sdlw }
3368947Sdlw 
3378947Sdlw 
3388947Sdlw 
3398947Sdlw /*
3408947Sdlw  * got_illegal_emod - handle illegal EMOD[DF] instruction.
3418947Sdlw  *
3428947Sdlw  * We don't do anything here yet.
3438947Sdlw  */
3448947Sdlw 
3458947Sdlw /*ARGSUSED*/
3468947Sdlw got_illegal_emod(opcode)
3478947Sdlw {
3488947Sdlw 	fprintf(units[STDERR].ufd, "Can't do 'emod' instructions yet\n");
349*20186Slibs 	f77_abort();
3508947Sdlw }
3518947Sdlw 
3528947Sdlw 
3538947Sdlw /*
3548947Sdlw  *	no_operands - determine the number of operands in this instruction.
3558947Sdlw  *
3568947Sdlw  */
3578947Sdlw 
3588947Sdlw no_operands(opcode)
3598947Sdlw {
3608947Sdlw 	switch (opcode) {
3618947Sdlw 		case ACBD:
3628947Sdlw 		case ACBF:
3638947Sdlw 			return 3;
3648947Sdlw 
3658947Sdlw 		case MNEGD:
3668947Sdlw 		case MNEGF:
3678947Sdlw 		case MOVD:
3688947Sdlw 		case MOVF:
3698947Sdlw 		case TSTD:
3708947Sdlw 		case TSTF:
3718947Sdlw 			return 1;
3728947Sdlw 
3738947Sdlw 		default:
3748947Sdlw 			return 2;
3758947Sdlw 	}
3768947Sdlw }
3778947Sdlw 
3788947Sdlw 
3798947Sdlw 
3808947Sdlw /*
3818947Sdlw  *	operand_type - is the operand a D or an F?
3828947Sdlw  *
3838947Sdlw  *	We are only descriminating between Floats and Doubles here.
3848947Sdlw  *	Other operands may be possible on exotic instructions.
3858947Sdlw  */
3868947Sdlw 
3878947Sdlw /*ARGSUSED*/
3888947Sdlw operand_type(opcode, no)
3898947Sdlw {
3908947Sdlw 	if (opcode >= 0x40 && opcode <= 0x56) return F;
3918947Sdlw 	if (opcode >= 0x60 && opcode <= 0x76) return D;
3928947Sdlw 	return IDUNNO;
3938947Sdlw }
3948947Sdlw 
3958947Sdlw 
3968947Sdlw 
3978947Sdlw /*
3988947Sdlw  *	advance_pc - Advance the program counter past an operand.
3998947Sdlw  *
4008947Sdlw  *	We just bump the pc by the appropriate values.
4018947Sdlw  */
4028947Sdlw 
4038947Sdlw advance_pc(type)
4048947Sdlw {
4058947Sdlw 	register int mode, reg;
4068947Sdlw 
4078947Sdlw 	mode = fetch_byte();
4088947Sdlw 	reg = mode & 0xf;
4098947Sdlw 	mode = (mode >> 4) & 0xf;
4108947Sdlw 	switch (mode) {
4118947Sdlw 		case LITERAL0:
4128947Sdlw 		case LITERAL1:
4138947Sdlw 		case LITERAL2:
4148947Sdlw 		case LITERAL3:
4158947Sdlw 			return;
4168947Sdlw 
4178947Sdlw 		case INDEXED:
4188947Sdlw 			advance_pc(type);
4198947Sdlw 			return;
4208947Sdlw 
4218947Sdlw 		case REGISTER:
4228947Sdlw 		case REG_DEF:
4238947Sdlw 		case AUTO_DEC:
4248947Sdlw 			return;
4258947Sdlw 
4268947Sdlw 		case AUTO_INC:
4278947Sdlw 			if (reg == PC) {
4288947Sdlw 				if (type == F) (void) fetch_long();
4298947Sdlw 				else if (type == D) {
4308947Sdlw 					(void) fetch_long();
4318947Sdlw 					(void) fetch_long();
4328947Sdlw 				} else {
4338947Sdlw 					fprintf(units[STDERR].ufd, "Bad type %d in advance\n",
4348947Sdlw 						type);
435*20186Slibs 					f77_abort();
4368947Sdlw 				}
4378947Sdlw 			}
4388947Sdlw 			return;
4398947Sdlw 
4408947Sdlw 		case AUTO_INC_DEF:
4418947Sdlw 			if (reg == PC) (void) fetch_long();
4428947Sdlw 			return;
4438947Sdlw 
4448947Sdlw 		case BYTE_DISP:
4458947Sdlw 		case BYTE_DISP_DEF:
4468947Sdlw 			(void) fetch_byte();
4478947Sdlw 			return;
4488947Sdlw 
4498947Sdlw 		case WORD_DISP:
4508947Sdlw 		case WORD_DISP_DEF:
4518947Sdlw 			(void) fetch_word();
4528947Sdlw 			return;
4538947Sdlw 
4548947Sdlw 		case LONG_DISP:
4558947Sdlw 		case LONG_DISP_DEF:
4568947Sdlw 			(void) fetch_long();
4578947Sdlw 			return;
4588947Sdlw 
4598947Sdlw 		default:
4608947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in op_length()\n", mode);
461*20186Slibs 			f77_abort();
4628947Sdlw 	}
4638947Sdlw }
4648947Sdlw 
4658947Sdlw 
4668947Sdlw anyval *
4678947Sdlw get_operand_address(type)
4688947Sdlw {
4698947Sdlw 	register int mode, reg, base;
4708947Sdlw 
4718947Sdlw 	mode = fetch_byte() & 0xff;
4728947Sdlw 	reg = mode & 0xf;
4738947Sdlw 	mode = (mode >> 4) & 0xf;
4748947Sdlw 	switch (mode) {
4758947Sdlw 		case LITERAL0:
4768947Sdlw 		case LITERAL1:
4778947Sdlw 		case LITERAL2:
4788947Sdlw 		case LITERAL3:
4798947Sdlw 			return NULL;
4808947Sdlw 
4818947Sdlw 		case INDEXED:
4828947Sdlw 			base = (int) get_operand_address(type);
4838947Sdlw 			if (base == NULL) return NULL;
4848947Sdlw 			base += contents_of_reg(reg)*type_length(type);
4858947Sdlw 			return (anyval *) base;
4868947Sdlw 
4878947Sdlw 		case REGISTER:
4888947Sdlw 			return addr_of_reg(reg);
4898947Sdlw 
4908947Sdlw 		case REG_DEF:
4918947Sdlw 			return (anyval *) contents_of_reg(reg);
4928947Sdlw 
4938947Sdlw 		case AUTO_DEC:
4948947Sdlw 			return (anyval *) (contents_of_reg(reg)
4958947Sdlw 				- type_length(type));
4968947Sdlw 
4978947Sdlw 		case AUTO_INC:
4988947Sdlw 			return (anyval *) contents_of_reg(reg);
4998947Sdlw 
5008947Sdlw 		case AUTO_INC_DEF:
5018947Sdlw 			return (anyval *) * (long *) contents_of_reg(reg);
5028947Sdlw 
5038947Sdlw 		case BYTE_DISP:
5048947Sdlw 			base = fetch_byte();
5058947Sdlw 			base += contents_of_reg(reg);
5068947Sdlw 			return (anyval *) base;
5078947Sdlw 
5088947Sdlw 		case BYTE_DISP_DEF:
5098947Sdlw 			base = fetch_byte();
5108947Sdlw 			base += contents_of_reg(reg);
5118947Sdlw 			return (anyval *) * (long *) base;
5128947Sdlw 
5138947Sdlw 		case WORD_DISP:
5148947Sdlw 			base = fetch_word();
5158947Sdlw 			base += contents_of_reg(reg);
5168947Sdlw 			return (anyval *) base;
5178947Sdlw 
5188947Sdlw 		case WORD_DISP_DEF:
5198947Sdlw 			base = fetch_word();
5208947Sdlw 			base += contents_of_reg(reg);
5218947Sdlw 			return (anyval *) * (long *) base;
5228947Sdlw 
5238947Sdlw 		case LONG_DISP:
5248947Sdlw 			base = fetch_long();
5258947Sdlw 			base += contents_of_reg(reg);
5268947Sdlw 			return (anyval *) base;
5278947Sdlw 
5288947Sdlw 		case LONG_DISP_DEF:
5298947Sdlw 			base = fetch_long();
5308947Sdlw 			base += contents_of_reg(reg);
5318947Sdlw 			return (anyval *) * (long *) base;
5328947Sdlw 
5338947Sdlw 		default:
5348947Sdlw 			fprintf(units[STDERR].ufd, "Bad mode 0x%x in get_addr()\n", mode);
535*20186Slibs 			f77_abort();
5368947Sdlw 	}
5378947Sdlw 	return NULL;
5388947Sdlw }
5398947Sdlw 
5408947Sdlw 
5418947Sdlw 
5428947Sdlw contents_of_reg(reg)
5438947Sdlw {
5448947Sdlw 	int value;
5458947Sdlw 
5468947Sdlw 	if (reg == PC) value = (int) pc;
5478947Sdlw 	else if (reg == SP) value = (int) &regs0t6[6];
5488947Sdlw 	else if (reg == FP) value = regs0t6[-2];
5498947Sdlw 	else if (reg == AP) value = regs0t6[-3];
5508947Sdlw 	else if (reg >= 0 && reg <= 6) value = regs0t6[reg];
5518947Sdlw 	else if (reg >= 7 && reg <= 11) value = regs7t11[reg];
5528947Sdlw 	else {
5538947Sdlw 		fprintf(units[STDERR].ufd, "Bad register 0x%x to contents_of()\n", reg);
554*20186Slibs 		f77_abort();
5558947Sdlw 		value = -1;
5568947Sdlw 	}
5578947Sdlw 	return value;
5588947Sdlw }
5598947Sdlw 
5608947Sdlw 
5618947Sdlw anyval *
5628947Sdlw addr_of_reg(reg)
5638947Sdlw {
5648947Sdlw 	if (reg >= 0 && reg <= 6) {
5658947Sdlw 		return (anyval *) &regs0t6[reg];
5668947Sdlw 	}
5678947Sdlw 	if (reg >= 7 && reg <= 11) {
5688947Sdlw 		return (anyval *) &regs7t11[reg];
5698947Sdlw 	}
5708947Sdlw 	fprintf(units[STDERR].ufd, "Bad reg 0x%x to addr_of()\n", reg);
571*20186Slibs 	f77_abort();
5728947Sdlw 	return NULL;
5738947Sdlw }
5748947Sdlw /*
5758947Sdlw  *	fetch_{byte, word, long} - extract values from the PROGRAM area.
5768947Sdlw  *
5778947Sdlw  *	These routines are used in the operand decoding to extract various
5788947Sdlw  *	fields from where the program counter points.  This is because the
5798947Sdlw  *	addressing on the Vax is dynamic: the program counter advances
5808947Sdlw  *	while we are grabbing operands, as well as when we pass instructions.
5818947Sdlw  *	This makes things a bit messy, but I can't help it.
5828947Sdlw  */
5838947Sdlw fetch_byte()
5848947Sdlw {
5858947Sdlw 	return *pc++;
5868947Sdlw }
5878947Sdlw 
5888947Sdlw 
5898947Sdlw 
5908947Sdlw fetch_word()
5918947Sdlw {
5928947Sdlw 	int *old_pc;
5938947Sdlw 
5948947Sdlw 	old_pc = (int *) pc;
5958947Sdlw 	pc += 2;
5968947Sdlw 	return *old_pc;
5978947Sdlw }
5988947Sdlw 
5998947Sdlw 
6008947Sdlw 
6018947Sdlw fetch_long()
6028947Sdlw {
6038947Sdlw 	long *old_pc;
6048947Sdlw 
6058947Sdlw 	old_pc = (long *) pc;
6068947Sdlw 	pc += 4;
6078947Sdlw 	return *old_pc;
6088947Sdlw }
609*20186Slibs 
6108947Sdlw 
6118947Sdlw type_length(type)
6128947Sdlw {
6138947Sdlw 	if (type == F) return 4;
6148947Sdlw 	if (type == D) return 8;
6158947Sdlw 	fprintf(units[STDERR].ufd, "Bad type 0x%x in type_length()\n", type);
616*20186Slibs 	f77_abort();
6178947Sdlw 	return -1;
6188947Sdlw }
6198947Sdlw 
6208947Sdlw 
6218947Sdlw 
6228947Sdlw char *opcode_name(opcode)
6238947Sdlw {
6248947Sdlw 	switch (opcode) {
6258947Sdlw 		case ACBD: 	return "ACBD";
6268947Sdlw 		case ACBF: 	return "ACBF";
6278947Sdlw 		case ADDD2: 	return "ADDD2";
6288947Sdlw 		case ADDD3: 	return "ADDD3";
6298947Sdlw 		case ADDF2: 	return "ADDF2";
6308947Sdlw 		case ADDF3: 	return "ADDF3";
6318947Sdlw 		case CMPD: 	return "CMPD";
6328947Sdlw 		case CMPF: 	return "CMPF";
6338947Sdlw 		case CVTDB: 	return "CVTDB";
6348947Sdlw 		case CVTDF: 	return "CVTDF";
6358947Sdlw 		case CVTDL: 	return "CVTDL";
6368947Sdlw 		case CVTDW: 	return "CVTDW";
6378947Sdlw 		case CVTFB: 	return "CVTFB";
6388947Sdlw 		case CVTFD: 	return "CVTFD";
6398947Sdlw 		case CVTFL: 	return "CVTFL";
6408947Sdlw 		case CVTFW: 	return "CVTFW";
6418947Sdlw 		case CVTRDL: 	return "CVTRDL";
6428947Sdlw 		case CVTRFL: 	return "CVTRFL";
6438947Sdlw 		case DIVD2: 	return "DIVD2";
6448947Sdlw 		case DIVD3: 	return "DIVD3";
6458947Sdlw 		case DIVF2: 	return "DIVF2";
6468947Sdlw 		case DIVF3: 	return "DIVF3";
6478947Sdlw 		case EMODD: 	return "EMODD";
6488947Sdlw 		case EMODF: 	return "EMODF";
6498947Sdlw 		case MNEGD: 	return "MNEGD";
6508947Sdlw 		case MNEGF: 	return "MNEGF";
6518947Sdlw 		case MOVD: 	return "MOVD";
6528947Sdlw 		case MOVF: 	return "MOVF";
6538947Sdlw 		case MULD2: 	return "MULD2";
6548947Sdlw 		case MULD3: 	return "MULD3";
6558947Sdlw 		case MULF2: 	return "MULF2";
6568947Sdlw 		case MULF3: 	return "MULF3";
6578947Sdlw 		case POLYD: 	return "POLYD";
6588947Sdlw 		case POLYF: 	return "POLYF";
6598947Sdlw 		case SUBD2: 	return "SUBD2";
6608947Sdlw 		case SUBD3: 	return "SUBD3";
6618947Sdlw 		case SUBF2: 	return "SUBF2";
6628947Sdlw 		case SUBF3: 	return "SUBF3";
6638947Sdlw 		case TSTD: 	return "TSTD";
6648947Sdlw 		case TSTF: 	return "TSTF";
6658947Sdlw 	}
6668947Sdlw }
6678947Sdlw #endif	vax
668