@@ -156,102 +156,50 @@ static inline int alternatives_text_reserved(void *start, void *end)
156
156
157
157
#define ALT_CALL_INSTR "call BUG_func"
158
158
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"
161
162
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" \
170
166
"# 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 */ \
208
175
" .4byte " __stringify (ft_flags ) "\n" /* feature + flags */ \
209
176
" .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"
211
179
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"
215
185
216
186
/* alternative assembly primitive: */
217
187
#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)
225
191
226
192
#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)
236
194
237
195
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
238
196
#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)
255
203
256
204
/*
257
205
* Alternative instructions for different CPU types or capabilities.
@@ -266,14 +214,11 @@ static inline int alternatives_text_reserved(void *start, void *end)
266
214
* without volatile and memory clobber.
267
215
*/
268
216
#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")
270
218
271
219
#define alternative_2 (oldinstr , newinstr1 , ft_flags1 , newinstr2 , ft_flags2 ) \
272
220
asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) ::: "memory")
273
221
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
-
277
222
/*
278
223
* Alternative inline assembly with input.
279
224
*
@@ -283,31 +228,41 @@ static inline int alternatives_text_reserved(void *start, void *end)
283
228
* Leaving an unused argument 0 to keep API compatibility.
284
229
*/
285
230
#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) \
287
232
: : "i" (0), ## input)
288
233
289
234
/* Like alternative_input, but with a single output argument */
290
235
#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) \
292
237
: output : "i" (0), ## input)
293
238
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)
298
253
299
254
/*
300
255
* Like alternative_call, but there are two features and respective functions.
301
256
* If CPU has feature2, function2 is used.
302
257
* Otherwise, if CPU has feature1, function1 is used.
303
258
* Otherwise, old function is used.
304
259
*/
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), \
311
266
[new2] "i" (newfunc2), ## input)
312
267
313
268
/*
@@ -322,6 +277,8 @@ static inline int alternatives_text_reserved(void *start, void *end)
322
277
*/
323
278
#define ASM_NO_INPUT_CLOBBER (clbr ...) "i" (0) : clbr
324
279
280
+ #define ALT_OUTPUT_SP (...) ASM_CALL_CONSTRAINT, ## __VA_ARGS__
281
+
325
282
/* Macro for creating assembler functions avoiding any C magic. */
326
283
#define DEFINE_ASM_FUNC (func , instr , sec ) \
327
284
asm (".pushsection " #sec ", \"ax\"\n" \
@@ -388,89 +345,43 @@ void nop_func(void);
388
345
* @newinstr. ".skip" directive takes care of proper instruction padding
389
346
* in case @newinstr is longer than @oldinstr.
390
347
*/
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 ;
401
362
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 )
407
365
.endm
408
366
409
367
#define old_len 141b-140b
410
368
#define new_len1 144f-143f
411
369
#define new_len2 145f-144f
412
370
#define new_len3 146f-145f
413
371
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
-
424
372
/*
425
373
* Same as ALTERNATIVE macro above but for two alternatives. If CPU
426
374
* has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
427
375
* @feature2, it replaces @oldinstr with @feature2.
428
376
*/
429
377
.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 )
449
380
.endm
450
381
451
382
.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 )
474
385
.endm
475
386
476
387
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
0 commit comments