1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _ASM_S390_ALTERNATIVE_ASM_H
3#define _ASM_S390_ALTERNATIVE_ASM_H
4
5#ifdef __ASSEMBLY__
6
7/*
8 * Issue one struct alt_instr descriptor entry (need to put it into
9 * the section .altinstructions, see below). This entry contains
10 * enough information for the alternatives patching code to patch an
11 * instruction. See apply_alternatives().
12 */
13.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
14	.long	\orig_start - .
15	.long	\alt_start - .
16	.word	\feature
17	.byte	\orig_end - \orig_start
18	.org	. - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start )
19	.org	. - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start )
20.endm
21
22/*
23 * Define an alternative between two instructions. If @feature is
24 * present, early code in apply_alternatives() replaces @oldinstr with
25 * @newinstr.
26 */
27.macro ALTERNATIVE oldinstr, newinstr, feature
28	.pushsection .altinstr_replacement,"ax"
29770:	\newinstr
30771:	.popsection
31772:	\oldinstr
32773:	.pushsection .altinstructions,"a"
33	alt_entry 772b, 773b, 770b, 771b, \feature
34	.popsection
35.endm
36
37/*
38 * Define an alternative between two instructions. If @feature is
39 * present, early code in apply_alternatives() replaces @oldinstr with
40 * @newinstr.
41 */
42.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
43	.pushsection .altinstr_replacement,"ax"
44770:	\newinstr1
45771:	\newinstr2
46772:	.popsection
47773:	\oldinstr
48774:	.pushsection .altinstructions,"a"
49	alt_entry 773b, 774b, 770b, 771b,\feature1
50	alt_entry 773b, 774b, 771b, 772b,\feature2
51	.popsection
52.endm
53
54#endif	/*  __ASSEMBLY__  */
55
56#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
57