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