1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#ifndef _ASM_X86_ALTERNATIVE_ASM_H_
#define _ASM_X86_ALTERNATIVE_ASM_H_
#include <asm/nops.h>
#ifdef __ASSEMBLY__
/*
* Issue one struct alt_instr descriptor entry (need to put it into
* the section .altinstructions, see below). This entry contains
* enough information for the alternatives patching code to patch an
* instruction. See apply_alternatives().
*/
.macro altinstruction_entry orig repl feature orig_len repl_len pad_len
.long \orig - .
.long \repl - .
.word \feature
.byte \orig_len
.byte \repl_len
.byte \pad_len
.byte 0 /* priv */
.endm
.macro mknops nr_bytes
#ifdef HAVE_AS_NOPS_DIRECTIVE
.nops \nr_bytes, ASM_NOP_MAX
#else
.skip \nr_bytes, 0x90
#endif
.endm
/* GAS's idea of true is -1, while Clang's idea is 1. */
#ifdef HAVE_AS_NEGATIVE_TRUE
# define as_true(x) (-(x))
#else
# define as_true(x) (x)
#endif
#define decl_orig(insn, padding) \
.L\@_orig_s: insn; .L\@_orig_e: \
.L\@_diff = padding; \
mknops (as_true(.L\@_diff > 0) * .L\@_diff); \
.L\@_orig_p:
#define orig_len (.L\@_orig_e - .L\@_orig_s)
#define pad_len (.L\@_orig_p - .L\@_orig_e)
#define total_len (.L\@_orig_p - .L\@_orig_s)
#define decl_repl(insn, nr) .L\@_repl_s\()nr: insn; .L\@_repl_e\()nr:
#define repl_len(nr) (.L\@_repl_e\()nr - .L\@_repl_s\()nr)
#define as_max(a, b) ((a) ^ (((a) ^ (b)) & -as_true((a) < (b))))
.macro ALTERNATIVE oldinstr, newinstr, feature
decl_orig(\oldinstr, repl_len(1) - orig_len)
.pushsection .altinstructions, "a", @progbits
altinstruction_entry .L\@_orig_s, .L\@_repl_s1, \feature, \
orig_len, repl_len(1), pad_len
.section .discard, "a", @progbits
/*
* Assembler-time checks:
* - total_len <= 255
* - \newinstr <= total_len
*/
.byte total_len
.byte 0xff + repl_len(1) - total_len
.section .altinstr_replacement, "ax", @progbits
decl_repl(\newinstr, 1)
.popsection
.endm
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
decl_orig(\oldinstr, as_max(repl_len(1), repl_len(2)) - orig_len)
.pushsection .altinstructions, "a", @progbits
altinstruction_entry .L\@_orig_s, .L\@_repl_s1, \feature1, \
orig_len, repl_len(1), pad_len
altinstruction_entry .L\@_orig_s, .L\@_repl_s2, \feature2, \
orig_len, repl_len(2), pad_len
.section .discard, "a", @progbits
/*
* Assembler-time checks:
* - total_len <= 255
* - \newinstr* <= total_len
*/
.byte total_len
.byte 0xff + repl_len(1) - total_len
.byte 0xff + repl_len(2) - total_len
.section .altinstr_replacement, "ax", @progbits
decl_repl(\newinstr1, 1)
decl_repl(\newinstr2, 2)
.popsection
.endm
#undef as_max
#undef repl_len
#undef decl_repl
#undef total_len
#undef pad_len
#undef orig_len
#undef decl_orig
#undef as_true
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_ALTERNATIVE_ASM_H_ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
|