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 */
exception(infop,type,param1,param2)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
not_needed(infop)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
cannot_do(infop)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