/* SPDX-License-Identifier: GPL-2.0 */1#ifndef _ASM_EXTABLE_H2#define _ASM_EXTABLE_H34/*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 instruction9* (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 sequence12* 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 arranged17* as in a MEM format instruction. This lets us emit our three18* values like so:19*20* lda valreg, nextinsn(errreg)21*22*/2324struct exception_table_entry25{26signed int insn;27union exception_fixup {28unsigned unit;29struct {30signed int nextinsn : 16;31unsigned int errreg : 5;32unsigned int valreg : 5;33} bits;34} fixup;35};3637/* Returns the new pc */38#define fixup_exception(map_reg, _fixup, pc) \39({ \40if ((_fixup)->fixup.bits.valreg != 31) \41map_reg((_fixup)->fixup.bits.valreg) = 0; \42if ((_fixup)->fixup.bits.errreg != 31) \43map_reg((_fixup)->fixup.bits.errreg) = -EFAULT; \44(pc) + (_fixup)->fixup.bits.nextinsn; \45})4647#define ARCH_HAS_RELATIVE_EXTABLE4849#define swap_ex_entry_fixup(a, b, tmp, delta) \50do { \51(a)->fixup.unit = (b)->fixup.unit; \52(b)->fixup.unit = (tmp).fixup.unit; \53} while (0)5455#endif565758