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) ®s0t6[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 *) ®s0t6[reg];
5738947Sdlw }
5748947Sdlw if (reg >= 7 && reg <= 11) {
5758947Sdlw return (anyval *) ®s7t11[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