162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef _ASM_EXTABLE_H 362306a36Sopenharmony_ci#define _ASM_EXTABLE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * About the exception table: 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * - insn is a 32-bit pc-relative offset from the faulting insn. 962306a36Sopenharmony_ci * - nextinsn is a 16-bit offset off of the faulting instruction 1062306a36Sopenharmony_ci * (not off of the *next* instruction as branches are). 1162306a36Sopenharmony_ci * - errreg is the register in which to place -EFAULT. 1262306a36Sopenharmony_ci * - valreg is the final target register for the load sequence 1362306a36Sopenharmony_ci * and will be zeroed. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Either errreg or valreg may be $31, in which case nothing happens. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * The exception fixup information "just so happens" to be arranged 1862306a36Sopenharmony_ci * as in a MEM format instruction. This lets us emit our three 1962306a36Sopenharmony_ci * values like so: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * lda valreg, nextinsn(errreg) 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct exception_table_entry 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci signed int insn; 2862306a36Sopenharmony_ci union exception_fixup { 2962306a36Sopenharmony_ci unsigned unit; 3062306a36Sopenharmony_ci struct { 3162306a36Sopenharmony_ci signed int nextinsn : 16; 3262306a36Sopenharmony_ci unsigned int errreg : 5; 3362306a36Sopenharmony_ci unsigned int valreg : 5; 3462306a36Sopenharmony_ci } bits; 3562306a36Sopenharmony_ci } fixup; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* Returns the new pc */ 3962306a36Sopenharmony_ci#define fixup_exception(map_reg, _fixup, pc) \ 4062306a36Sopenharmony_ci({ \ 4162306a36Sopenharmony_ci if ((_fixup)->fixup.bits.valreg != 31) \ 4262306a36Sopenharmony_ci map_reg((_fixup)->fixup.bits.valreg) = 0; \ 4362306a36Sopenharmony_ci if ((_fixup)->fixup.bits.errreg != 31) \ 4462306a36Sopenharmony_ci map_reg((_fixup)->fixup.bits.errreg) = -EFAULT; \ 4562306a36Sopenharmony_ci (pc) + (_fixup)->fixup.bits.nextinsn; \ 4662306a36Sopenharmony_ci}) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define ARCH_HAS_RELATIVE_EXTABLE 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define swap_ex_entry_fixup(a, b, tmp, delta) \ 5162306a36Sopenharmony_ci do { \ 5262306a36Sopenharmony_ci (a)->fixup.unit = (b)->fixup.unit; \ 5362306a36Sopenharmony_ci (b)->fixup.unit = (tmp).fixup.unit; \ 5462306a36Sopenharmony_ci } while (0) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#endif 57