xref: /linux/arch/alpha/include/asm/extable.h (revision e58e871becec2d3b04ed91c0c16fe8deac9c9dfa)
1 #ifndef _ASM_EXTABLE_H
2 #define _ASM_EXTABLE_H
3 
4 /*
5  * About the exception table:
6  *
7  * - insn is a 32-bit pc-relative offset from the faulting insn.
8  * - nextinsn is a 16-bit offset off of the faulting instruction
9  *   (not off of the *next* instruction as branches are).
10  * - errreg is the register in which to place -EFAULT.
11  * - valreg is the final target register for the load sequence
12  *   and will be zeroed.
13  *
14  * Either errreg or valreg may be $31, in which case nothing happens.
15  *
16  * The exception fixup information "just so happens" to be arranged
17  * as in a MEM format instruction.  This lets us emit our three
18  * values like so:
19  *
20  *      lda valreg, nextinsn(errreg)
21  *
22  */
23 
24 struct exception_table_entry
25 {
26 	signed int insn;
27 	union exception_fixup {
28 		unsigned unit;
29 		struct {
30 			signed int nextinsn : 16;
31 			unsigned int errreg : 5;
32 			unsigned int valreg : 5;
33 		} bits;
34 	} fixup;
35 };
36 
37 /* Returns the new pc */
38 #define fixup_exception(map_reg, _fixup, pc)			\
39 ({								\
40 	if ((_fixup)->fixup.bits.valreg != 31)			\
41 		map_reg((_fixup)->fixup.bits.valreg) = 0;	\
42 	if ((_fixup)->fixup.bits.errreg != 31)			\
43 		map_reg((_fixup)->fixup.bits.errreg) = -EFAULT;	\
44 	(pc) + (_fixup)->fixup.bits.nextinsn;			\
45 })
46 
47 #define ARCH_HAS_RELATIVE_EXTABLE
48 
49 #define swap_ex_entry_fixup(a, b, tmp, delta)			\
50 	do {							\
51 		(a)->fixup.unit = (b)->fixup.unit;		\
52 		(b)->fixup.unit = (tmp).fixup.unit;		\
53 	} while (0)
54 
55 #endif
56