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