@lumiscia/lumen-cli-linux-arm64 0.0.0-stage → 0.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2036 @@
1
+ COPYING:
2
+
3
+ Copyright © 2018-2025, VideoLAN and dav1d authors
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+
27
+
28
+ x86inc.asm:
29
+
30
+ ;*****************************************************************************
31
+ ;* x86inc.asm: x86 abstraction layer
32
+ ;*****************************************************************************
33
+ ;* Copyright (C) 2005-2024 x264 project
34
+ ;*
35
+ ;* Authors: Loren Merritt <lorenm@u.washington.edu>
36
+ ;* Henrik Gramner <henrik@gramner.com>
37
+ ;* Anton Mitrofanov <BugMaster@narod.ru>
38
+ ;* Fiona Glaser <fiona@x264.com>
39
+ ;*
40
+ ;* Permission to use, copy, modify, and/or distribute this software for any
41
+ ;* purpose with or without fee is hereby granted, provided that the above
42
+ ;* copyright notice and this permission notice appear in all copies.
43
+ ;*
44
+ ;* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
45
+ ;* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
46
+ ;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
47
+ ;* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48
+ ;* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
49
+ ;* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
50
+ ;* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51
+ ;*****************************************************************************
52
+
53
+ ; This is a header file for the x86inc.asm assembly language, which uses
54
+ ; NASM/YASM syntax combined with a large number of macros to provide easy
55
+ ; abstraction between different calling conventions (x86_32, win64, linux64).
56
+ ; It also has various other useful features to simplify writing the kind of
57
+ ; DSP functions that are most often used.
58
+
59
+ %ifndef private_prefix
60
+ %error private_prefix not defined
61
+ %endif
62
+
63
+ %ifndef public_prefix
64
+ %define public_prefix private_prefix
65
+ %endif
66
+
67
+ %ifndef STACK_ALIGNMENT
68
+ %if ARCH_X86_64
69
+ %define STACK_ALIGNMENT 16
70
+ %else
71
+ %define STACK_ALIGNMENT 4
72
+ %endif
73
+ %endif
74
+
75
+ %define WIN32 0
76
+ %define WIN64 0
77
+ %define UNIX64 0
78
+ %if ARCH_X86_64
79
+ %ifidn __OUTPUT_FORMAT__,win32
80
+ %define WIN32 1
81
+ %define WIN64 1
82
+ %elifidn __OUTPUT_FORMAT__,win64
83
+ %define WIN32 1
84
+ %define WIN64 1
85
+ %elifidn __OUTPUT_FORMAT__,x64
86
+ %define WIN32 1
87
+ %define WIN64 1
88
+ %else
89
+ %define UNIX64 1
90
+ %endif
91
+ %else
92
+ %ifidn __OUTPUT_FORMAT__,win32
93
+ %define WIN32 1
94
+ %endif
95
+ %endif
96
+
97
+ %define FORMAT_ELF 0
98
+ %define FORMAT_MACHO 0
99
+ %define FORMAT_OBJ 0
100
+ %ifidn __OUTPUT_FORMAT__,elf
101
+ %define FORMAT_ELF 1
102
+ %elifidn __OUTPUT_FORMAT__,elf32
103
+ %define FORMAT_ELF 1
104
+ %elifidn __OUTPUT_FORMAT__,elf64
105
+ %define FORMAT_ELF 1
106
+ %elifidn __OUTPUT_FORMAT__,macho
107
+ %define FORMAT_MACHO 1
108
+ %elifidn __OUTPUT_FORMAT__,macho32
109
+ %define FORMAT_MACHO 1
110
+ %elifidn __OUTPUT_FORMAT__,macho64
111
+ %define FORMAT_MACHO 1
112
+ %elifidn __OUTPUT_FORMAT__,obj
113
+ %define FORMAT_OBJ 1
114
+ %elifidn __OUTPUT_FORMAT__,obj2
115
+ %define FORMAT_OBJ 1
116
+ %endif
117
+
118
+ %ifdef PREFIX
119
+ %define mangle(x) _ %+ x
120
+ %else
121
+ %define mangle(x) x
122
+ %endif
123
+
124
+ ; Use VEX-encoding even in non-AVX functions
125
+ %ifndef FORCE_VEX_ENCODING
126
+ %define FORCE_VEX_ENCODING 0
127
+ %endif
128
+
129
+ %macro SECTION_RODATA 0-1 16
130
+ %ifidn __OUTPUT_FORMAT__,win32
131
+ SECTION .rdata align=%1
132
+ %elif WIN64
133
+ SECTION .rdata align=%1
134
+ %elifidn __OUTPUT_FORMAT__,aout
135
+ SECTION .text
136
+ %else
137
+ SECTION .rodata align=%1
138
+ %endif
139
+ %endmacro
140
+
141
+ %if ARCH_X86_64
142
+ %define PIC 1 ; always use PIC on x86-64
143
+ default rel
144
+ %elifidn __OUTPUT_FORMAT__,win32
145
+ %define PIC 0 ; PIC isn't used on 32-bit Windows
146
+ %elifndef PIC
147
+ %define PIC 0
148
+ %endif
149
+
150
+ %define HAVE_PRIVATE_EXTERN 1
151
+ %ifdef __NASM_VERSION_ID__
152
+ %use smartalign
153
+ %if __NASM_VERSION_ID__ < 0x020e0000 ; 2.14
154
+ %define HAVE_PRIVATE_EXTERN 0
155
+ %endif
156
+ %endif
157
+
158
+ ; Macros to eliminate most code duplication between x86_32 and x86_64:
159
+ ; Currently this works only for leaf functions which load all their arguments
160
+ ; into registers at the start, and make no other use of the stack. Luckily that
161
+ ; covers most use cases.
162
+
163
+ ; PROLOGUE:
164
+ ; %1 = number of arguments. loads them from stack if needed.
165
+ ; %2 = number of registers used. pushes callee-saved regs if needed.
166
+ ; %3 = number of xmm registers used. pushes callee-saved xmm regs if needed.
167
+ ; %4 = (optional) stack size to be allocated. The stack will be aligned before
168
+ ; allocating the specified stack size. If the required stack alignment is
169
+ ; larger than the known stack alignment the stack will be manually aligned
170
+ ; and an extra register will be allocated to hold the original stack
171
+ ; pointer (to not invalidate r0m etc.). To prevent the use of an extra
172
+ ; register as stack pointer, request a negative stack size.
173
+ ; %4+/%5+ = list of names to define to registers
174
+ ; PROLOGUE can also be invoked by adding the same options to cglobal
175
+
176
+ ; e.g.
177
+ ; cglobal foo, 2,3,7,0x40, dst, src, tmp
178
+ ; declares a function (foo) that automatically loads two arguments (dst and
179
+ ; src) into registers, uses one additional register (tmp) plus 7 vector
180
+ ; registers (m0-m6) and allocates 0x40 bytes of stack space.
181
+
182
+ ; TODO Some functions can use some args directly from the stack. If they're the
183
+ ; last args then you can just not declare them, but if they're in the middle
184
+ ; we need more flexible macro.
185
+
186
+ ; RET:
187
+ ; Pops anything that was pushed by PROLOGUE, and returns.
188
+
189
+ ; REP_RET:
190
+ ; Use this instead of RET if it's a branch target.
191
+
192
+ ; registers:
193
+ ; rN and rNq are the native-size register holding function argument N
194
+ ; rNd, rNw, rNb are dword, word, and byte size
195
+ ; rNh is the high 8 bits of the word size
196
+ ; rNm is the original location of arg N (a register or on the stack), dword
197
+ ; rNmp is native size
198
+
199
+ %macro DECLARE_REG 2-3
200
+ %define r%1q %2
201
+ %define r%1d %2d
202
+ %define r%1w %2w
203
+ %define r%1b %2b
204
+ %define r%1h %2h
205
+ %define %2q %2
206
+ %if %0 == 2
207
+ %define r%1m %2d
208
+ %define r%1mp %2
209
+ %elif ARCH_X86_64 ; memory
210
+ %define r%1m [rstk + stack_offset + %3]
211
+ %define r%1mp qword r %+ %1 %+ m
212
+ %else
213
+ %define r%1m [rstk + stack_offset + %3]
214
+ %define r%1mp dword r %+ %1 %+ m
215
+ %endif
216
+ %define r%1 %2
217
+ %endmacro
218
+
219
+ %macro DECLARE_REG_SIZE 3
220
+ %define r%1q r%1
221
+ %define e%1q r%1
222
+ %define r%1d e%1
223
+ %define e%1d e%1
224
+ %define r%1w %1
225
+ %define e%1w %1
226
+ %define r%1h %3
227
+ %define e%1h %3
228
+ %define r%1b %2
229
+ %define e%1b %2
230
+ %if ARCH_X86_64 == 0
231
+ %define r%1 e%1
232
+ %endif
233
+ %endmacro
234
+
235
+ DECLARE_REG_SIZE ax, al, ah
236
+ DECLARE_REG_SIZE bx, bl, bh
237
+ DECLARE_REG_SIZE cx, cl, ch
238
+ DECLARE_REG_SIZE dx, dl, dh
239
+ DECLARE_REG_SIZE si, sil, null
240
+ DECLARE_REG_SIZE di, dil, null
241
+ DECLARE_REG_SIZE bp, bpl, null
242
+
243
+ ; t# defines for when per-arch register allocation is more complex than just function arguments
244
+
245
+ %macro DECLARE_REG_TMP 1-*
246
+ %assign %%i 0
247
+ %rep %0
248
+ CAT_XDEFINE t, %%i, r%1
249
+ %assign %%i %%i+1
250
+ %rotate 1
251
+ %endrep
252
+ %endmacro
253
+
254
+ %macro DECLARE_REG_TMP_SIZE 0-*
255
+ %rep %0
256
+ %define t%1q t%1 %+ q
257
+ %define t%1d t%1 %+ d
258
+ %define t%1w t%1 %+ w
259
+ %define t%1h t%1 %+ h
260
+ %define t%1b t%1 %+ b
261
+ %rotate 1
262
+ %endrep
263
+ %endmacro
264
+
265
+ DECLARE_REG_TMP_SIZE 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
266
+
267
+ %if ARCH_X86_64
268
+ %define gprsize 8
269
+ %else
270
+ %define gprsize 4
271
+ %endif
272
+
273
+ %macro LEA 2
274
+ %if ARCH_X86_64
275
+ lea %1, [%2]
276
+ %elif PIC
277
+ call $+5 ; special-cased to not affect the RSB on most CPU:s
278
+ pop %1
279
+ add %1, -$+1+%2
280
+ %else
281
+ mov %1, %2
282
+ %endif
283
+ %endmacro
284
+
285
+ ; Repeats an instruction/operation for multiple arguments.
286
+ ; Example usage: "REPX {psrlw x, 8}, m0, m1, m2, m3"
287
+ %macro REPX 2-* ; operation, args
288
+ %xdefine %%f(x) %1
289
+ %rep %0 - 1
290
+ %rotate 1
291
+ %%f(%1)
292
+ %endrep
293
+ %endmacro
294
+
295
+ %macro PUSH 1
296
+ push %1
297
+ %ifidn rstk, rsp
298
+ %assign stack_offset stack_offset+gprsize
299
+ %endif
300
+ %endmacro
301
+
302
+ %macro POP 1
303
+ pop %1
304
+ %ifidn rstk, rsp
305
+ %assign stack_offset stack_offset-gprsize
306
+ %endif
307
+ %endmacro
308
+
309
+ %macro PUSH_IF_USED 1-*
310
+ %rep %0
311
+ %if %1 < regs_used
312
+ PUSH r%1
313
+ %endif
314
+ %rotate 1
315
+ %endrep
316
+ %endmacro
317
+
318
+ %macro POP_IF_USED 1-*
319
+ %rep %0
320
+ %if %1 < regs_used
321
+ pop r%1
322
+ %endif
323
+ %rotate 1
324
+ %endrep
325
+ %endmacro
326
+
327
+ %macro LOAD_IF_USED 1-*
328
+ %rep %0
329
+ %if %1 < num_args
330
+ mov r%1, r %+ %1 %+ mp
331
+ %endif
332
+ %rotate 1
333
+ %endrep
334
+ %endmacro
335
+
336
+ %macro SUB 2
337
+ sub %1, %2
338
+ %ifidn %1, rstk
339
+ %assign stack_offset stack_offset+(%2)
340
+ %endif
341
+ %endmacro
342
+
343
+ %macro ADD 2
344
+ add %1, %2
345
+ %ifidn %1, rstk
346
+ %assign stack_offset stack_offset-(%2)
347
+ %endif
348
+ %endmacro
349
+
350
+ %macro movifnidn 2
351
+ %ifnidn %1, %2
352
+ mov %1, %2
353
+ %endif
354
+ %endmacro
355
+
356
+ %if ARCH_X86_64 == 0
357
+ %define movsxd movifnidn
358
+ %endif
359
+
360
+ %macro movsxdifnidn 2
361
+ %ifnidn %1, %2
362
+ movsxd %1, %2
363
+ %endif
364
+ %endmacro
365
+
366
+ %macro ASSERT 1
367
+ %if (%1) == 0
368
+ %error assertion ``%1'' failed
369
+ %endif
370
+ %endmacro
371
+
372
+ %macro DEFINE_ARGS 0-*
373
+ %ifdef n_arg_names
374
+ %assign %%i 0
375
+ %rep n_arg_names
376
+ CAT_UNDEF arg_name %+ %%i, q
377
+ CAT_UNDEF arg_name %+ %%i, d
378
+ CAT_UNDEF arg_name %+ %%i, w
379
+ CAT_UNDEF arg_name %+ %%i, h
380
+ CAT_UNDEF arg_name %+ %%i, b
381
+ CAT_UNDEF arg_name %+ %%i, m
382
+ CAT_UNDEF arg_name %+ %%i, mp
383
+ CAT_UNDEF arg_name, %%i
384
+ %assign %%i %%i+1
385
+ %endrep
386
+ %endif
387
+
388
+ %xdefine %%stack_offset stack_offset
389
+ %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine
390
+ %assign %%i 0
391
+ %rep %0
392
+ %xdefine %1q r %+ %%i %+ q
393
+ %xdefine %1d r %+ %%i %+ d
394
+ %xdefine %1w r %+ %%i %+ w
395
+ %xdefine %1h r %+ %%i %+ h
396
+ %xdefine %1b r %+ %%i %+ b
397
+ %xdefine %1m r %+ %%i %+ m
398
+ %xdefine %1mp r %+ %%i %+ mp
399
+ CAT_XDEFINE arg_name, %%i, %1
400
+ %assign %%i %%i+1
401
+ %rotate 1
402
+ %endrep
403
+ %xdefine stack_offset %%stack_offset
404
+ %assign n_arg_names %0
405
+ %endmacro
406
+
407
+ %define required_stack_alignment ((mmsize + 15) & ~15)
408
+ %define vzeroupper_required (mmsize > 16 && (ARCH_X86_64 == 0 || xmm_regs_used > 16 || notcpuflag(avx512)))
409
+ %define high_mm_regs (16*cpuflag(avx512))
410
+
411
+ ; Large stack allocations on Windows need to use stack probing in order
412
+ ; to guarantee that all stack memory is committed before accessing it.
413
+ ; This is done by ensuring that the guard page(s) at the end of the
414
+ ; currently committed pages are touched prior to any pages beyond that.
415
+ %if WIN64
416
+ %assign STACK_PROBE_SIZE 8192
417
+ %elifidn __OUTPUT_FORMAT__, win32
418
+ %assign STACK_PROBE_SIZE 4096
419
+ %else
420
+ %assign STACK_PROBE_SIZE 0
421
+ %endif
422
+
423
+ %macro PROBE_STACK 1 ; stack_size
424
+ %if STACK_PROBE_SIZE
425
+ %assign %%i STACK_PROBE_SIZE
426
+ %rep %1 / STACK_PROBE_SIZE
427
+ mov eax, [rsp-%%i]
428
+ %assign %%i %%i+STACK_PROBE_SIZE
429
+ %endrep
430
+ %endif
431
+ %endmacro
432
+
433
+ %macro RESET_STACK_STATE 0
434
+ %ifidn rstk, rsp
435
+ %assign stack_offset stack_offset - stack_size_padded
436
+ %else
437
+ %xdefine rstk rsp
438
+ %endif
439
+ %assign stack_size 0
440
+ %assign stack_size_padded 0
441
+ %assign xmm_regs_used 0
442
+ %endmacro
443
+
444
+ %macro ALLOC_STACK 0-2 0, 0 ; stack_size, n_xmm_regs
445
+ RESET_STACK_STATE
446
+ %ifnum %2
447
+ %if mmsize != 8
448
+ %assign xmm_regs_used %2
449
+ %endif
450
+ %endif
451
+ %ifnum %1
452
+ %if %1 != 0
453
+ %assign %%pad 0
454
+ %assign stack_size %1
455
+ %if stack_size < 0
456
+ %assign stack_size -stack_size
457
+ %endif
458
+ %if WIN64
459
+ %assign %%pad %%pad + 32 ; shadow space
460
+ %if xmm_regs_used > 8
461
+ %assign %%pad %%pad + (xmm_regs_used-8)*16 ; callee-saved xmm registers
462
+ %endif
463
+ %endif
464
+ %if required_stack_alignment <= STACK_ALIGNMENT
465
+ ; maintain the current stack alignment
466
+ %assign stack_size_padded stack_size + %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1))
467
+ PROBE_STACK stack_size_padded
468
+ SUB rsp, stack_size_padded
469
+ %else
470
+ %assign %%reg_num (regs_used - 1)
471
+ %xdefine rstk r %+ %%reg_num
472
+ ; align stack, and save original stack location directly above
473
+ ; it, i.e. in [rsp+stack_size_padded], so we can restore the
474
+ ; stack in a single instruction (i.e. mov rsp, rstk or mov
475
+ ; rsp, [rsp+stack_size_padded])
476
+ %if %1 < 0 ; need to store rsp on stack
477
+ %xdefine rstkm [rsp + stack_size + %%pad]
478
+ %assign %%pad %%pad + gprsize
479
+ %else ; can keep rsp in rstk during whole function
480
+ %xdefine rstkm rstk
481
+ %endif
482
+ %assign stack_size_padded stack_size + ((%%pad + required_stack_alignment-1) & ~(required_stack_alignment-1))
483
+ PROBE_STACK stack_size_padded
484
+ mov rstk, rsp
485
+ and rsp, ~(required_stack_alignment-1)
486
+ sub rsp, stack_size_padded
487
+ movifnidn rstkm, rstk
488
+ %endif
489
+ WIN64_PUSH_XMM
490
+ %endif
491
+ %endif
492
+ %endmacro
493
+
494
+ %macro SETUP_STACK_POINTER 0-1 0
495
+ %ifnum %1
496
+ %if %1 != 0 && required_stack_alignment > STACK_ALIGNMENT
497
+ %if %1 > 0
498
+ ; Reserve an additional register for storing the original stack pointer, but avoid using
499
+ ; eax/rax for this purpose since it can potentially get overwritten as a return value.
500
+ %assign regs_used (regs_used + 1)
501
+ %if ARCH_X86_64 && regs_used == 7
502
+ %assign regs_used 8
503
+ %elif ARCH_X86_64 == 0 && regs_used == 1
504
+ %assign regs_used 2
505
+ %endif
506
+ %endif
507
+ %if ARCH_X86_64 && regs_used < 5 + UNIX64 * 3
508
+ ; Ensure that we don't clobber any registers containing arguments. For UNIX64 we also preserve r6 (rax)
509
+ ; since it's used as a hidden argument in vararg functions to specify the number of vector registers used.
510
+ %assign regs_used 5 + UNIX64 * 3
511
+ %endif
512
+ %endif
513
+ %endif
514
+ %endmacro
515
+
516
+ %if WIN64 ; Windows x64 ;=================================================
517
+
518
+ DECLARE_REG 0, rcx
519
+ DECLARE_REG 1, rdx
520
+ DECLARE_REG 2, R8
521
+ DECLARE_REG 3, R9
522
+ DECLARE_REG 4, R10, 40
523
+ DECLARE_REG 5, R11, 48
524
+ DECLARE_REG 6, rax, 56
525
+ DECLARE_REG 7, rdi, 64
526
+ DECLARE_REG 8, rsi, 72
527
+ DECLARE_REG 9, rbx, 80
528
+ DECLARE_REG 10, rbp, 88
529
+ DECLARE_REG 11, R14, 96
530
+ DECLARE_REG 12, R15, 104
531
+ DECLARE_REG 13, R12, 112
532
+ DECLARE_REG 14, R13, 120
533
+
534
+ %macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names...
535
+ %assign num_args %1
536
+ %assign regs_used %2
537
+ ASSERT regs_used >= num_args
538
+ SETUP_STACK_POINTER %4
539
+ ASSERT regs_used <= 15
540
+ PUSH_IF_USED 7, 8, 9, 10, 11, 12, 13, 14
541
+ ALLOC_STACK %4, %3
542
+ %if mmsize != 8 && stack_size == 0
543
+ WIN64_SPILL_XMM %3
544
+ %endif
545
+ LOAD_IF_USED 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
546
+ %if %0 > 4
547
+ %ifnum %4
548
+ DEFINE_ARGS %5
549
+ %else
550
+ DEFINE_ARGS %4, %5
551
+ %endif
552
+ %elifnnum %4
553
+ DEFINE_ARGS %4
554
+ %endif
555
+ %endmacro
556
+
557
+ ; Push XMM registers to the stack. If no argument is specified all used register
558
+ ; will be pushed, otherwise only push previously unpushed registers.
559
+ %macro WIN64_PUSH_XMM 0-2 ; new_xmm_regs_used, xmm_regs_pushed
560
+ %if mmsize != 8
561
+ %if %0 == 2
562
+ %assign %%pushed %2
563
+ %assign xmm_regs_used %1
564
+ %elif %0 == 1
565
+ %assign %%pushed xmm_regs_used
566
+ %assign xmm_regs_used %1
567
+ %else
568
+ %assign %%pushed 0
569
+ %endif
570
+ ; Use the shadow space to store XMM6 and XMM7, the rest needs stack space allocated.
571
+ %if %%pushed <= 6 + high_mm_regs && xmm_regs_used > 6 + high_mm_regs
572
+ movaps [rstk + stack_offset + 8], xmm6
573
+ %endif
574
+ %if %%pushed <= 7 + high_mm_regs && xmm_regs_used > 7 + high_mm_regs
575
+ movaps [rstk + stack_offset + 24], xmm7
576
+ %endif
577
+ %assign %%pushed %%pushed - high_mm_regs - 8
578
+ %if %%pushed < 0
579
+ %assign %%pushed 0
580
+ %endif
581
+ %assign %%regs_to_push xmm_regs_used - %%pushed - high_mm_regs - 8
582
+ %if %%regs_to_push > 0
583
+ ASSERT (%%regs_to_push + %%pushed) * 16 <= stack_size_padded - stack_size - 32
584
+ %assign %%i %%pushed + 8
585
+ %rep %%regs_to_push
586
+ movaps [rsp + (%%i-8)*16 + stack_size + 32], xmm %+ %%i
587
+ %assign %%i %%i+1
588
+ %endrep
589
+ %endif
590
+ %endif
591
+ %endmacro
592
+
593
+ ; Allocated stack space for XMM registers and push all, or a subset, of those
594
+ %macro WIN64_SPILL_XMM 1-2 ; xmm_regs_used, xmm_regs_reserved
595
+ RESET_STACK_STATE
596
+ %if mmsize != 8
597
+ %assign xmm_regs_used %1
598
+ ASSERT xmm_regs_used <= 16 + high_mm_regs
599
+ %if %0 == 2
600
+ ASSERT %2 >= %1
601
+ %assign %%xmm_regs_on_stack %2 - high_mm_regs - 8
602
+ %else
603
+ %assign %%xmm_regs_on_stack %1 - high_mm_regs - 8
604
+ %endif
605
+ %if %%xmm_regs_on_stack > 0
606
+ ; Allocate stack space for callee-saved xmm registers plus shadow space and align the stack.
607
+ %assign %%pad %%xmm_regs_on_stack*16 + 32
608
+ %assign stack_size_padded %%pad + ((-%%pad-stack_offset-gprsize) & (STACK_ALIGNMENT-1))
609
+ SUB rsp, stack_size_padded
610
+ %endif
611
+ WIN64_PUSH_XMM
612
+ %endif
613
+ %endmacro
614
+
615
+ %macro WIN64_RESTORE_XMM_INTERNAL 0
616
+ %assign %%pad_size 0
617
+ %assign %%xmm_regs_on_stack xmm_regs_used - high_mm_regs - 8
618
+ %if %%xmm_regs_on_stack > 0
619
+ %assign %%i xmm_regs_used - high_mm_regs
620
+ %rep %%xmm_regs_on_stack
621
+ %assign %%i %%i-1
622
+ movaps xmm %+ %%i, [rsp + (%%i-8)*16 + stack_size + 32]
623
+ %endrep
624
+ %endif
625
+ %if stack_size_padded > 0
626
+ %if stack_size > 0 && required_stack_alignment > STACK_ALIGNMENT
627
+ mov rsp, rstkm
628
+ %else
629
+ add rsp, stack_size_padded
630
+ %assign %%pad_size stack_size_padded
631
+ %endif
632
+ %endif
633
+ %if xmm_regs_used > 7 + high_mm_regs
634
+ movaps xmm7, [rsp + stack_offset - %%pad_size + 24]
635
+ %endif
636
+ %if xmm_regs_used > 6 + high_mm_regs
637
+ movaps xmm6, [rsp + stack_offset - %%pad_size + 8]
638
+ %endif
639
+ %endmacro
640
+
641
+ %macro WIN64_RESTORE_XMM 0
642
+ WIN64_RESTORE_XMM_INTERNAL
643
+ RESET_STACK_STATE
644
+ %endmacro
645
+
646
+ %define has_epilogue regs_used > 7 || stack_size > 0 || vzeroupper_required || xmm_regs_used > 6+high_mm_regs
647
+
648
+ %macro RET 0
649
+ WIN64_RESTORE_XMM_INTERNAL
650
+ POP_IF_USED 14, 13, 12, 11, 10, 9, 8, 7
651
+ %if vzeroupper_required
652
+ vzeroupper
653
+ %endif
654
+ AUTO_REP_RET
655
+ %endmacro
656
+
657
+ %elif ARCH_X86_64 ; *nix x64 ;=============================================
658
+
659
+ DECLARE_REG 0, rdi
660
+ DECLARE_REG 1, rsi
661
+ DECLARE_REG 2, rdx
662
+ DECLARE_REG 3, rcx
663
+ DECLARE_REG 4, R8
664
+ DECLARE_REG 5, R9
665
+ DECLARE_REG 6, rax, 8
666
+ DECLARE_REG 7, R10, 16
667
+ DECLARE_REG 8, R11, 24
668
+ DECLARE_REG 9, rbx, 32
669
+ DECLARE_REG 10, rbp, 40
670
+ DECLARE_REG 11, R14, 48
671
+ DECLARE_REG 12, R15, 56
672
+ DECLARE_REG 13, R12, 64
673
+ DECLARE_REG 14, R13, 72
674
+
675
+ %macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names...
676
+ %assign num_args %1
677
+ %assign regs_used %2
678
+ ASSERT regs_used >= num_args
679
+ SETUP_STACK_POINTER %4
680
+ ASSERT regs_used <= 15
681
+ PUSH_IF_USED 9, 10, 11, 12, 13, 14
682
+ ALLOC_STACK %4, %3
683
+ LOAD_IF_USED 6, 7, 8, 9, 10, 11, 12, 13, 14
684
+ %if %0 > 4
685
+ %ifnum %4
686
+ DEFINE_ARGS %5
687
+ %else
688
+ DEFINE_ARGS %4, %5
689
+ %endif
690
+ %elifnnum %4
691
+ DEFINE_ARGS %4
692
+ %endif
693
+ %endmacro
694
+
695
+ %define has_epilogue regs_used > 9 || stack_size > 0 || vzeroupper_required
696
+
697
+ %macro RET 0
698
+ %if stack_size_padded > 0
699
+ %if required_stack_alignment > STACK_ALIGNMENT
700
+ mov rsp, rstkm
701
+ %else
702
+ add rsp, stack_size_padded
703
+ %endif
704
+ %endif
705
+ POP_IF_USED 14, 13, 12, 11, 10, 9
706
+ %if vzeroupper_required
707
+ vzeroupper
708
+ %endif
709
+ AUTO_REP_RET
710
+ %endmacro
711
+
712
+ %else ; X86_32 ;==============================================================
713
+
714
+ DECLARE_REG 0, eax, 4
715
+ DECLARE_REG 1, ecx, 8
716
+ DECLARE_REG 2, edx, 12
717
+ DECLARE_REG 3, ebx, 16
718
+ DECLARE_REG 4, esi, 20
719
+ DECLARE_REG 5, edi, 24
720
+ DECLARE_REG 6, ebp, 28
721
+ %define rsp esp
722
+
723
+ %macro DECLARE_ARG 1-*
724
+ %rep %0
725
+ %define r%1m [rstk + stack_offset + 4*%1 + 4]
726
+ %define r%1mp dword r%1m
727
+ %rotate 1
728
+ %endrep
729
+ %endmacro
730
+
731
+ DECLARE_ARG 7, 8, 9, 10, 11, 12, 13, 14
732
+
733
+ %macro PROLOGUE 2-5+ 0, 0 ; #args, #regs, #xmm_regs, [stack_size,] arg_names...
734
+ %assign num_args %1
735
+ %assign regs_used %2
736
+ ASSERT regs_used >= num_args
737
+ %if num_args > 7
738
+ %assign num_args 7
739
+ %endif
740
+ %if regs_used > 7
741
+ %assign regs_used 7
742
+ %endif
743
+ SETUP_STACK_POINTER %4
744
+ ASSERT regs_used <= 7
745
+ PUSH_IF_USED 3, 4, 5, 6
746
+ ALLOC_STACK %4, %3
747
+ LOAD_IF_USED 0, 1, 2, 3, 4, 5, 6
748
+ %if %0 > 4
749
+ %ifnum %4
750
+ DEFINE_ARGS %5
751
+ %else
752
+ DEFINE_ARGS %4, %5
753
+ %endif
754
+ %elifnnum %4
755
+ DEFINE_ARGS %4
756
+ %endif
757
+ %endmacro
758
+
759
+ %define has_epilogue regs_used > 3 || stack_size > 0 || vzeroupper_required
760
+
761
+ %macro RET 0
762
+ %if stack_size_padded > 0
763
+ %if required_stack_alignment > STACK_ALIGNMENT
764
+ mov rsp, rstkm
765
+ %else
766
+ add rsp, stack_size_padded
767
+ %endif
768
+ %endif
769
+ POP_IF_USED 6, 5, 4, 3
770
+ %if vzeroupper_required
771
+ vzeroupper
772
+ %endif
773
+ AUTO_REP_RET
774
+ %endmacro
775
+
776
+ %endif ;======================================================================
777
+
778
+ %if WIN64 == 0
779
+ %macro WIN64_SPILL_XMM 1-2
780
+ RESET_STACK_STATE
781
+ %if mmsize != 8
782
+ %assign xmm_regs_used %1
783
+ %endif
784
+ %endmacro
785
+ %macro WIN64_RESTORE_XMM 0
786
+ RESET_STACK_STATE
787
+ %endmacro
788
+ %macro WIN64_PUSH_XMM 0-2
789
+ %if mmsize != 8 && %0 >= 1
790
+ %assign xmm_regs_used %1
791
+ %endif
792
+ %endmacro
793
+ %endif
794
+
795
+ ; On AMD cpus <=K10, an ordinary ret is slow if it immediately follows either
796
+ ; a branch or a branch target. So switch to a 2-byte form of ret in that case.
797
+ ; We can automatically detect "follows a branch", but not a branch target.
798
+ ; (SSSE3 is a sufficient condition to know that your cpu doesn't have this problem.)
799
+ %macro REP_RET 0
800
+ %if has_epilogue || cpuflag(ssse3)
801
+ RET
802
+ %else
803
+ rep ret
804
+ %endif
805
+ annotate_function_size
806
+ %endmacro
807
+
808
+ %define last_branch_adr $$
809
+ %macro AUTO_REP_RET 0
810
+ %if notcpuflag(ssse3)
811
+ times ((last_branch_adr-$)>>31)+1 rep ; times 1 iff $ == last_branch_adr.
812
+ %endif
813
+ ret
814
+ annotate_function_size
815
+ %endmacro
816
+
817
+ %macro BRANCH_INSTR 0-*
818
+ %rep %0
819
+ %macro %1 1-2 %1
820
+ %2 %1
821
+ %if notcpuflag(ssse3)
822
+ %%branch_instr equ $
823
+ %xdefine last_branch_adr %%branch_instr
824
+ %endif
825
+ %endmacro
826
+ %rotate 1
827
+ %endrep
828
+ %endmacro
829
+
830
+ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, jna, jnae, jb, jbe, jnb, jnbe, jc, jnc, js, jns, jo, jno, jp, jnp
831
+
832
+ %macro TAIL_CALL 1-2 1 ; callee, is_nonadjacent
833
+ %if has_epilogue
834
+ call %1
835
+ RET
836
+ %elif %2
837
+ jmp %1
838
+ %endif
839
+ annotate_function_size
840
+ %endmacro
841
+
842
+ ;=============================================================================
843
+ ; arch-independent part
844
+ ;=============================================================================
845
+
846
+ %assign function_align 16
847
+
848
+ ; Begin a function.
849
+ ; Applies any symbol mangling needed for C linkage, and sets up a define such that
850
+ ; subsequent uses of the function name automatically refer to the mangled version.
851
+ ; Appends cpuflags to the function name if cpuflags has been specified.
852
+ ; The "" empty default parameter is a workaround for nasm, which fails if SUFFIX
853
+ ; is empty and we call cglobal_internal with just %1 %+ SUFFIX (without %2).
854
+ %macro cglobal 1-2+ "" ; name, [PROLOGUE args]
855
+ cglobal_internal 1, %1 %+ SUFFIX, %2
856
+ %endmacro
857
+ %macro cvisible 1-2+ "" ; name, [PROLOGUE args]
858
+ cglobal_internal 0, %1 %+ SUFFIX, %2
859
+ %endmacro
860
+ %macro cglobal_internal 2-3+
861
+ annotate_function_size
862
+ %ifndef cglobaled_%2
863
+ %if %1
864
+ %xdefine %2 mangle(private_prefix %+ _ %+ %2)
865
+ %else
866
+ %xdefine %2 mangle(public_prefix %+ _ %+ %2)
867
+ %endif
868
+ %xdefine %2.skip_prologue %2 %+ .skip_prologue
869
+ CAT_XDEFINE cglobaled_, %2, 1
870
+ %endif
871
+ %xdefine current_function %2
872
+ %xdefine current_function_section __SECT__
873
+ %if FORMAT_ELF
874
+ %if %1
875
+ global %2:function hidden
876
+ %else
877
+ global %2:function
878
+ %endif
879
+ %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN && %1
880
+ global %2:private_extern
881
+ %else
882
+ global %2
883
+ %endif
884
+ %if WIN32 && !%1
885
+ %ifdef BUILDING_DLL
886
+ export %2
887
+ %endif
888
+ %elif FORMAT_OBJ && !%1
889
+ export %2
890
+ %endif
891
+ align function_align
892
+ %2:
893
+ RESET_MM_PERMUTATION ; needed for x86-64, also makes disassembly somewhat nicer
894
+ %xdefine rstk rsp ; copy of the original stack pointer, used when greater alignment than the known stack alignment is required
895
+ %assign stack_offset 0 ; stack pointer offset relative to the return address
896
+ %assign stack_size 0 ; amount of stack space that can be freely used inside a function
897
+ %assign stack_size_padded 0 ; total amount of allocated stack space, including space for callee-saved xmm registers on WIN64 and alignment padding
898
+ %assign xmm_regs_used 0 ; number of XMM registers requested, used for dealing with callee-saved registers on WIN64 and vzeroupper
899
+ %ifnidn %3, ""
900
+ PROLOGUE %3
901
+ %endif
902
+ %endmacro
903
+
904
+ ; Create a global symbol from a local label with the correct name mangling and type
905
+ %macro cglobal_label 1
906
+ %if FORMAT_ELF
907
+ global current_function %+ %1:function hidden
908
+ %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN
909
+ global current_function %+ %1:private_extern
910
+ %else
911
+ global current_function %+ %1
912
+ %endif
913
+ %1:
914
+ %endmacro
915
+
916
+ %macro cextern 1
917
+ %xdefine %1 mangle(private_prefix %+ _ %+ %1)
918
+ CAT_XDEFINE cglobaled_, %1, 2
919
+ extern %1
920
+ %endmacro
921
+
922
+ ; Like cextern, but without the prefix. This should be used for symbols from external libraries.
923
+ %macro cextern_naked 1
924
+ %ifdef PREFIX
925
+ %xdefine %1 mangle(%1)
926
+ %endif
927
+ CAT_XDEFINE cglobaled_, %1, 3
928
+ extern %1
929
+ %endmacro
930
+
931
+ %macro const 1-2+
932
+ %xdefine %1 mangle(private_prefix %+ _ %+ %1)
933
+ %if FORMAT_ELF
934
+ global %1:data hidden
935
+ %elif FORMAT_MACHO && HAVE_PRIVATE_EXTERN
936
+ global %1:private_extern
937
+ %else
938
+ global %1
939
+ %endif
940
+ %1: %2
941
+ %endmacro
942
+
943
+ %if FORMAT_ELF
944
+ ; The GNU linker assumes the stack is executable by default.
945
+ [SECTION .note.GNU-stack noalloc noexec nowrite progbits]
946
+
947
+ %ifdef __NASM_VERSION_ID__
948
+ %if __NASM_VERSION_ID__ >= 0x020e0300 ; 2.14.03
949
+ %if ARCH_X86_64
950
+ ; Control-flow Enforcement Technology (CET) properties.
951
+ [SECTION .note.gnu.property alloc noexec nowrite note align=gprsize]
952
+ dd 0x00000004 ; n_namesz
953
+ dd gprsize + 8 ; n_descsz
954
+ dd 0x00000005 ; n_type = NT_GNU_PROPERTY_TYPE_0
955
+ db "GNU",0 ; n_name
956
+ dd 0xc0000002 ; pr_type = GNU_PROPERTY_X86_FEATURE_1_AND
957
+ dd 0x00000004 ; pr_datasz
958
+ dd 0x00000002 ; pr_data = GNU_PROPERTY_X86_FEATURE_1_SHSTK
959
+ dd 0x00000000 ; pr_padding
960
+ %endif
961
+ %endif
962
+ %endif
963
+ %endif
964
+
965
+ ; Tell debuggers how large the function was.
966
+ ; This may be invoked multiple times per function; we rely on later instances overriding earlier ones.
967
+ ; This is invoked by RET and similar macros, and also cglobal does it for the previous function,
968
+ ; but if the last function in a source file doesn't use any of the standard macros for its epilogue,
969
+ ; then its size might be unspecified.
970
+ %macro annotate_function_size 0
971
+ %ifdef __YASM_VER__
972
+ %ifdef current_function
973
+ %if FORMAT_ELF
974
+ current_function_section
975
+ %%ecf equ $
976
+ size current_function %%ecf - current_function
977
+ __SECT__
978
+ %endif
979
+ %endif
980
+ %endif
981
+ %endmacro
982
+
983
+ ; cpuflags
984
+
985
+ %assign cpuflags_mmx (1<<0)
986
+ %assign cpuflags_mmx2 (1<<1) | cpuflags_mmx
987
+ %assign cpuflags_3dnow (1<<2) | cpuflags_mmx
988
+ %assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow
989
+ %assign cpuflags_sse (1<<4) | cpuflags_mmx2
990
+ %assign cpuflags_sse2 (1<<5) | cpuflags_sse
991
+ %assign cpuflags_sse2slow (1<<6) | cpuflags_sse2
992
+ %assign cpuflags_lzcnt (1<<7) | cpuflags_sse2
993
+ %assign cpuflags_sse3 (1<<8) | cpuflags_sse2
994
+ %assign cpuflags_ssse3 (1<<9) | cpuflags_sse3
995
+ %assign cpuflags_sse4 (1<<10) | cpuflags_ssse3
996
+ %assign cpuflags_sse42 (1<<11) | cpuflags_sse4
997
+ %assign cpuflags_aesni (1<<12) | cpuflags_sse42
998
+ %assign cpuflags_clmul (1<<13) | cpuflags_sse42
999
+ %assign cpuflags_gfni (1<<14) | cpuflags_aesni|cpuflags_clmul
1000
+ %assign cpuflags_avx (1<<15) | cpuflags_sse42
1001
+ %assign cpuflags_xop (1<<16) | cpuflags_avx
1002
+ %assign cpuflags_fma4 (1<<17) | cpuflags_avx
1003
+ %assign cpuflags_fma3 (1<<18) | cpuflags_avx
1004
+ %assign cpuflags_bmi1 (1<<19) | cpuflags_avx|cpuflags_lzcnt
1005
+ %assign cpuflags_bmi2 (1<<20) | cpuflags_bmi1
1006
+ %assign cpuflags_avx2 (1<<21) | cpuflags_fma3|cpuflags_bmi2
1007
+ %assign cpuflags_avx512 (1<<22) | cpuflags_avx2 ; F, CD, BW, DQ, VL
1008
+ %assign cpuflags_avx512icl (1<<23) | cpuflags_avx512|cpuflags_gfni ; VNNI, IFMA, VBMI, VBMI2, VPOPCNTDQ, BITALG, VAES, VPCLMULQDQ
1009
+
1010
+ %assign cpuflags_cache32 (1<<24)
1011
+ %assign cpuflags_cache64 (1<<25)
1012
+ %assign cpuflags_aligned (1<<26) ; not a cpu feature, but a function variant
1013
+ %assign cpuflags_atom (1<<27)
1014
+
1015
+ ; Returns a boolean value expressing whether or not the specified cpuflag is enabled.
1016
+ %define cpuflag(x) (((((cpuflags & (cpuflags_ %+ x)) ^ (cpuflags_ %+ x)) - 1) >> 31) & 1)
1017
+ %define notcpuflag(x) (cpuflag(x) ^ 1)
1018
+
1019
+ ; Takes an arbitrary number of cpuflags from the above list.
1020
+ ; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu.
1021
+ ; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co.
1022
+ %macro INIT_CPUFLAGS 0-*
1023
+ %xdefine SUFFIX
1024
+ %undef cpuname
1025
+ %assign cpuflags 0
1026
+
1027
+ %if %0 >= 1
1028
+ %rep %0
1029
+ %ifdef cpuname
1030
+ %xdefine cpuname cpuname %+ _%1
1031
+ %else
1032
+ %xdefine cpuname %1
1033
+ %endif
1034
+ %assign cpuflags cpuflags | cpuflags_%1
1035
+ %rotate 1
1036
+ %endrep
1037
+ %xdefine SUFFIX _ %+ cpuname
1038
+
1039
+ %if cpuflag(avx)
1040
+ %assign avx_enabled 1
1041
+ %endif
1042
+ %if (mmsize == 16 && notcpuflag(sse2)) || (mmsize == 32 && notcpuflag(avx2))
1043
+ %define mova movaps
1044
+ %define movu movups
1045
+ %define movnta movntps
1046
+ %endif
1047
+ %if cpuflag(aligned)
1048
+ %define movu mova
1049
+ %elif cpuflag(sse3) && notcpuflag(ssse3)
1050
+ %define movu lddqu
1051
+ %endif
1052
+ %endif
1053
+
1054
+ %if ARCH_X86_64 || cpuflag(sse2)
1055
+ %ifdef __NASM_VERSION_ID__
1056
+ ALIGNMODE p6
1057
+ %else
1058
+ CPU amdnop
1059
+ %endif
1060
+ %else
1061
+ %ifdef __NASM_VERSION_ID__
1062
+ ALIGNMODE nop
1063
+ %else
1064
+ CPU basicnop
1065
+ %endif
1066
+ %endif
1067
+ %endmacro
1068
+
1069
+ ; Merge mmx, sse*, and avx*
1070
+ ; m# is a simd register of the currently selected size
1071
+ ; xm# is the corresponding xmm register if mmsize >= 16, otherwise the same as m#
1072
+ ; ym# is the corresponding ymm register if mmsize >= 32, otherwise the same as m#
1073
+ ; zm# is the corresponding zmm register if mmsize >= 64, otherwise the same as m#
1074
+ ; (All 4 remain in sync through SWAP.)
1075
+
1076
+ %macro CAT_XDEFINE 3
1077
+ %xdefine %1%2 %3
1078
+ %endmacro
1079
+
1080
+ %macro CAT_UNDEF 2
1081
+ %undef %1%2
1082
+ %endmacro
1083
+
1084
+ %macro DEFINE_MMREGS 1 ; mmtype
1085
+ %assign %%prev_mmregs 0
1086
+ %ifdef num_mmregs
1087
+ %assign %%prev_mmregs num_mmregs
1088
+ %endif
1089
+
1090
+ %assign num_mmregs 8
1091
+ %if ARCH_X86_64 && mmsize >= 16
1092
+ %assign num_mmregs 16
1093
+ %if cpuflag(avx512) || mmsize == 64
1094
+ %assign num_mmregs 32
1095
+ %endif
1096
+ %endif
1097
+
1098
+ %assign %%i 0
1099
+ %rep num_mmregs
1100
+ CAT_XDEFINE m, %%i, %1 %+ %%i
1101
+ CAT_XDEFINE nn%1, %%i, %%i
1102
+ %assign %%i %%i+1
1103
+ %endrep
1104
+ %if %%prev_mmregs > num_mmregs
1105
+ %rep %%prev_mmregs - num_mmregs
1106
+ CAT_UNDEF m, %%i
1107
+ CAT_UNDEF nn %+ mmtype, %%i
1108
+ %assign %%i %%i+1
1109
+ %endrep
1110
+ %endif
1111
+ %xdefine mmtype %1
1112
+ %endmacro
1113
+
1114
+ ; Prefer registers 16-31 over 0-15 to avoid having to use vzeroupper
1115
+ %macro AVX512_MM_PERMUTATION 0-1 0 ; start_reg
1116
+ %if ARCH_X86_64 && cpuflag(avx512)
1117
+ %assign %%i %1
1118
+ %rep 16-%1
1119
+ %assign %%i_high %%i+16
1120
+ SWAP %%i, %%i_high
1121
+ %assign %%i %%i+1
1122
+ %endrep
1123
+ %endif
1124
+ %endmacro
1125
+
1126
+ %macro INIT_MMX 0-1+
1127
+ %assign avx_enabled 0
1128
+ %define RESET_MM_PERMUTATION INIT_MMX %1
1129
+ %define mmsize 8
1130
+ %define mova movq
1131
+ %define movu movq
1132
+ %define movh movd
1133
+ %define movnta movntq
1134
+ INIT_CPUFLAGS %1
1135
+ DEFINE_MMREGS mm
1136
+ %endmacro
1137
+
1138
+ %macro INIT_XMM 0-1+
1139
+ %assign avx_enabled FORCE_VEX_ENCODING
1140
+ %define RESET_MM_PERMUTATION INIT_XMM %1
1141
+ %define mmsize 16
1142
+ %define mova movdqa
1143
+ %define movu movdqu
1144
+ %define movh movq
1145
+ %define movnta movntdq
1146
+ INIT_CPUFLAGS %1
1147
+ DEFINE_MMREGS xmm
1148
+ %if WIN64
1149
+ AVX512_MM_PERMUTATION 6 ; Swap callee-saved registers with volatile registers
1150
+ %endif
1151
+ %xdefine bcstw 1to8
1152
+ %xdefine bcstd 1to4
1153
+ %xdefine bcstq 1to2
1154
+ %endmacro
1155
+
1156
+ %macro INIT_YMM 0-1+
1157
+ %assign avx_enabled 1
1158
+ %define RESET_MM_PERMUTATION INIT_YMM %1
1159
+ %define mmsize 32
1160
+ %define mova movdqa
1161
+ %define movu movdqu
1162
+ %undef movh
1163
+ %define movnta movntdq
1164
+ INIT_CPUFLAGS %1
1165
+ DEFINE_MMREGS ymm
1166
+ AVX512_MM_PERMUTATION
1167
+ %xdefine bcstw 1to16
1168
+ %xdefine bcstd 1to8
1169
+ %xdefine bcstq 1to4
1170
+ %endmacro
1171
+
1172
+ %macro INIT_ZMM 0-1+
1173
+ %assign avx_enabled 1
1174
+ %define RESET_MM_PERMUTATION INIT_ZMM %1
1175
+ %define mmsize 64
1176
+ %define mova movdqa
1177
+ %define movu movdqu
1178
+ %undef movh
1179
+ %define movnta movntdq
1180
+ INIT_CPUFLAGS %1
1181
+ DEFINE_MMREGS zmm
1182
+ AVX512_MM_PERMUTATION
1183
+ %xdefine bcstw 1to32
1184
+ %xdefine bcstd 1to16
1185
+ %xdefine bcstq 1to8
1186
+ %endmacro
1187
+
1188
+ INIT_XMM
1189
+
1190
+ %macro DECLARE_MMCAST 1
1191
+ %define mmmm%1 mm%1
1192
+ %define mmxmm%1 mm%1
1193
+ %define mmymm%1 mm%1
1194
+ %define mmzmm%1 mm%1
1195
+ %define xmmmm%1 mm%1
1196
+ %define xmmxmm%1 xmm%1
1197
+ %define xmmymm%1 xmm%1
1198
+ %define xmmzmm%1 xmm%1
1199
+ %define ymmmm%1 mm%1
1200
+ %define ymmxmm%1 xmm%1
1201
+ %define ymmymm%1 ymm%1
1202
+ %define ymmzmm%1 ymm%1
1203
+ %define zmmmm%1 mm%1
1204
+ %define zmmxmm%1 xmm%1
1205
+ %define zmmymm%1 ymm%1
1206
+ %define zmmzmm%1 zmm%1
1207
+ %define xm%1 xmm %+ m%1
1208
+ %define ym%1 ymm %+ m%1
1209
+ %define zm%1 zmm %+ m%1
1210
+ %endmacro
1211
+
1212
+ %assign i 0
1213
+ %rep 32
1214
+ DECLARE_MMCAST i
1215
+ %assign i i+1
1216
+ %endrep
1217
+
1218
+ ; I often want to use macros that permute their arguments. e.g. there's no
1219
+ ; efficient way to implement butterfly or transpose or dct without swapping some
1220
+ ; arguments.
1221
+ ;
1222
+ ; I would like to not have to manually keep track of the permutations:
1223
+ ; If I insert a permutation in the middle of a function, it should automatically
1224
+ ; change everything that follows. For more complex macros I may also have multiple
1225
+ ; implementations, e.g. the SSE2 and SSSE3 versions may have different permutations.
1226
+ ;
1227
+ ; Hence these macros. Insert a PERMUTE or some SWAPs at the end of a macro that
1228
+ ; permutes its arguments. It's equivalent to exchanging the contents of the
1229
+ ; registers, except that this way you exchange the register names instead, so it
1230
+ ; doesn't cost any cycles.
1231
+
1232
+ %macro PERMUTE 2-* ; takes a list of pairs to swap
1233
+ %rep %0/2
1234
+ %xdefine %%tmp%2 m%2
1235
+ %rotate 2
1236
+ %endrep
1237
+ %rep %0/2
1238
+ %xdefine m%1 %%tmp%2
1239
+ CAT_XDEFINE nn, m%1, %1
1240
+ %rotate 2
1241
+ %endrep
1242
+ %endmacro
1243
+
1244
+ %macro SWAP 2+ ; swaps a single chain (sometimes more concise than pairs)
1245
+ %ifnum %1 ; SWAP 0, 1, ...
1246
+ SWAP_INTERNAL_NUM %1, %2
1247
+ %else ; SWAP m0, m1, ...
1248
+ SWAP_INTERNAL_NAME %1, %2
1249
+ %endif
1250
+ %endmacro
1251
+
1252
+ %macro SWAP_INTERNAL_NUM 2-*
1253
+ %rep %0-1
1254
+ %xdefine %%tmp m%1
1255
+ %xdefine m%1 m%2
1256
+ %xdefine m%2 %%tmp
1257
+ CAT_XDEFINE nn, m%1, %1
1258
+ CAT_XDEFINE nn, m%2, %2
1259
+ %rotate 1
1260
+ %endrep
1261
+ %endmacro
1262
+
1263
+ %macro SWAP_INTERNAL_NAME 2-*
1264
+ %xdefine %%args nn %+ %1
1265
+ %rep %0-1
1266
+ %xdefine %%args %%args, nn %+ %2
1267
+ %rotate 1
1268
+ %endrep
1269
+ SWAP_INTERNAL_NUM %%args
1270
+ %endmacro
1271
+
1272
+ ; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later
1273
+ ; calls to that function will automatically load the permutation, so values can
1274
+ ; be returned in mmregs.
1275
+ %macro SAVE_MM_PERMUTATION 0-1
1276
+ %if %0
1277
+ %xdefine %%f %1_m
1278
+ %else
1279
+ %xdefine %%f current_function %+ _m
1280
+ %endif
1281
+ %assign %%i 0
1282
+ %rep num_mmregs
1283
+ %xdefine %%tmp m %+ %%i
1284
+ CAT_XDEFINE %%f, %%i, regnumof %+ %%tmp
1285
+ %assign %%i %%i+1
1286
+ %endrep
1287
+ %endmacro
1288
+
1289
+ %macro LOAD_MM_PERMUTATION 0-1 ; name to load from
1290
+ %if %0
1291
+ %xdefine %%f %1_m
1292
+ %else
1293
+ %xdefine %%f current_function %+ _m
1294
+ %endif
1295
+ %xdefine %%tmp %%f %+ 0
1296
+ %ifnum %%tmp
1297
+ DEFINE_MMREGS mmtype
1298
+ %assign %%i 0
1299
+ %rep num_mmregs
1300
+ %xdefine %%tmp %%f %+ %%i
1301
+ CAT_XDEFINE %%m, %%i, m %+ %%tmp
1302
+ %assign %%i %%i+1
1303
+ %endrep
1304
+ %rep num_mmregs
1305
+ %assign %%i %%i-1
1306
+ CAT_XDEFINE m, %%i, %%m %+ %%i
1307
+ CAT_XDEFINE nn, m %+ %%i, %%i
1308
+ %endrep
1309
+ %endif
1310
+ %endmacro
1311
+
1312
+ ; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't
1313
+ %macro call 1
1314
+ %ifid %1
1315
+ call_internal %1 %+ SUFFIX, %1
1316
+ %else
1317
+ call %1
1318
+ %endif
1319
+ %endmacro
1320
+ %macro call_internal 2
1321
+ %xdefine %%i %2
1322
+ %define %%j %%i
1323
+ %ifndef cglobaled_%2
1324
+ %ifdef cglobaled_%1
1325
+ %xdefine %%i %1
1326
+ %endif
1327
+ %elif FORMAT_ELF
1328
+ %if ARCH_X86_64
1329
+ %if cglobaled_%2 >= 2
1330
+ ; Always emit PLT relocations when calling external functions,
1331
+ ; the linker will eliminate unnecessary PLT indirections anyway.
1332
+ %define %%j %%i wrt ..plt
1333
+ %endif
1334
+ %elif PIC && cglobaled_%2 == 3
1335
+ ; Go through the GOT for functions declared using cextern_naked with
1336
+ ; PIC, as such functions presumably exists in external libraries.
1337
+ extern _GLOBAL_OFFSET_TABLE_
1338
+ LEA eax, $$+_GLOBAL_OFFSET_TABLE_ wrt ..gotpc
1339
+ %define %%j [eax+%%i wrt ..got]
1340
+ %endif
1341
+ %endif
1342
+ call %%j
1343
+ LOAD_MM_PERMUTATION %%i
1344
+ %endmacro
1345
+
1346
+ ; Substitutions that reduce instruction size but are functionally equivalent
1347
+ %macro add 2
1348
+ %ifnum %2
1349
+ %if %2==128
1350
+ sub %1, -128
1351
+ %else
1352
+ add %1, %2
1353
+ %endif
1354
+ %else
1355
+ add %1, %2
1356
+ %endif
1357
+ %endmacro
1358
+
1359
+ %macro sub 2
1360
+ %ifnum %2
1361
+ %if %2==128
1362
+ add %1, -128
1363
+ %else
1364
+ sub %1, %2
1365
+ %endif
1366
+ %else
1367
+ sub %1, %2
1368
+ %endif
1369
+ %endmacro
1370
+
1371
+ ;=============================================================================
1372
+ ; AVX abstraction layer
1373
+ ;=============================================================================
1374
+
1375
+ %assign i 0
1376
+ %rep 32
1377
+ %if i < 8
1378
+ CAT_XDEFINE sizeofmm, i, 8
1379
+ CAT_XDEFINE regnumofmm, i, i
1380
+ %endif
1381
+ CAT_XDEFINE sizeofxmm, i, 16
1382
+ CAT_XDEFINE sizeofymm, i, 32
1383
+ CAT_XDEFINE sizeofzmm, i, 64
1384
+ CAT_XDEFINE regnumofxmm, i, i
1385
+ CAT_XDEFINE regnumofymm, i, i
1386
+ CAT_XDEFINE regnumofzmm, i, i
1387
+ %assign i i+1
1388
+ %endrep
1389
+ %undef i
1390
+
1391
+ %macro CHECK_AVX_INSTR_EMU 3-*
1392
+ %xdefine %%opcode %1
1393
+ %xdefine %%dst %2
1394
+ %rep %0-2
1395
+ %ifidn %%dst, %3
1396
+ %error non-avx emulation of ``%%opcode'' is not supported
1397
+ %endif
1398
+ %rotate 1
1399
+ %endrep
1400
+ %endmacro
1401
+
1402
+ ;%1 == instruction
1403
+ ;%2 == minimal instruction set
1404
+ ;%3 == 1 if float, 0 if int
1405
+ ;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation)
1406
+ ;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not
1407
+ ;%6+: operands
1408
+ %macro RUN_AVX_INSTR 6-9+
1409
+ %ifnum sizeof%7
1410
+ %assign __sizeofreg sizeof%7
1411
+ %elifnum sizeof%6
1412
+ %assign __sizeofreg sizeof%6
1413
+ %else
1414
+ %assign __sizeofreg mmsize
1415
+ %endif
1416
+ %assign __emulate_avx 0
1417
+ %if avx_enabled && __sizeofreg >= 16
1418
+ %xdefine __instr v%1
1419
+ %else
1420
+ %xdefine __instr %1
1421
+ %if %0 >= 8+%4
1422
+ %assign __emulate_avx 1
1423
+ %endif
1424
+ %endif
1425
+ %ifnidn %2, fnord
1426
+ %ifdef cpuname
1427
+ %if notcpuflag(%2)
1428
+ %error use of ``%1'' %2 instruction in cpuname function: current_function
1429
+ %elif %3 == 0 && __sizeofreg == 16 && notcpuflag(sse2)
1430
+ %error use of ``%1'' sse2 instruction in cpuname function: current_function
1431
+ %elif %3 == 0 && __sizeofreg == 32 && notcpuflag(avx2)
1432
+ %error use of ``%1'' avx2 instruction in cpuname function: current_function
1433
+ %elif __sizeofreg == 16 && notcpuflag(sse)
1434
+ %error use of ``%1'' sse instruction in cpuname function: current_function
1435
+ %elif __sizeofreg == 32 && notcpuflag(avx)
1436
+ %error use of ``%1'' avx instruction in cpuname function: current_function
1437
+ %elif __sizeofreg == 64 && notcpuflag(avx512)
1438
+ %error use of ``%1'' avx512 instruction in cpuname function: current_function
1439
+ %elifidn %1, pextrw ; special case because the base instruction is mmx2,
1440
+ %ifnid %6 ; but sse4 is required for memory operands
1441
+ %if notcpuflag(sse4)
1442
+ %error use of ``%1'' sse4 instruction in cpuname function: current_function
1443
+ %endif
1444
+ %endif
1445
+ %endif
1446
+ %endif
1447
+ %endif
1448
+
1449
+ %if __emulate_avx
1450
+ %xdefine __src1 %7
1451
+ %xdefine __src2 %8
1452
+ %if %5 && %4 == 0
1453
+ %ifnidn %6, %7
1454
+ %ifidn %6, %8
1455
+ %xdefine __src1 %8
1456
+ %xdefine __src2 %7
1457
+ %elifnnum sizeof%8
1458
+ ; 3-operand AVX instructions with a memory arg can only have it in src2,
1459
+ ; whereas SSE emulation prefers to have it in src1 (i.e. the mov).
1460
+ ; So, if the instruction is commutative with a memory arg, swap them.
1461
+ %xdefine __src1 %8
1462
+ %xdefine __src2 %7
1463
+ %endif
1464
+ %endif
1465
+ %endif
1466
+ %ifnidn %6, __src1
1467
+ %if %0 >= 9
1468
+ CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, __src2, %9
1469
+ %else
1470
+ CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, __src2
1471
+ %endif
1472
+ %if __sizeofreg == 8
1473
+ MOVQ %6, __src1
1474
+ %elif %3
1475
+ MOVAPS %6, __src1
1476
+ %else
1477
+ MOVDQA %6, __src1
1478
+ %endif
1479
+ %endif
1480
+ %if %0 >= 9
1481
+ %1 %6, __src2, %9
1482
+ %else
1483
+ %1 %6, __src2
1484
+ %endif
1485
+ %elif %0 >= 9
1486
+ %if avx_enabled && __sizeofreg >= 16 && %4 == 1
1487
+ %ifnnum regnumof%7
1488
+ %if %3
1489
+ vmovaps %6, %7
1490
+ %else
1491
+ vmovdqa %6, %7
1492
+ %endif
1493
+ __instr %6, %6, %8, %9
1494
+ %else
1495
+ __instr %6, %7, %8, %9
1496
+ %endif
1497
+ %else
1498
+ __instr %6, %7, %8, %9
1499
+ %endif
1500
+ %elif %0 == 8
1501
+ %if avx_enabled && __sizeofreg >= 16 && %4 == 0
1502
+ %xdefine __src1 %7
1503
+ %xdefine __src2 %8
1504
+ %if %5
1505
+ %ifnum regnumof%7
1506
+ %ifnum regnumof%8
1507
+ %if regnumof%7 < 8 && regnumof%8 >= 8 && regnumof%8 < 16 && sizeof%8 <= 32
1508
+ ; Most VEX-encoded instructions require an additional byte to encode when
1509
+ ; src2 is a high register (e.g. m8..15). If the instruction is commutative
1510
+ ; we can swap src1 and src2 when doing so reduces the instruction length.
1511
+ %xdefine __src1 %8
1512
+ %xdefine __src2 %7
1513
+ %endif
1514
+ %endif
1515
+ %elifnum regnumof%8 ; put memory operands in src2 when possible
1516
+ %xdefine __src1 %8
1517
+ %xdefine __src2 %7
1518
+ %else
1519
+ %assign __emulate_avx 1
1520
+ %endif
1521
+ %elifnnum regnumof%7
1522
+ ; EVEX allows imm8 shift instructions to be used with memory operands,
1523
+ ; but VEX does not. This handles those special cases.
1524
+ %ifnnum %8
1525
+ %assign __emulate_avx 1
1526
+ %elif notcpuflag(avx512)
1527
+ %assign __emulate_avx 1
1528
+ %endif
1529
+ %endif
1530
+ %if __emulate_avx ; a separate load is required
1531
+ %if %3
1532
+ vmovaps %6, %7
1533
+ %else
1534
+ vmovdqa %6, %7
1535
+ %endif
1536
+ __instr %6, %6, %8
1537
+ %else
1538
+ __instr %6, __src1, __src2
1539
+ %endif
1540
+ %else
1541
+ __instr %6, %7, %8
1542
+ %endif
1543
+ %elif %0 == 7
1544
+ %if avx_enabled && __sizeofreg >= 16 && %5
1545
+ %xdefine __src1 %6
1546
+ %xdefine __src2 %7
1547
+ %ifnum regnumof%6
1548
+ %ifnum regnumof%7
1549
+ %if regnumof%6 < 8 && regnumof%7 >= 8 && regnumof%7 < 16 && sizeof%7 <= 32
1550
+ %xdefine __src1 %7
1551
+ %xdefine __src2 %6
1552
+ %endif
1553
+ %endif
1554
+ %endif
1555
+ __instr %6, __src1, __src2
1556
+ %else
1557
+ __instr %6, %7
1558
+ %endif
1559
+ %else
1560
+ __instr %6
1561
+ %endif
1562
+ %endmacro
1563
+
1564
+ ;%1 == instruction
1565
+ ;%2 == minimal instruction set
1566
+ ;%3 == 1 if float, 0 if int
1567
+ ;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation)
1568
+ ;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not
1569
+ %macro AVX_INSTR 1-5 fnord, 0, 255, 0
1570
+ %macro %1 1-10 fnord, fnord, fnord, fnord, %1, %2, %3, %4, %5
1571
+ %ifidn %2, fnord
1572
+ RUN_AVX_INSTR %6, %7, %8, %9, %10, %1
1573
+ %elifidn %3, fnord
1574
+ RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2
1575
+ %elifidn %4, fnord
1576
+ RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3
1577
+ %elifidn %5, fnord
1578
+ RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4
1579
+ %else
1580
+ RUN_AVX_INSTR %6, %7, %8, %9, %10, %1, %2, %3, %4, %5
1581
+ %endif
1582
+ %endmacro
1583
+ %endmacro
1584
+
1585
+ ; Instructions with both VEX/EVEX and legacy encodings
1586
+ ; Non-destructive instructions are written without parameters
1587
+ AVX_INSTR addpd, sse2, 1, 0, 1
1588
+ AVX_INSTR addps, sse, 1, 0, 1
1589
+ AVX_INSTR addsd, sse2, 1, 0, 0
1590
+ AVX_INSTR addss, sse, 1, 0, 0
1591
+ AVX_INSTR addsubpd, sse3, 1, 0, 0
1592
+ AVX_INSTR addsubps, sse3, 1, 0, 0
1593
+ AVX_INSTR aesdec, aesni, 0, 0, 0
1594
+ AVX_INSTR aesdeclast, aesni, 0, 0, 0
1595
+ AVX_INSTR aesenc, aesni, 0, 0, 0
1596
+ AVX_INSTR aesenclast, aesni, 0, 0, 0
1597
+ AVX_INSTR aesimc, aesni
1598
+ AVX_INSTR aeskeygenassist, aesni
1599
+ AVX_INSTR andnpd, sse2, 1, 0, 0
1600
+ AVX_INSTR andnps, sse, 1, 0, 0
1601
+ AVX_INSTR andpd, sse2, 1, 0, 1
1602
+ AVX_INSTR andps, sse, 1, 0, 1
1603
+ AVX_INSTR blendpd, sse4, 1, 1, 0
1604
+ AVX_INSTR blendps, sse4, 1, 1, 0
1605
+ AVX_INSTR blendvpd, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding
1606
+ AVX_INSTR blendvps, sse4, 1, 1, 0 ; last operand must be xmm0 with legacy encoding
1607
+ AVX_INSTR cmpeqpd, sse2, 1, 0, 1
1608
+ AVX_INSTR cmpeqps, sse, 1, 0, 1
1609
+ AVX_INSTR cmpeqsd, sse2, 1, 0, 0
1610
+ AVX_INSTR cmpeqss, sse, 1, 0, 0
1611
+ AVX_INSTR cmplepd, sse2, 1, 0, 0
1612
+ AVX_INSTR cmpleps, sse, 1, 0, 0
1613
+ AVX_INSTR cmplesd, sse2, 1, 0, 0
1614
+ AVX_INSTR cmpless, sse, 1, 0, 0
1615
+ AVX_INSTR cmpltpd, sse2, 1, 0, 0
1616
+ AVX_INSTR cmpltps, sse, 1, 0, 0
1617
+ AVX_INSTR cmpltsd, sse2, 1, 0, 0
1618
+ AVX_INSTR cmpltss, sse, 1, 0, 0
1619
+ AVX_INSTR cmpneqpd, sse2, 1, 0, 1
1620
+ AVX_INSTR cmpneqps, sse, 1, 0, 1
1621
+ AVX_INSTR cmpneqsd, sse2, 1, 0, 0
1622
+ AVX_INSTR cmpneqss, sse, 1, 0, 0
1623
+ AVX_INSTR cmpnlepd, sse2, 1, 0, 0
1624
+ AVX_INSTR cmpnleps, sse, 1, 0, 0
1625
+ AVX_INSTR cmpnlesd, sse2, 1, 0, 0
1626
+ AVX_INSTR cmpnless, sse, 1, 0, 0
1627
+ AVX_INSTR cmpnltpd, sse2, 1, 0, 0
1628
+ AVX_INSTR cmpnltps, sse, 1, 0, 0
1629
+ AVX_INSTR cmpnltsd, sse2, 1, 0, 0
1630
+ AVX_INSTR cmpnltss, sse, 1, 0, 0
1631
+ AVX_INSTR cmpordpd, sse2 1, 0, 1
1632
+ AVX_INSTR cmpordps, sse 1, 0, 1
1633
+ AVX_INSTR cmpordsd, sse2 1, 0, 0
1634
+ AVX_INSTR cmpordss, sse 1, 0, 0
1635
+ AVX_INSTR cmppd, sse2, 1, 1, 0
1636
+ AVX_INSTR cmpps, sse, 1, 1, 0
1637
+ AVX_INSTR cmpsd, sse2, 1, 1, 0
1638
+ AVX_INSTR cmpss, sse, 1, 1, 0
1639
+ AVX_INSTR cmpunordpd, sse2, 1, 0, 1
1640
+ AVX_INSTR cmpunordps, sse, 1, 0, 1
1641
+ AVX_INSTR cmpunordsd, sse2, 1, 0, 0
1642
+ AVX_INSTR cmpunordss, sse, 1, 0, 0
1643
+ AVX_INSTR comisd, sse2, 1
1644
+ AVX_INSTR comiss, sse, 1
1645
+ AVX_INSTR cvtdq2pd, sse2, 1
1646
+ AVX_INSTR cvtdq2ps, sse2, 1
1647
+ AVX_INSTR cvtpd2dq, sse2, 1
1648
+ AVX_INSTR cvtpd2ps, sse2, 1
1649
+ AVX_INSTR cvtps2dq, sse2, 1
1650
+ AVX_INSTR cvtps2pd, sse2, 1
1651
+ AVX_INSTR cvtsd2si, sse2, 1
1652
+ AVX_INSTR cvtsd2ss, sse2, 1, 0, 0
1653
+ AVX_INSTR cvtsi2sd, sse2, 1, 0, 0
1654
+ AVX_INSTR cvtsi2ss, sse, 1, 0, 0
1655
+ AVX_INSTR cvtss2sd, sse2, 1, 0, 0
1656
+ AVX_INSTR cvtss2si, sse, 1
1657
+ AVX_INSTR cvttpd2dq, sse2, 1
1658
+ AVX_INSTR cvttps2dq, sse2, 1
1659
+ AVX_INSTR cvttsd2si, sse2, 1
1660
+ AVX_INSTR cvttss2si, sse, 1
1661
+ AVX_INSTR divpd, sse2, 1, 0, 0
1662
+ AVX_INSTR divps, sse, 1, 0, 0
1663
+ AVX_INSTR divsd, sse2, 1, 0, 0
1664
+ AVX_INSTR divss, sse, 1, 0, 0
1665
+ AVX_INSTR dppd, sse4, 1, 1, 0
1666
+ AVX_INSTR dpps, sse4, 1, 1, 0
1667
+ AVX_INSTR extractps, sse4, 1
1668
+ AVX_INSTR gf2p8affineinvqb, gfni, 0, 1, 0
1669
+ AVX_INSTR gf2p8affineqb, gfni, 0, 1, 0
1670
+ AVX_INSTR gf2p8mulb, gfni, 0, 0, 0
1671
+ AVX_INSTR haddpd, sse3, 1, 0, 0
1672
+ AVX_INSTR haddps, sse3, 1, 0, 0
1673
+ AVX_INSTR hsubpd, sse3, 1, 0, 0
1674
+ AVX_INSTR hsubps, sse3, 1, 0, 0
1675
+ AVX_INSTR insertps, sse4, 1, 1, 0
1676
+ AVX_INSTR lddqu, sse3
1677
+ AVX_INSTR ldmxcsr, sse, 1
1678
+ AVX_INSTR maskmovdqu, sse2
1679
+ AVX_INSTR maxpd, sse2, 1, 0, 1
1680
+ AVX_INSTR maxps, sse, 1, 0, 1
1681
+ AVX_INSTR maxsd, sse2, 1, 0, 0
1682
+ AVX_INSTR maxss, sse, 1, 0, 0
1683
+ AVX_INSTR minpd, sse2, 1, 0, 1
1684
+ AVX_INSTR minps, sse, 1, 0, 1
1685
+ AVX_INSTR minsd, sse2, 1, 0, 0
1686
+ AVX_INSTR minss, sse, 1, 0, 0
1687
+ AVX_INSTR movapd, sse2, 1
1688
+ AVX_INSTR movaps, sse, 1
1689
+ AVX_INSTR movd, mmx
1690
+ AVX_INSTR movddup, sse3, 1
1691
+ AVX_INSTR movdqa, sse2
1692
+ AVX_INSTR movdqu, sse2
1693
+ AVX_INSTR movhlps, sse, 1, 0, 0
1694
+ AVX_INSTR movhpd, sse2, 1, 0, 0
1695
+ AVX_INSTR movhps, sse, 1, 0, 0
1696
+ AVX_INSTR movlhps, sse, 1, 0, 0
1697
+ AVX_INSTR movlpd, sse2, 1, 0, 0
1698
+ AVX_INSTR movlps, sse, 1, 0, 0
1699
+ AVX_INSTR movmskpd, sse2, 1
1700
+ AVX_INSTR movmskps, sse, 1
1701
+ AVX_INSTR movntdq, sse2
1702
+ AVX_INSTR movntdqa, sse4
1703
+ AVX_INSTR movntpd, sse2, 1
1704
+ AVX_INSTR movntps, sse, 1
1705
+ AVX_INSTR movq, mmx
1706
+ AVX_INSTR movsd, sse2, 1, 0, 0
1707
+ AVX_INSTR movshdup, sse3, 1
1708
+ AVX_INSTR movsldup, sse3, 1
1709
+ AVX_INSTR movss, sse, 1, 0, 0
1710
+ AVX_INSTR movupd, sse2, 1
1711
+ AVX_INSTR movups, sse, 1
1712
+ AVX_INSTR mpsadbw, sse4, 0, 1, 0
1713
+ AVX_INSTR mulpd, sse2, 1, 0, 1
1714
+ AVX_INSTR mulps, sse, 1, 0, 1
1715
+ AVX_INSTR mulsd, sse2, 1, 0, 0
1716
+ AVX_INSTR mulss, sse, 1, 0, 0
1717
+ AVX_INSTR orpd, sse2, 1, 0, 1
1718
+ AVX_INSTR orps, sse, 1, 0, 1
1719
+ AVX_INSTR pabsb, ssse3
1720
+ AVX_INSTR pabsd, ssse3
1721
+ AVX_INSTR pabsw, ssse3
1722
+ AVX_INSTR packssdw, mmx, 0, 0, 0
1723
+ AVX_INSTR packsswb, mmx, 0, 0, 0
1724
+ AVX_INSTR packusdw, sse4, 0, 0, 0
1725
+ AVX_INSTR packuswb, mmx, 0, 0, 0
1726
+ AVX_INSTR paddb, mmx, 0, 0, 1
1727
+ AVX_INSTR paddd, mmx, 0, 0, 1
1728
+ AVX_INSTR paddq, sse2, 0, 0, 1
1729
+ AVX_INSTR paddsb, mmx, 0, 0, 1
1730
+ AVX_INSTR paddsw, mmx, 0, 0, 1
1731
+ AVX_INSTR paddusb, mmx, 0, 0, 1
1732
+ AVX_INSTR paddusw, mmx, 0, 0, 1
1733
+ AVX_INSTR paddw, mmx, 0, 0, 1
1734
+ AVX_INSTR palignr, ssse3, 0, 1, 0
1735
+ AVX_INSTR pand, mmx, 0, 0, 1
1736
+ AVX_INSTR pandn, mmx, 0, 0, 0
1737
+ AVX_INSTR pavgb, mmx2, 0, 0, 1
1738
+ AVX_INSTR pavgw, mmx2, 0, 0, 1
1739
+ AVX_INSTR pblendvb, sse4, 0, 1, 0 ; last operand must be xmm0 with legacy encoding
1740
+ AVX_INSTR pblendw, sse4, 0, 1, 0
1741
+ AVX_INSTR pclmulhqhqdq, clmul, 0, 0, 0
1742
+ AVX_INSTR pclmulhqlqdq, clmul, 0, 0, 0
1743
+ AVX_INSTR pclmullqhqdq, clmul, 0, 0, 0
1744
+ AVX_INSTR pclmullqlqdq, clmul, 0, 0, 0
1745
+ AVX_INSTR pclmulqdq, clmul, 0, 1, 0
1746
+ AVX_INSTR pcmpeqb, mmx, 0, 0, 1
1747
+ AVX_INSTR pcmpeqd, mmx, 0, 0, 1
1748
+ AVX_INSTR pcmpeqq, sse4, 0, 0, 1
1749
+ AVX_INSTR pcmpeqw, mmx, 0, 0, 1
1750
+ AVX_INSTR pcmpestri, sse42
1751
+ AVX_INSTR pcmpestrm, sse42
1752
+ AVX_INSTR pcmpgtb, mmx, 0, 0, 0
1753
+ AVX_INSTR pcmpgtd, mmx, 0, 0, 0
1754
+ AVX_INSTR pcmpgtq, sse42, 0, 0, 0
1755
+ AVX_INSTR pcmpgtw, mmx, 0, 0, 0
1756
+ AVX_INSTR pcmpistri, sse42
1757
+ AVX_INSTR pcmpistrm, sse42
1758
+ AVX_INSTR pextrb, sse4
1759
+ AVX_INSTR pextrd, sse4
1760
+ AVX_INSTR pextrq, sse4
1761
+ AVX_INSTR pextrw, mmx2
1762
+ AVX_INSTR phaddd, ssse3, 0, 0, 0
1763
+ AVX_INSTR phaddsw, ssse3, 0, 0, 0
1764
+ AVX_INSTR phaddw, ssse3, 0, 0, 0
1765
+ AVX_INSTR phminposuw, sse4
1766
+ AVX_INSTR phsubd, ssse3, 0, 0, 0
1767
+ AVX_INSTR phsubsw, ssse3, 0, 0, 0
1768
+ AVX_INSTR phsubw, ssse3, 0, 0, 0
1769
+ AVX_INSTR pinsrb, sse4, 0, 1, 0
1770
+ AVX_INSTR pinsrd, sse4, 0, 1, 0
1771
+ AVX_INSTR pinsrq, sse4, 0, 1, 0
1772
+ AVX_INSTR pinsrw, mmx2, 0, 1, 0
1773
+ AVX_INSTR pmaddubsw, ssse3, 0, 0, 0
1774
+ AVX_INSTR pmaddwd, mmx, 0, 0, 1
1775
+ AVX_INSTR pmaxsb, sse4, 0, 0, 1
1776
+ AVX_INSTR pmaxsd, sse4, 0, 0, 1
1777
+ AVX_INSTR pmaxsw, mmx2, 0, 0, 1
1778
+ AVX_INSTR pmaxub, mmx2, 0, 0, 1
1779
+ AVX_INSTR pmaxud, sse4, 0, 0, 1
1780
+ AVX_INSTR pmaxuw, sse4, 0, 0, 1
1781
+ AVX_INSTR pminsb, sse4, 0, 0, 1
1782
+ AVX_INSTR pminsd, sse4, 0, 0, 1
1783
+ AVX_INSTR pminsw, mmx2, 0, 0, 1
1784
+ AVX_INSTR pminub, mmx2, 0, 0, 1
1785
+ AVX_INSTR pminud, sse4, 0, 0, 1
1786
+ AVX_INSTR pminuw, sse4, 0, 0, 1
1787
+ AVX_INSTR pmovmskb, mmx2
1788
+ AVX_INSTR pmovsxbd, sse4
1789
+ AVX_INSTR pmovsxbq, sse4
1790
+ AVX_INSTR pmovsxbw, sse4
1791
+ AVX_INSTR pmovsxdq, sse4
1792
+ AVX_INSTR pmovsxwd, sse4
1793
+ AVX_INSTR pmovsxwq, sse4
1794
+ AVX_INSTR pmovzxbd, sse4
1795
+ AVX_INSTR pmovzxbq, sse4
1796
+ AVX_INSTR pmovzxbw, sse4
1797
+ AVX_INSTR pmovzxdq, sse4
1798
+ AVX_INSTR pmovzxwd, sse4
1799
+ AVX_INSTR pmovzxwq, sse4
1800
+ AVX_INSTR pmuldq, sse4, 0, 0, 1
1801
+ AVX_INSTR pmulhrsw, ssse3, 0, 0, 1
1802
+ AVX_INSTR pmulhuw, mmx2, 0, 0, 1
1803
+ AVX_INSTR pmulhw, mmx, 0, 0, 1
1804
+ AVX_INSTR pmulld, sse4, 0, 0, 1
1805
+ AVX_INSTR pmullw, mmx, 0, 0, 1
1806
+ AVX_INSTR pmuludq, sse2, 0, 0, 1
1807
+ AVX_INSTR por, mmx, 0, 0, 1
1808
+ AVX_INSTR psadbw, mmx2, 0, 0, 1
1809
+ AVX_INSTR pshufb, ssse3, 0, 0, 0
1810
+ AVX_INSTR pshufd, sse2
1811
+ AVX_INSTR pshufhw, sse2
1812
+ AVX_INSTR pshuflw, sse2
1813
+ AVX_INSTR psignb, ssse3, 0, 0, 0
1814
+ AVX_INSTR psignd, ssse3, 0, 0, 0
1815
+ AVX_INSTR psignw, ssse3, 0, 0, 0
1816
+ AVX_INSTR pslld, mmx, 0, 0, 0
1817
+ AVX_INSTR pslldq, sse2, 0, 0, 0
1818
+ AVX_INSTR psllq, mmx, 0, 0, 0
1819
+ AVX_INSTR psllw, mmx, 0, 0, 0
1820
+ AVX_INSTR psrad, mmx, 0, 0, 0
1821
+ AVX_INSTR psraw, mmx, 0, 0, 0
1822
+ AVX_INSTR psrld, mmx, 0, 0, 0
1823
+ AVX_INSTR psrldq, sse2, 0, 0, 0
1824
+ AVX_INSTR psrlq, mmx, 0, 0, 0
1825
+ AVX_INSTR psrlw, mmx, 0, 0, 0
1826
+ AVX_INSTR psubb, mmx, 0, 0, 0
1827
+ AVX_INSTR psubd, mmx, 0, 0, 0
1828
+ AVX_INSTR psubq, sse2, 0, 0, 0
1829
+ AVX_INSTR psubsb, mmx, 0, 0, 0
1830
+ AVX_INSTR psubsw, mmx, 0, 0, 0
1831
+ AVX_INSTR psubusb, mmx, 0, 0, 0
1832
+ AVX_INSTR psubusw, mmx, 0, 0, 0
1833
+ AVX_INSTR psubw, mmx, 0, 0, 0
1834
+ AVX_INSTR ptest, sse4
1835
+ AVX_INSTR punpckhbw, mmx, 0, 0, 0
1836
+ AVX_INSTR punpckhdq, mmx, 0, 0, 0
1837
+ AVX_INSTR punpckhqdq, sse2, 0, 0, 0
1838
+ AVX_INSTR punpckhwd, mmx, 0, 0, 0
1839
+ AVX_INSTR punpcklbw, mmx, 0, 0, 0
1840
+ AVX_INSTR punpckldq, mmx, 0, 0, 0
1841
+ AVX_INSTR punpcklqdq, sse2, 0, 0, 0
1842
+ AVX_INSTR punpcklwd, mmx, 0, 0, 0
1843
+ AVX_INSTR pxor, mmx, 0, 0, 1
1844
+ AVX_INSTR rcpps, sse, 1
1845
+ AVX_INSTR rcpss, sse, 1, 0, 0
1846
+ AVX_INSTR roundpd, sse4, 1
1847
+ AVX_INSTR roundps, sse4, 1
1848
+ AVX_INSTR roundsd, sse4, 1, 1, 0
1849
+ AVX_INSTR roundss, sse4, 1, 1, 0
1850
+ AVX_INSTR rsqrtps, sse, 1
1851
+ AVX_INSTR rsqrtss, sse, 1, 0, 0
1852
+ AVX_INSTR shufpd, sse2, 1, 1, 0
1853
+ AVX_INSTR shufps, sse, 1, 1, 0
1854
+ AVX_INSTR sqrtpd, sse2, 1
1855
+ AVX_INSTR sqrtps, sse, 1
1856
+ AVX_INSTR sqrtsd, sse2, 1, 0, 0
1857
+ AVX_INSTR sqrtss, sse, 1, 0, 0
1858
+ AVX_INSTR stmxcsr, sse, 1
1859
+ AVX_INSTR subpd, sse2, 1, 0, 0
1860
+ AVX_INSTR subps, sse, 1, 0, 0
1861
+ AVX_INSTR subsd, sse2, 1, 0, 0
1862
+ AVX_INSTR subss, sse, 1, 0, 0
1863
+ AVX_INSTR ucomisd, sse2, 1
1864
+ AVX_INSTR ucomiss, sse, 1
1865
+ AVX_INSTR unpckhpd, sse2, 1, 0, 0
1866
+ AVX_INSTR unpckhps, sse, 1, 0, 0
1867
+ AVX_INSTR unpcklpd, sse2, 1, 0, 0
1868
+ AVX_INSTR unpcklps, sse, 1, 0, 0
1869
+ AVX_INSTR xorpd, sse2, 1, 0, 1
1870
+ AVX_INSTR xorps, sse, 1, 0, 1
1871
+
1872
+ ; 3DNow instructions, for sharing code between AVX, SSE and 3DN
1873
+ AVX_INSTR pfadd, 3dnow, 1, 0, 1
1874
+ AVX_INSTR pfmul, 3dnow, 1, 0, 1
1875
+ AVX_INSTR pfsub, 3dnow, 1, 0, 0
1876
+
1877
+ ;%1 == instruction
1878
+ ;%2 == minimal instruction set
1879
+ %macro GPR_INSTR 2
1880
+ %macro %1 2-5 fnord, %1, %2
1881
+ %ifdef cpuname
1882
+ %if notcpuflag(%5)
1883
+ %error use of ``%4'' %5 instruction in cpuname function: current_function
1884
+ %endif
1885
+ %endif
1886
+ %ifidn %3, fnord
1887
+ %4 %1, %2
1888
+ %else
1889
+ %4 %1, %2, %3
1890
+ %endif
1891
+ %endmacro
1892
+ %endmacro
1893
+
1894
+ GPR_INSTR andn, bmi1
1895
+ GPR_INSTR bextr, bmi1
1896
+ GPR_INSTR blsi, bmi1
1897
+ GPR_INSTR blsmsk, bmi1
1898
+ GPR_INSTR blsr, bmi1
1899
+ GPR_INSTR bzhi, bmi2
1900
+ GPR_INSTR crc32, sse42
1901
+ GPR_INSTR mulx, bmi2
1902
+ GPR_INSTR pdep, bmi2
1903
+ GPR_INSTR pext, bmi2
1904
+ GPR_INSTR popcnt, sse42
1905
+ GPR_INSTR rorx, bmi2
1906
+ GPR_INSTR sarx, bmi2
1907
+ GPR_INSTR shlx, bmi2
1908
+ GPR_INSTR shrx, bmi2
1909
+
1910
+ ; base-4 constants for shuffles
1911
+ %assign i 0
1912
+ %rep 256
1913
+ %assign j ((i>>6)&3)*1000 + ((i>>4)&3)*100 + ((i>>2)&3)*10 + (i&3)
1914
+ %if j < 10
1915
+ CAT_XDEFINE q000, j, i
1916
+ %elif j < 100
1917
+ CAT_XDEFINE q00, j, i
1918
+ %elif j < 1000
1919
+ CAT_XDEFINE q0, j, i
1920
+ %else
1921
+ CAT_XDEFINE q, j, i
1922
+ %endif
1923
+ %assign i i+1
1924
+ %endrep
1925
+ %undef i
1926
+ %undef j
1927
+
1928
+ %macro FMA_INSTR 3
1929
+ %macro %1 4-7 %1, %2, %3
1930
+ %if cpuflag(xop)
1931
+ v%5 %1, %2, %3, %4
1932
+ %elifnidn %1, %4
1933
+ %6 %1, %2, %3
1934
+ %7 %1, %4
1935
+ %else
1936
+ %error non-xop emulation of ``%5 %1, %2, %3, %4'' is not supported
1937
+ %endif
1938
+ %endmacro
1939
+ %endmacro
1940
+
1941
+ FMA_INSTR pmacsdd, pmulld, paddd ; sse4 emulation
1942
+ FMA_INSTR pmacsdql, pmuldq, paddq ; sse4 emulation
1943
+ FMA_INSTR pmacsww, pmullw, paddw
1944
+ FMA_INSTR pmadcswd, pmaddwd, paddd
1945
+
1946
+ ; Macros for consolidating FMA3 and FMA4 using 4-operand (dst, src1, src2, src3) syntax.
1947
+ ; FMA3 is only possible if dst is the same as one of the src registers.
1948
+ ; Either src2 or src3 can be a memory operand.
1949
+ %macro FMA4_INSTR 2-*
1950
+ %push fma4_instr
1951
+ %xdefine %$prefix %1
1952
+ %rep %0 - 1
1953
+ %macro %$prefix%2 4-6 %$prefix, %2
1954
+ %if notcpuflag(fma3) && notcpuflag(fma4)
1955
+ %error use of ``%5%6'' fma instruction in cpuname function: current_function
1956
+ %elif cpuflag(fma4)
1957
+ v%5%6 %1, %2, %3, %4
1958
+ %elifidn %1, %2
1959
+ ; If %3 or %4 is a memory operand it needs to be encoded as the last operand.
1960
+ %ifnum sizeof%3
1961
+ v%{5}213%6 %2, %3, %4
1962
+ %else
1963
+ v%{5}132%6 %2, %4, %3
1964
+ %endif
1965
+ %elifidn %1, %3
1966
+ v%{5}213%6 %3, %2, %4
1967
+ %elifidn %1, %4
1968
+ v%{5}231%6 %4, %2, %3
1969
+ %else
1970
+ %error fma3 emulation of ``%5%6 %1, %2, %3, %4'' is not supported
1971
+ %endif
1972
+ %endmacro
1973
+ %rotate 1
1974
+ %endrep
1975
+ %pop
1976
+ %endmacro
1977
+
1978
+ FMA4_INSTR fmadd, pd, ps, sd, ss
1979
+ FMA4_INSTR fmaddsub, pd, ps
1980
+ FMA4_INSTR fmsub, pd, ps, sd, ss
1981
+ FMA4_INSTR fmsubadd, pd, ps
1982
+ FMA4_INSTR fnmadd, pd, ps, sd, ss
1983
+ FMA4_INSTR fnmsub, pd, ps, sd, ss
1984
+
1985
+ ; Macros for converting VEX instructions to equivalent EVEX ones.
1986
+ %macro EVEX_INSTR 2-3 0 ; vex, evex, prefer_evex
1987
+ %macro %1 2-7 fnord, fnord, %1, %2, %3
1988
+ %ifidn %3, fnord
1989
+ %define %%args %1, %2
1990
+ %elifidn %4, fnord
1991
+ %define %%args %1, %2, %3
1992
+ %else
1993
+ %define %%args %1, %2, %3, %4
1994
+ %endif
1995
+ %assign %%evex_required cpuflag(avx512) & %7
1996
+ %ifnum regnumof%1
1997
+ %if regnumof%1 >= 16 || sizeof%1 > 32
1998
+ %assign %%evex_required 1
1999
+ %endif
2000
+ %endif
2001
+ %ifnum regnumof%2
2002
+ %if regnumof%2 >= 16 || sizeof%2 > 32
2003
+ %assign %%evex_required 1
2004
+ %endif
2005
+ %endif
2006
+ %ifnum regnumof%3
2007
+ %if regnumof%3 >= 16 || sizeof%3 > 32
2008
+ %assign %%evex_required 1
2009
+ %endif
2010
+ %endif
2011
+ %if %%evex_required
2012
+ %6 %%args
2013
+ %else
2014
+ %5 %%args ; Prefer VEX over EVEX due to shorter instruction length
2015
+ %endif
2016
+ %endmacro
2017
+ %endmacro
2018
+
2019
+ EVEX_INSTR vbroadcastf128, vbroadcastf32x4
2020
+ EVEX_INSTR vbroadcasti128, vbroadcasti32x4
2021
+ EVEX_INSTR vextractf128, vextractf32x4
2022
+ EVEX_INSTR vextracti128, vextracti32x4
2023
+ EVEX_INSTR vinsertf128, vinsertf32x4
2024
+ EVEX_INSTR vinserti128, vinserti32x4
2025
+ EVEX_INSTR vmovdqa, vmovdqa32
2026
+ EVEX_INSTR vmovdqu, vmovdqu32
2027
+ EVEX_INSTR vpand, vpandd
2028
+ EVEX_INSTR vpandn, vpandnd
2029
+ EVEX_INSTR vpor, vpord
2030
+ EVEX_INSTR vpxor, vpxord
2031
+ EVEX_INSTR vrcpps, vrcp14ps, 1 ; EVEX versions have higher precision
2032
+ EVEX_INSTR vrcpss, vrcp14ss, 1
2033
+ EVEX_INSTR vrsqrtps, vrsqrt14ps, 1
2034
+ EVEX_INSTR vrsqrtss, vrsqrt14ss, 1
2035
+
2036
+