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