| ; |
| ; jsimdext.inc - common declarations |
| ; |
| ; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB |
| ; Copyright (C) 2010, 2016, D. R. Commander. |
| ; Copyright (C) 2018, Matthieu Darbois. |
| ; |
| ; Based on the x86 SIMD extension for IJG JPEG library - version 1.02 |
| ; |
| ; Copyright (C) 1999-2006, MIYASAKA Masaru. |
| ; |
| ; This software is provided 'as-is', without any express or implied |
| ; warranty. In no event will the authors be held liable for any damages |
| ; arising from the use of this software. |
| ; |
| ; Permission is granted to anyone to use this software for any purpose, |
| ; including commercial applications, and to alter it and redistribute it |
| ; freely, subject to the following restrictions: |
| ; |
| ; 1. The origin of this software must not be misrepresented; you must not |
| ; claim that you wrote the original software. If you use this software |
| ; in a product, an acknowledgment in the product documentation would be |
| ; appreciated but is not required. |
| ; 2. Altered source versions must be plainly marked as such, and must not be |
| ; misrepresented as being the original software. |
| ; 3. This notice may not be removed or altered from any source distribution. |
| ; |
| ; [TAB8] |
| |
| ; ========================================================================== |
| ; System-dependent configurations |
| |
| %ifdef WIN32 ; ----(nasm -fwin32 -DWIN32 ...)-------- |
| ; * Microsoft Visual C++ |
| ; * MinGW (Minimalist GNU for Windows) |
| ; * CygWin |
| ; * LCC-Win32 |
| |
| ; -- segment definition -- |
| ; |
| %ifdef __YASM_VER__ |
| %define SEG_TEXT .text align=32 |
| %define SEG_CONST .rdata align=32 |
| %else |
| %define SEG_TEXT .text align=32 public use32 class=CODE |
| %define SEG_CONST .rdata align=32 public use32 class=CONST |
| %endif |
| |
| %elifdef WIN64 ; ----(nasm -fwin64 -DWIN64 ...)-------- |
| ; * Microsoft Visual C++ |
| |
| ; -- segment definition -- |
| ; |
| %ifdef __YASM_VER__ |
| %define SEG_TEXT .text align=32 |
| %define SEG_CONST .rdata align=32 |
| %else |
| %define SEG_TEXT .text align=32 public use64 class=CODE |
| %define SEG_CONST .rdata align=32 public use64 class=CONST |
| %endif |
| %define EXTN(name) name ; foo() -> foo |
| |
| %elifdef OBJ32 ; ----(nasm -fobj -DOBJ32 ...)---------- |
| ; * Borland C++ (Win32) |
| |
| ; -- segment definition -- |
| ; |
| %define SEG_TEXT _text align=32 public use32 class=CODE |
| %define SEG_CONST _data align=32 public use32 class=DATA |
| |
| %elifdef ELF ; ----(nasm -felf[64] -DELF ...)------------ |
| ; * Linux |
| ; * *BSD family Unix using elf format |
| ; * Unix System V, including Solaris x86, UnixWare and SCO Unix |
| |
| ; mark stack as non-executable |
| section .note.GNU-stack noalloc noexec nowrite progbits |
| |
| ; -- segment definition -- |
| ; |
| %ifdef __x86_64__ |
| %define SEG_TEXT .text progbits align=32 |
| %define SEG_CONST .rodata progbits align=32 |
| %else |
| %define SEG_TEXT .text progbits alloc exec nowrite align=32 |
| %define SEG_CONST .rodata progbits alloc noexec nowrite align=32 |
| %endif |
| |
| ; To make the code position-independent, append -DPIC to the commandline |
| ; |
| %define GOT_SYMBOL _GLOBAL_OFFSET_TABLE_ ; ELF supports PIC |
| %define EXTN(name) name ; foo() -> foo |
| |
| %elifdef AOUT ; ----(nasm -faoutb/aout -DAOUT ...)---- |
| ; * Older Linux using a.out format (nasm -f aout -DAOUT ...) |
| ; * *BSD family Unix using a.out format (nasm -f aoutb -DAOUT ...) |
| |
| ; -- segment definition -- |
| ; |
| %define SEG_TEXT .text |
| %define SEG_CONST .data |
| |
| ; To make the code position-independent, append -DPIC to the commandline |
| ; |
| %define GOT_SYMBOL __GLOBAL_OFFSET_TABLE_ ; BSD-style a.out supports PIC |
| |
| %elifdef MACHO ; ----(nasm -fmacho -DMACHO ...)-------- |
| ; * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (Mach-O format) |
| |
| ; -- segment definition -- |
| ; |
| %define SEG_TEXT .text ;align=32 ; nasm doesn't accept align=32. why? |
| %define SEG_CONST .rodata align=32 |
| |
| ; The generation of position-independent code (PIC) is the default on Darwin. |
| ; |
| %define PIC |
| %define GOT_SYMBOL _MACHO_PIC_ ; Mach-O style code-relative addressing |
| |
| %else ; ----(Other case)---------------------- |
| |
| ; -- segment definition -- |
| ; |
| %define SEG_TEXT .text |
| %define SEG_CONST .data |
| |
| %endif ; ---------------------------------------------- |
| |
| ; ========================================================================== |
| |
| ; -------------------------------------------------------------------------- |
| ; Common types |
| ; |
| %ifdef __x86_64__ |
| %define POINTER qword ; general pointer type |
| %define SIZEOF_POINTER SIZEOF_QWORD ; sizeof(POINTER) |
| %define POINTER_BIT QWORD_BIT ; sizeof(POINTER)*BYTE_BIT |
| %else |
| %define POINTER dword ; general pointer type |
| %define SIZEOF_POINTER SIZEOF_DWORD ; sizeof(POINTER) |
| %define POINTER_BIT DWORD_BIT ; sizeof(POINTER)*BYTE_BIT |
| %endif |
| |
| %define INT dword ; signed integer type |
| %define SIZEOF_INT SIZEOF_DWORD ; sizeof(INT) |
| %define INT_BIT DWORD_BIT ; sizeof(INT)*BYTE_BIT |
| |
| %define FP32 dword ; IEEE754 single |
| %define SIZEOF_FP32 SIZEOF_DWORD ; sizeof(FP32) |
| %define FP32_BIT DWORD_BIT ; sizeof(FP32)*BYTE_BIT |
| |
| %define MMWORD qword ; int64 (MMX register) |
| %define SIZEOF_MMWORD SIZEOF_QWORD ; sizeof(MMWORD) |
| %define MMWORD_BIT QWORD_BIT ; sizeof(MMWORD)*BYTE_BIT |
| |
| ; NASM is buggy and doesn't properly handle operand sizes for SSE |
| ; instructions, so for now we have to define XMMWORD as blank. |
| %define XMMWORD ; int128 (SSE register) |
| %define SIZEOF_XMMWORD SIZEOF_OWORD ; sizeof(XMMWORD) |
| %define XMMWORD_BIT OWORD_BIT ; sizeof(XMMWORD)*BYTE_BIT |
| |
| %define YMMWORD ; int256 (AVX register) |
| %define SIZEOF_YMMWORD SIZEOF_YWORD ; sizeof(YMMWORD) |
| %define YMMWORD_BIT YWORD_BIT ; sizeof(YMMWORD)*BYTE_BIT |
| |
| ; Similar hacks for when we load a dword or MMWORD into an xmm# register |
| %define XMM_DWORD |
| %define XMM_MMWORD |
| |
| %define SIZEOF_BYTE 1 ; sizeof(BYTE) |
| %define SIZEOF_WORD 2 ; sizeof(WORD) |
| %define SIZEOF_DWORD 4 ; sizeof(DWORD) |
| %define SIZEOF_QWORD 8 ; sizeof(QWORD) |
| %define SIZEOF_OWORD 16 ; sizeof(OWORD) |
| %define SIZEOF_YWORD 32 ; sizeof(YWORD) |
| |
| %define BYTE_BIT 8 ; CHAR_BIT in C |
| %define WORD_BIT 16 ; sizeof(WORD)*BYTE_BIT |
| %define DWORD_BIT 32 ; sizeof(DWORD)*BYTE_BIT |
| %define QWORD_BIT 64 ; sizeof(QWORD)*BYTE_BIT |
| %define OWORD_BIT 128 ; sizeof(OWORD)*BYTE_BIT |
| %define YWORD_BIT 256 ; sizeof(YWORD)*BYTE_BIT |
| |
| ; -------------------------------------------------------------------------- |
| ; External Symbol Name |
| ; |
| %ifndef EXTN |
| %define EXTN(name) _ %+ name ; foo() -> _foo |
| %endif |
| |
| ; -------------------------------------------------------------------------- |
| ; Hidden symbols |
| ; |
| %ifdef ELF ; ----(nasm -felf[64] -DELF ...)-------- |
| %define GLOBAL_FUNCTION(name) global EXTN(name):function hidden |
| %define GLOBAL_DATA(name) global EXTN(name):data hidden |
| %elifdef MACHO ; ----(nasm -fmacho -DMACHO ...)-------- |
| %ifdef __YASM_VER__ |
| %define GLOBAL_FUNCTION(name) global EXTN(name):private_extern |
| %define GLOBAL_DATA(name) global EXTN(name):private_extern |
| %endif |
| %endif |
| |
| %ifndef GLOBAL_FUNCTION |
| %define GLOBAL_FUNCTION(name) global EXTN(name) |
| %endif |
| %ifndef GLOBAL_DATA |
| %define GLOBAL_DATA(name) global EXTN(name) |
| %endif |
| |
| ; -------------------------------------------------------------------------- |
| ; Macros for position-independent code (PIC) support |
| ; |
| %ifndef GOT_SYMBOL |
| %undef PIC |
| %endif |
| |
| %ifdef PIC ; ------------------------------------------- |
| |
| %ifidn GOT_SYMBOL, _MACHO_PIC_ ; -------------------- |
| |
| ; At present, nasm doesn't seem to support PIC generation for Mach-O. |
| ; The PIC support code below is a little tricky. |
| |
| SECTION SEG_CONST |
| const_base: |
| |
| %define GOTOFF(got, sym) (got) + (sym) - const_base |
| |
| %imacro get_GOT 1 |
| ; NOTE: this macro destroys ecx resister. |
| call %%geteip |
| add ecx, byte (%%ref - $) |
| jmp short %%adjust |
| %%geteip: |
| mov ecx, POINTER [esp] |
| ret |
| %%adjust: |
| push ebp |
| xor ebp, ebp ; ebp = 0 |
| %ifidni %1, ebx ; (%1 == ebx) |
| ; db 0x8D,0x9C + jmp near const_base = |
| ; lea ebx, [ecx+ebp*8+(const_base-%%ref)] ; 8D,9C,E9,(offset32) |
| db 0x8D, 0x9C ; 8D,9C |
| jmp near const_base ; E9,(const_base-%%ref) |
| %%ref: |
| %else ; (%1 != ebx) |
| ; db 0x8D,0x8C + jmp near const_base = |
| ; lea ecx, [ecx+ebp*8+(const_base-%%ref)] ; 8D,8C,E9,(offset32) |
| db 0x8D, 0x8C ; 8D,8C |
| jmp near const_base ; E9,(const_base-%%ref) |
| %%ref: |
| mov %1, ecx |
| %endif ; (%1 == ebx) |
| pop ebp |
| %endmacro |
| |
| %else ; GOT_SYMBOL != _MACHO_PIC_ ---------------- |
| |
| %define GOTOFF(got, sym) (got) + (sym) wrt ..gotoff |
| |
| %imacro get_GOT 1 |
| extern GOT_SYMBOL |
| call %%geteip |
| add %1, GOT_SYMBOL + $$ - $ wrt ..gotpc |
| jmp short %%done |
| %%geteip: |
| mov %1, POINTER [esp] |
| ret |
| %%done: |
| %endmacro |
| |
| %endif ; GOT_SYMBOL == _MACHO_PIC_ ---------------- |
| |
| %imacro pushpic 1.nolist |
| push %1 |
| %endmacro |
| %imacro poppic 1.nolist |
| pop %1 |
| %endmacro |
| %imacro movpic 2.nolist |
| mov %1, %2 |
| %endmacro |
| |
| %else ; !PIC ----------------------------------------- |
| |
| %define GOTOFF(got, sym) (sym) |
| |
| %imacro get_GOT 1.nolist |
| %endmacro |
| %imacro pushpic 1.nolist |
| %endmacro |
| %imacro poppic 1.nolist |
| %endmacro |
| %imacro movpic 2.nolist |
| %endmacro |
| |
| %endif ; PIC ----------------------------------------- |
| |
| ; -------------------------------------------------------------------------- |
| ; Align the next instruction on {2,4,8,16,..}-byte boundary. |
| ; ".balign n,,m" in GNU as |
| ; |
| %define MSKLE(x, y) (~(((y) & 0xFFFF) - ((x) & 0xFFFF)) >> 16) |
| %define FILLB(b, n) (($$-(b)) & ((n)-1)) |
| |
| %imacro alignx 1-2.nolist 0xFFFF |
| %%bs: \ |
| times MSKLE(FILLB(%%bs, %1), %2) & MSKLE(16, FILLB($, %1)) & FILLB($, %1) \ |
| db 0x90 ; nop |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 9 \ |
| db 0x8D, 0x9C, 0x23, 0x00, 0x00, 0x00, 0x00 ; lea ebx,[ebx+0x00000000] |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 7 \ |
| db 0x8D, 0xAC, 0x25, 0x00, 0x00, 0x00, 0x00 ; lea ebp,[ebp+0x00000000] |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 6 \ |
| db 0x8D, 0xAD, 0x00, 0x00, 0x00, 0x00 ; lea ebp,[ebp+0x00000000] |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 4 \ |
| db 0x8D, 0x6C, 0x25, 0x00 ; lea ebp,[ebp+0x00] |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 3 \ |
| db 0x8D, 0x6D, 0x00 ; lea ebp,[ebp+0x00] |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 2 \ |
| db 0x8B, 0xED ; mov ebp,ebp |
| times MSKLE(FILLB(%%bs, %1), %2) & FILLB($, %1) / 1 \ |
| db 0x90 ; nop |
| %endmacro |
| |
| ; Align the next data on {2,4,8,16,..}-byte boundary. |
| ; |
| %imacro alignz 1.nolist |
| align %1, db 0 ; filling zeros |
| %endmacro |
| |
| %ifdef __x86_64__ |
| |
| %ifdef WIN64 |
| |
| %imacro collect_args 1 |
| sub rsp, SIZEOF_XMMWORD |
| movaps XMMWORD [rsp], xmm6 |
| sub rsp, SIZEOF_XMMWORD |
| movaps XMMWORD [rsp], xmm7 |
| mov r10, rcx |
| %if %1 > 1 |
| mov r11, rdx |
| %endif |
| %if %1 > 2 |
| push r12 |
| mov r12, r8 |
| %endif |
| %if %1 > 3 |
| push r13 |
| mov r13, r9 |
| %endif |
| %if %1 > 4 |
| push r14 |
| mov r14, [rax+48] |
| %endif |
| %if %1 > 5 |
| push r15 |
| mov r15, [rax+56] |
| %endif |
| push rsi |
| push rdi |
| %endmacro |
| |
| %imacro uncollect_args 1 |
| pop rdi |
| pop rsi |
| %if %1 > 5 |
| pop r15 |
| %endif |
| %if %1 > 4 |
| pop r14 |
| %endif |
| %if %1 > 3 |
| pop r13 |
| %endif |
| %if %1 > 2 |
| pop r12 |
| %endif |
| movaps xmm7, XMMWORD [rsp] |
| add rsp, SIZEOF_XMMWORD |
| movaps xmm6, XMMWORD [rsp] |
| add rsp, SIZEOF_XMMWORD |
| %endmacro |
| |
| %imacro push_xmm 1 |
| sub rsp, %1 * SIZEOF_XMMWORD |
| movaps XMMWORD [rsp+0*SIZEOF_XMMWORD], xmm8 |
| %if %1 > 1 |
| movaps XMMWORD [rsp+1*SIZEOF_XMMWORD], xmm9 |
| %endif |
| %if %1 > 2 |
| movaps XMMWORD [rsp+2*SIZEOF_XMMWORD], xmm10 |
| %endif |
| %if %1 > 3 |
| movaps XMMWORD [rsp+3*SIZEOF_XMMWORD], xmm11 |
| %endif |
| %endmacro |
| |
| %imacro pop_xmm 1 |
| movaps xmm8, XMMWORD [rsp+0*SIZEOF_XMMWORD] |
| %if %1 > 1 |
| movaps xmm9, XMMWORD [rsp+1*SIZEOF_XMMWORD] |
| %endif |
| %if %1 > 2 |
| movaps xmm10, XMMWORD [rsp+2*SIZEOF_XMMWORD] |
| %endif |
| %if %1 > 3 |
| movaps xmm11, XMMWORD [rsp+3*SIZEOF_XMMWORD] |
| %endif |
| add rsp, %1 * SIZEOF_XMMWORD |
| %endmacro |
| |
| %else |
| |
| %imacro collect_args 1 |
| push r10 |
| mov r10, rdi |
| %if %1 > 1 |
| push r11 |
| mov r11, rsi |
| %endif |
| %if %1 > 2 |
| push r12 |
| mov r12, rdx |
| %endif |
| %if %1 > 3 |
| push r13 |
| mov r13, rcx |
| %endif |
| %if %1 > 4 |
| push r14 |
| mov r14, r8 |
| %endif |
| %if %1 > 5 |
| push r15 |
| mov r15, r9 |
| %endif |
| %endmacro |
| |
| %imacro uncollect_args 1 |
| %if %1 > 5 |
| pop r15 |
| %endif |
| %if %1 > 4 |
| pop r14 |
| %endif |
| %if %1 > 3 |
| pop r13 |
| %endif |
| %if %1 > 2 |
| pop r12 |
| %endif |
| %if %1 > 1 |
| pop r11 |
| %endif |
| pop r10 |
| %endmacro |
| |
| %imacro push_xmm 1 |
| %endmacro |
| |
| %imacro pop_xmm 1 |
| %endmacro |
| |
| %endif |
| |
| %endif |
| |
| ; -------------------------------------------------------------------------- |
| ; Defines picked up from the C headers |
| ; |
| %include "jsimdcfg.inc" |
| |
| ; -------------------------------------------------------------------------- |