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