@@ -156,102 +156,50 @@ static inline int alternatives_text_reserved(void *start, void *end)
156156
157157#define ALT_CALL_INSTR "call BUG_func"
158158
159- #define b_replacement (num ) "664"#num
160- #define e_replacement (num ) "665"#num
159+ #define alt_slen "772b-771b"
160+ #define alt_total_slen "773b-771b"
161+ #define alt_rlen "775f-774f"
161162
162- #define alt_end_marker "663"
163- #define alt_slen "662b-661b"
164- #define alt_total_slen alt_end_marker"b-661b"
165- #define alt_rlen (num ) e_replacement(num)"f-"b_replacement(num)"f"
166-
167- #define OLDINSTR (oldinstr , num ) \
168- "# ALT: oldnstr\n" \
169- "661:\n\t" oldinstr "\n662:\n" \
163+ #define OLDINSTR (oldinstr ) \
164+ "# ALT: oldinstr\n" \
165+ "771:\n\t" oldinstr "\n772:\n" \
170166 "# ALT: padding\n" \
171- ".skip -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * " \
172- "((" alt_rlen(num) ")-(" alt_slen ")),0x90\n" \
173- alt_end_marker ":\n"
174-
175- /*
176- * gas compatible max based on the idea from:
177- * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
178- *
179- * The additional "-" is needed because gas uses a "true" value of -1.
180- */
181- #define alt_max_short (a , b ) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
182-
183- /*
184- * Pad the second replacement alternative with additional NOPs if it is
185- * additionally longer than the first replacement alternative.
186- */
187- #define OLDINSTR_2 (oldinstr , num1 , num2 ) \
188- "# ALT: oldinstr2\n" \
189- "661:\n\t" oldinstr "\n662:\n" \
190- "# ALT: padding2\n" \
191- ".skip -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \
192- "(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")), 0x90\n" \
193- alt_end_marker ":\n"
194-
195- #define OLDINSTR_3 (oldinsn , n1 , n2 , n3 ) \
196- "# ALT: oldinstr3\n" \
197- "661:\n\t" oldinsn "\n662:\n" \
198- "# ALT: padding3\n" \
199- ".skip -((" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
200- " - (" alt_slen ")) > 0) * " \
201- "(" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
202- " - (" alt_slen ")), 0x90\n" \
203- alt_end_marker ":\n"
204-
205- #define ALTINSTR_ENTRY (ft_flags , num ) \
206- " .long 661b - .\n" /* label */ \
207- " .long " b_replacement (num )"f - .\n" /* new instruction */ \
167+ ".skip -(((" alt_rlen ")-(" alt_slen ")) > 0) * " \
168+ "((" alt_rlen ")-(" alt_slen ")),0x90\n" \
169+ "773:\n"
170+
171+ #define ALTINSTR_ENTRY (ft_flags ) \
172+ ".pushsection .altinstructions,\"a\"\n" \
173+ " .long 771b - .\n" /* label */ \
174+ " .long 774f - .\n" /* new instruction */ \
208175 " .4byte " __stringify (ft_flags ) "\n" /* feature + flags */ \
209176 " .byte " alt_total_slen "\n" /* source len */ \
210- " .byte " alt_rlen (num ) "\n" /* replacement len */
177+ " .byte " alt_rlen "\n" /* replacement len */ \
178+ ".popsection\n"
211179
212- #define ALTINSTR_REPLACEMENT (newinstr , num ) /* replacement */ \
213- "# ALT: replacement " #num "\n" \
214- b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n"
180+ #define ALTINSTR_REPLACEMENT (newinstr ) /* replacement */ \
181+ ".pushsection .altinstr_replacement, \"ax\"\n" \
182+ "# ALT: replacement\n" \
183+ "774:\n\t" newinstr "\n775:\n" \
184+ ".popsection\n"
215185
216186/* alternative assembly primitive: */
217187#define ALTERNATIVE (oldinstr , newinstr , ft_flags ) \
218- OLDINSTR(oldinstr, 1) \
219- ".pushsection .altinstructions,\"a\"\n" \
220- ALTINSTR_ENTRY(ft_flags, 1) \
221- ".popsection\n" \
222- ".pushsection .altinstr_replacement, \"ax\"\n" \
223- ALTINSTR_REPLACEMENT(newinstr, 1) \
224- ".popsection\n"
188+ OLDINSTR(oldinstr) \
189+ ALTINSTR_ENTRY(ft_flags) \
190+ ALTINSTR_REPLACEMENT(newinstr)
225191
226192#define ALTERNATIVE_2 (oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2 ) \
227- OLDINSTR_2(oldinstr, 1, 2) \
228- ".pushsection .altinstructions,\"a\"\n" \
229- ALTINSTR_ENTRY(ft_flags1, 1) \
230- ALTINSTR_ENTRY(ft_flags2, 2) \
231- ".popsection\n" \
232- ".pushsection .altinstr_replacement, \"ax\"\n" \
233- ALTINSTR_REPLACEMENT(newinstr1, 1) \
234- ALTINSTR_REPLACEMENT(newinstr2, 2) \
235- ".popsection\n"
193+ ALTERNATIVE(ALTERNATIVE(oldinstr, newinstr1, ft_flags1), newinstr2, ft_flags2)
236194
237195/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
238196#define ALTERNATIVE_TERNARY (oldinstr , ft_flags , newinstr_yes , newinstr_no ) \
239- ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
240- newinstr_yes, ft_flags)
241-
242- #define ALTERNATIVE_3 (oldinsn , newinsn1 , ft_flags1 , newinsn2 , ft_flags2 , \
243- newinsn3 , ft_flags3 ) \
244- OLDINSTR_3(oldinsn, 1, 2, 3) \
245- ".pushsection .altinstructions,\"a\"\n" \
246- ALTINSTR_ENTRY(ft_flags1, 1) \
247- ALTINSTR_ENTRY(ft_flags2, 2) \
248- ALTINSTR_ENTRY(ft_flags3, 3) \
249- ".popsection\n" \
250- ".pushsection .altinstr_replacement, \"ax\"\n" \
251- ALTINSTR_REPLACEMENT(newinsn1, 1) \
252- ALTINSTR_REPLACEMENT(newinsn2, 2) \
253- ALTINSTR_REPLACEMENT(newinsn3, 3) \
254- ".popsection\n"
197+ ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, newinstr_yes, ft_flags)
198+
199+ #define ALTERNATIVE_3 (oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2 , \
200+ newinstr3 , ft_flags3 ) \
201+ ALTERNATIVE(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2), \
202+ newinstr3, ft_flags3)
255203
256204/*
257205 * Alternative instructions for different CPU types or capabilities.
@@ -266,14 +214,11 @@ static inline int alternatives_text_reserved(void *start, void *end)
266214 * without volatile and memory clobber.
267215 */
268216#define alternative (oldinstr , newinstr , ft_flags ) \
269- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) : : : "memory")
217+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) : : : "memory")
270218
271219#define alternative_2 (oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2 ) \
272220 asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) ::: "memory")
273221
274- #define alternative_ternary (oldinstr , ft_flags , newinstr_yes , newinstr_no ) \
275- asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) ::: "memory")
276-
277222/*
278223 * Alternative inline assembly with input.
279224 *
@@ -283,31 +228,41 @@ static inline int alternatives_text_reserved(void *start, void *end)
283228 * Leaving an unused argument 0 to keep API compatibility.
284229 */
285230#define alternative_input (oldinstr , newinstr , ft_flags , input ...) \
286- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) \
231+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
287232 : : "i" (0), ## input)
288233
289234/* Like alternative_input, but with a single output argument */
290235#define alternative_io (oldinstr , newinstr , ft_flags , output , input ...) \
291- asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, ft_flags) \
236+ asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
292237 : output : "i" (0), ## input)
293238
294- /* Like alternative_io, but for replacing a direct call with another one. */
295- #define alternative_call (oldfunc , newfunc , ft_flags , output , input ...) \
296- asm_inline volatile (ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \
297- : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
239+ /*
240+ * Like alternative_io, but for replacing a direct call with another one.
241+ *
242+ * Use the %c operand modifier which is the generic way to print a bare
243+ * constant expression with all syntax-specific punctuation omitted. %P
244+ * is the x86-specific variant which can handle constants too, for
245+ * historical reasons, but it should be used primarily for PIC
246+ * references: i.e., if used for a function, it would add the PLT
247+ * suffix.
248+ */
249+ #define alternative_call (oldfunc , newfunc , ft_flags , output , input ...) \
250+ asm_inline volatile(ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \
251+ : ALT_OUTPUT_SP(output) \
252+ : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
298253
299254/*
300255 * Like alternative_call, but there are two features and respective functions.
301256 * If CPU has feature2, function2 is used.
302257 * Otherwise, if CPU has feature1, function1 is used.
303258 * Otherwise, old function is used.
304259 */
305- #define alternative_call_2 (oldfunc , newfunc1 , ft_flags1 , newfunc2 , ft_flags2 , \
306- output , input ...) \
307- asm_inline volatile (ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \
308- "call %c[new2]", ft_flags2) \
309- : output, ASM_CALL_CONSTRAINT \
310- : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
260+ #define alternative_call_2 (oldfunc , newfunc1 , ft_flags1 , newfunc2 , ft_flags2 , \
261+ output , input ...) \
262+ asm_inline volatile(ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \
263+ "call %c[new2]", ft_flags2) \
264+ : ALT_OUTPUT_SP( output) \
265+ : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
311266 [new2] "i" (newfunc2), ## input)
312267
313268/*
@@ -322,6 +277,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
322277 */
323278#define ASM_NO_INPUT_CLOBBER (clbr ...) "i" (0) : clbr
324279
280+ #define ALT_OUTPUT_SP (...) ASM_CALL_CONSTRAINT, ## __VA_ARGS__
281+
325282/* Macro for creating assembler functions avoiding any C magic. */
326283#define DEFINE_ASM_FUNC (func , instr , sec ) \
327284 asm (".pushsection " #sec ", \"ax\"\n" \
@@ -388,89 +345,43 @@ void nop_func(void);
388345 * @newinstr. ".skip" directive takes care of proper instruction padding
389346 * in case @newinstr is longer than @oldinstr.
390347 */
391- .macro ALTERNATIVE oldinstr , newinstr , ft_flags
392- 140 :
393- \oldinstr
394- 141 :
395- .skip - (((144f - 143f )- (141b - 140b )) > 0 ) * ((144f - 143f )- (141b - 140b )),0x90
396- 142 :
397-
398- .pushsection .altinstructions ,"a"
399- altinstr_entry 140b ,143f ,\ft_flags ,142b - 140b ,144f - 143f
400- .popsection
348+ #define __ALTERNATIVE (oldinst , newinst , flag ) \
349+ 740: \
350+ oldinst ; \
351+ 741: \
352+ .skip -(((744f-743f)-(741b-740b)) > 0) * ((744f-743f)-(741b-740b)),0x90 ;\
353+ 742: \
354+ .pushsection .altinstructions,"a" ; \
355+ altinstr_entry 740b,743f,flag,742b-740b,744f-743f ; \
356+ .popsection ; \
357+ .pushsection .altinstr_replacement,"ax" ; \
358+ 743: \
359+ newinst ; \
360+ 744: \
361+ .popsection ;
401362
402- .pushsection .altinstr_replacement ,"ax"
403- 143 :
404- \newinstr
405- 144 :
406- .popsection
363+ .macro ALTERNATIVE oldinstr , newinstr , ft_flags
364+ __ALTERNATIVE (\oldinstr , \newinstr , \ft_flags )
407365.endm
408366
409367#define old_len 141b-140b
410368#define new_len1 144f-143f
411369#define new_len2 145f-144f
412370#define new_len3 146f-145f
413371
414- /*
415- * gas compatible max based on the idea from:
416- * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
417- *
418- * The additional "-" is needed because gas uses a "true" value of -1.
419- */
420- #define alt_max_2 (a , b ) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
421- #define alt_max_3 (a , b , c ) (alt_max_2(alt_max_2(a, b), c))
422-
423-
424372/*
425373 * Same as ALTERNATIVE macro above but for two alternatives. If CPU
426374 * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
427375 * @feature2, it replaces @oldinstr with @feature2.
428376 */
429377.macro ALTERNATIVE_2 oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2
430- 140 :
431- \oldinstr
432- 141 :
433- .skip - ((alt_max_2 (new_len1 , new_len2 ) - (old_len )) > 0 ) * \
434- (alt_max_2 (new_len1 , new_len2 ) - (old_len )),0x90
435- 142 :
436-
437- .pushsection .altinstructions ,"a "
438- altinstr_entry 140b ,143f ,\ft_flags1 ,142b -140b ,144f -143f
439- altinstr_entry 140b ,144f ,\ft_flags2 ,142b -140b ,145f -144f
440- .popsection
441-
442- .pushsection .altinstr_replacement ,"ax "
443- 143 :
444- \newinstr1
445- 144 :
446- \newinstr2
447- 145 :
448- .popsection
378+ __ALTERNATIVE (__ALTERNATIVE (\oldinstr , \newinstr1 , \ft_flags1 ),
379+ \newinstr2 , \ft_flags2 )
449380.endm
450381
451382.macro ALTERNATIVE_3 oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2 , newinstr3 , ft_flags3
452- 140 :
453- \oldinstr
454- 141 :
455- .skip - ((alt_max_3 (new_len1 , new_len2 , new_len3 ) - (old_len )) > 0 ) * \
456- (alt_max_3 (new_len1 , new_len2 , new_len3 ) - (old_len )),0x90
457- 142 :
458-
459- .pushsection .altinstructions ,"a "
460- altinstr_entry 140b ,143f ,\ft_flags1 ,142b -140b ,144f -143f
461- altinstr_entry 140b ,144f ,\ft_flags2 ,142b -140b ,145f -144f
462- altinstr_entry 140b ,145f ,\ft_flags3 ,142b -140b ,146f -145f
463- .popsection
464-
465- .pushsection .altinstr_replacement ,"ax "
466- 143 :
467- \newinstr1
468- 144 :
469- \newinstr2
470- 145 :
471- \newinstr3
472- 146 :
473- .popsection
383+ __ALTERNATIVE (ALTERNATIVE_2 (\oldinstr , \newinstr1 , \ft_flags1 , \newinstr2 , \ft_flags2 ),
384+ \newinstr3 , \ft_flags3 )
474385.endm
475386
476387/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
0 commit comments