xref: /original-bsd/sys/tahoe/align/exception.c (revision e0c0d005)
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