1 /*- 2 * Copyright (c) 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Computer Consoles Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)exception.c 7.1 (Berkeley) 12/06/90 11 */ 12 13 #include "align.h" 14 15 /* 16 * Signal an exception. It will be handled by 'locore.s'. Here, I: 17 * 1) Put the exception code where it belongs on the stack. 18 * 2) Restore pc and sp to show that the current opcode 19 * 'was not executed'. 20 * 3) Execute one big non-local-goto. In the process we take care 21 * to reset the current HW fp such that 'alignment' will 22 * indeed return to 'locore.s'. 23 * IMPORTANT NOTE : the process I use will NOT restore 24 * all registers (like normal returns) so the call to the 25 * handling routine HAS TO BE the last thing in 'alignment'. 26 * Otherwise, all its own register variables will be a mess !! 27 * I also know that 'alignment' itself WILL restore all 28 * registers for 'locore.s' since its entry mask is all-1. 29 */ 30 exception(infop, type, param1, param2) 31 process_info *infop; 32 int type, param1, param2; 33 { 34 register long *my_fp; 35 register long *current_fp, *prev_fp; 36 37 my_fp = (long *)&infop-1 ; 38 infop->ret_exception = type; 39 switch (type) { 40 case ARITHMETIC: 41 infop->ret_code = param1; 42 break; 43 case ILL_ACCESS: 44 infop->ret_addr = param1; 45 infop->ret_code = param2; 46 break; 47 case ALIGNMENT: 48 case ILL_ADDRMOD: 49 case ILL_OPRND: 50 break; 51 default : 52 printf ("Bad exception type %d (alignment code)\n", type); 53 break; 54 } 55 /* 56 * Now the big trick. Look up the stack until the frame of 57 * 'alignment' is found. prev_fp will point to it and current_fp 58 * will then point to the frame of whoever 'alignment' called. 59 * This should better work ... 60 */ 61 prev_fp = my_fp; 62 while (prev_fp != &fp) { 63 current_fp = prev_fp; 64 prev_fp = (long *) *prev_fp; 65 } 66 /* 67 * Found it. Now fool the HW into thinking that 'alignment' called 68 * us directly here, so this routine's 'return' will go back 69 * all the way to 'alignment', stopping any further emulation 70 * for the current offending opcode. 71 * "fool the HW..." ha ha, am I realy fooling myself ? 72 */ 73 *my_fp = *current_fp; 74 *(my_fp - 2) = *(current_fp -2); /* Alter program counter */ 75 /* 76 * Without further ado, just go back now !!!! 77 */ 78 } 79 80 not_needed (infop) 81 process_info *infop; 82 { 83 /* 84 * Shouldn't ever come to this routine. 85 */ 86 87 printf ("Opcode 0x%x should not trap to alignment code.", 88 opCODE); 89 printf (" OS or machine problem!! \n"); 90 } 91 92 93 cannot_do (infop) 94 process_info *infop; 95 { 96 /* 97 * Some opcode-caused alignments cannot be emulated. See table.c for 98 * specific reasons. Reflect this back to the process as alignment 99 * exception. 100 */ 101 exception (infop, ALIGNMENT); 102 } 103