chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
; 7zAsm.asm -- ASM macros
|
||||
; 2023-12-08 : Igor Pavlov : Public domain
|
||||
|
||||
|
||||
; UASM can require these changes
|
||||
; OPTION FRAMEPRESERVEFLAGS:ON
|
||||
; OPTION PROLOGUE:NONE
|
||||
; OPTION EPILOGUE:NONE
|
||||
|
||||
ifdef @wordsize
|
||||
; @wordsize is defined only in JWASM and ASMC and is not defined in MASM
|
||||
; @wordsize eq 8 for 64-bit x64
|
||||
; @wordsize eq 2 for 32-bit x86
|
||||
if @wordsize eq 8
|
||||
x64 equ 1
|
||||
endif
|
||||
else
|
||||
ifdef RAX
|
||||
x64 equ 1
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifdef x64
|
||||
IS_X64 equ 1
|
||||
else
|
||||
IS_X64 equ 0
|
||||
endif
|
||||
|
||||
ifdef ABI_LINUX
|
||||
IS_LINUX equ 1
|
||||
else
|
||||
IS_LINUX equ 0
|
||||
endif
|
||||
|
||||
ifndef x64
|
||||
; Use ABI_CDECL for x86 (32-bit) only
|
||||
; if ABI_CDECL is not defined, we use fastcall abi
|
||||
ifdef ABI_CDECL
|
||||
IS_CDECL equ 1
|
||||
else
|
||||
IS_CDECL equ 0
|
||||
endif
|
||||
endif
|
||||
|
||||
OPTION PROLOGUE:NONE
|
||||
OPTION EPILOGUE:NONE
|
||||
|
||||
MY_ASM_START macro
|
||||
ifdef x64
|
||||
.code
|
||||
else
|
||||
.386
|
||||
.model flat
|
||||
_TEXT$00 SEGMENT PARA PUBLIC 'CODE'
|
||||
endif
|
||||
endm
|
||||
|
||||
MY_PROC macro name:req, numParams:req
|
||||
align 16
|
||||
proc_numParams = numParams
|
||||
if (IS_X64 gt 0)
|
||||
proc_name equ name
|
||||
elseif (IS_LINUX gt 0)
|
||||
proc_name equ name
|
||||
elseif (IS_CDECL gt 0)
|
||||
proc_name equ @CatStr(_,name)
|
||||
else
|
||||
proc_name equ @CatStr(@,name,@, %numParams * 4)
|
||||
endif
|
||||
proc_name PROC
|
||||
endm
|
||||
|
||||
MY_ENDP macro
|
||||
if (IS_X64 gt 0)
|
||||
ret
|
||||
elseif (IS_CDECL gt 0)
|
||||
ret
|
||||
elseif (proc_numParams LT 3)
|
||||
ret
|
||||
else
|
||||
ret (proc_numParams - 2) * 4
|
||||
endif
|
||||
proc_name ENDP
|
||||
endm
|
||||
|
||||
|
||||
ifdef x64
|
||||
REG_SIZE equ 8
|
||||
REG_LOGAR_SIZE equ 3
|
||||
else
|
||||
REG_SIZE equ 4
|
||||
REG_LOGAR_SIZE equ 2
|
||||
endif
|
||||
|
||||
x0 equ EAX
|
||||
x1 equ ECX
|
||||
x2 equ EDX
|
||||
x3 equ EBX
|
||||
x4 equ ESP
|
||||
x5 equ EBP
|
||||
x6 equ ESI
|
||||
x7 equ EDI
|
||||
|
||||
x0_W equ AX
|
||||
x1_W equ CX
|
||||
x2_W equ DX
|
||||
x3_W equ BX
|
||||
|
||||
x5_W equ BP
|
||||
x6_W equ SI
|
||||
x7_W equ DI
|
||||
|
||||
x0_L equ AL
|
||||
x1_L equ CL
|
||||
x2_L equ DL
|
||||
x3_L equ BL
|
||||
|
||||
x0_H equ AH
|
||||
x1_H equ CH
|
||||
x2_H equ DH
|
||||
x3_H equ BH
|
||||
|
||||
; r0_L equ AL
|
||||
; r1_L equ CL
|
||||
; r2_L equ DL
|
||||
; r3_L equ BL
|
||||
|
||||
; r0_H equ AH
|
||||
; r1_H equ CH
|
||||
; r2_H equ DH
|
||||
; r3_H equ BH
|
||||
|
||||
|
||||
ifdef x64
|
||||
x5_L equ BPL
|
||||
x6_L equ SIL
|
||||
x7_L equ DIL
|
||||
x8_L equ r8b
|
||||
x9_L equ r9b
|
||||
x10_L equ r10b
|
||||
x11_L equ r11b
|
||||
x12_L equ r12b
|
||||
x13_L equ r13b
|
||||
x14_L equ r14b
|
||||
x15_L equ r15b
|
||||
|
||||
r0 equ RAX
|
||||
r1 equ RCX
|
||||
r2 equ RDX
|
||||
r3 equ RBX
|
||||
r4 equ RSP
|
||||
r5 equ RBP
|
||||
r6 equ RSI
|
||||
r7 equ RDI
|
||||
x8 equ r8d
|
||||
x9 equ r9d
|
||||
x10 equ r10d
|
||||
x11 equ r11d
|
||||
x12 equ r12d
|
||||
x13 equ r13d
|
||||
x14 equ r14d
|
||||
x15 equ r15d
|
||||
else
|
||||
r0 equ x0
|
||||
r1 equ x1
|
||||
r2 equ x2
|
||||
r3 equ x3
|
||||
r4 equ x4
|
||||
r5 equ x5
|
||||
r6 equ x6
|
||||
r7 equ x7
|
||||
endif
|
||||
|
||||
x0_R equ r0
|
||||
x1_R equ r1
|
||||
x2_R equ r2
|
||||
x3_R equ r3
|
||||
x4_R equ r4
|
||||
x5_R equ r5
|
||||
x6_R equ r6
|
||||
x7_R equ r7
|
||||
x8_R equ r8
|
||||
x9_R equ r9
|
||||
x10_R equ r10
|
||||
x11_R equ r11
|
||||
x12_R equ r12
|
||||
x13_R equ r13
|
||||
x14_R equ r14
|
||||
x15_R equ r15
|
||||
|
||||
ifdef x64
|
||||
ifdef ABI_LINUX
|
||||
|
||||
MY_PUSH_2_REGS macro
|
||||
push r3
|
||||
push r5
|
||||
endm
|
||||
|
||||
MY_POP_2_REGS macro
|
||||
pop r5
|
||||
pop r3
|
||||
endm
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
MY_PUSH_4_REGS macro
|
||||
push r3
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
endm
|
||||
|
||||
MY_POP_4_REGS macro
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r3
|
||||
endm
|
||||
|
||||
|
||||
; for fastcall and for WIN-x64
|
||||
REG_PARAM_0_x equ x1
|
||||
REG_PARAM_0 equ r1
|
||||
REG_PARAM_1_x equ x2
|
||||
REG_PARAM_1 equ r2
|
||||
|
||||
ifndef x64
|
||||
; for x86-fastcall
|
||||
|
||||
REG_ABI_PARAM_0_x equ REG_PARAM_0_x
|
||||
REG_ABI_PARAM_0 equ REG_PARAM_0
|
||||
REG_ABI_PARAM_1_x equ REG_PARAM_1_x
|
||||
REG_ABI_PARAM_1 equ REG_PARAM_1
|
||||
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro
|
||||
MY_PUSH_4_REGS
|
||||
endm
|
||||
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro
|
||||
MY_POP_4_REGS
|
||||
endm
|
||||
|
||||
else
|
||||
; x64
|
||||
|
||||
if (IS_LINUX eq 0)
|
||||
|
||||
; for WIN-x64:
|
||||
REG_PARAM_2_x equ x8
|
||||
REG_PARAM_2 equ r8
|
||||
REG_PARAM_3 equ r9
|
||||
|
||||
REG_ABI_PARAM_0_x equ REG_PARAM_0_x
|
||||
REG_ABI_PARAM_0 equ REG_PARAM_0
|
||||
REG_ABI_PARAM_1_x equ REG_PARAM_1_x
|
||||
REG_ABI_PARAM_1 equ REG_PARAM_1
|
||||
REG_ABI_PARAM_2_x equ REG_PARAM_2_x
|
||||
REG_ABI_PARAM_2 equ REG_PARAM_2
|
||||
REG_ABI_PARAM_3 equ REG_PARAM_3
|
||||
|
||||
else
|
||||
; for LINUX-x64:
|
||||
REG_LINUX_PARAM_0_x equ x7
|
||||
REG_LINUX_PARAM_0 equ r7
|
||||
REG_LINUX_PARAM_1_x equ x6
|
||||
REG_LINUX_PARAM_1 equ r6
|
||||
REG_LINUX_PARAM_2 equ r2
|
||||
REG_LINUX_PARAM_3 equ r1
|
||||
REG_LINUX_PARAM_4_x equ x8
|
||||
REG_LINUX_PARAM_4 equ r8
|
||||
REG_LINUX_PARAM_5 equ r9
|
||||
|
||||
REG_ABI_PARAM_0_x equ REG_LINUX_PARAM_0_x
|
||||
REG_ABI_PARAM_0 equ REG_LINUX_PARAM_0
|
||||
REG_ABI_PARAM_1_x equ REG_LINUX_PARAM_1_x
|
||||
REG_ABI_PARAM_1 equ REG_LINUX_PARAM_1
|
||||
REG_ABI_PARAM_2 equ REG_LINUX_PARAM_2
|
||||
REG_ABI_PARAM_3 equ REG_LINUX_PARAM_3
|
||||
REG_ABI_PARAM_4_x equ REG_LINUX_PARAM_4_x
|
||||
REG_ABI_PARAM_4 equ REG_LINUX_PARAM_4
|
||||
REG_ABI_PARAM_5 equ REG_LINUX_PARAM_5
|
||||
|
||||
MY_ABI_LINUX_TO_WIN_2 macro
|
||||
mov r2, r6
|
||||
mov r1, r7
|
||||
endm
|
||||
|
||||
MY_ABI_LINUX_TO_WIN_3 macro
|
||||
mov r8, r2
|
||||
mov r2, r6
|
||||
mov r1, r7
|
||||
endm
|
||||
|
||||
MY_ABI_LINUX_TO_WIN_4 macro
|
||||
mov r9, r1
|
||||
mov r8, r2
|
||||
mov r2, r6
|
||||
mov r1, r7
|
||||
endm
|
||||
|
||||
endif ; IS_LINUX
|
||||
|
||||
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro
|
||||
if (IS_LINUX gt 0)
|
||||
MY_PUSH_2_REGS
|
||||
else
|
||||
MY_PUSH_4_REGS
|
||||
endif
|
||||
endm
|
||||
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro
|
||||
if (IS_LINUX gt 0)
|
||||
MY_POP_2_REGS
|
||||
else
|
||||
MY_POP_4_REGS
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
MY_PUSH_PRESERVED_ABI_REGS macro
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
endm
|
||||
|
||||
|
||||
MY_POP_PRESERVED_ABI_REGS macro
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
endm
|
||||
|
||||
endif ; x64
|
||||
@@ -0,0 +1,258 @@
|
||||
; 7zCrcOpt.asm -- CRC32 calculation : optimized version
|
||||
; 2023-12-08 : Igor Pavlov : Public domain
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
NUM_WORDS equ 3
|
||||
UNROLL_CNT equ 2
|
||||
|
||||
if (NUM_WORDS lt 1) or (NUM_WORDS gt 64)
|
||||
.err <NUM_WORDS_IS_INCORRECT>
|
||||
endif
|
||||
if (UNROLL_CNT lt 1)
|
||||
.err <UNROLL_CNT_IS_INCORRECT>
|
||||
endif
|
||||
|
||||
rD equ r2
|
||||
rD_x equ x2
|
||||
rN equ r7
|
||||
rT equ r5
|
||||
|
||||
ifndef x64
|
||||
if (IS_CDECL gt 0)
|
||||
crc_OFFS equ (REG_SIZE * 5)
|
||||
data_OFFS equ (REG_SIZE + crc_OFFS)
|
||||
size_OFFS equ (REG_SIZE + data_OFFS)
|
||||
else
|
||||
size_OFFS equ (REG_SIZE * 5)
|
||||
endif
|
||||
table_OFFS equ (REG_SIZE + size_OFFS)
|
||||
endif
|
||||
|
||||
; rN + rD is same speed as rD, but we reduce one instruction in loop
|
||||
SRCDAT_1 equ rN + rD * 1 + 1 *
|
||||
SRCDAT_4 equ rN + rD * 1 + 4 *
|
||||
|
||||
CRC macro op:req, dest:req, src:req, t:req
|
||||
op dest, dword ptr [rT + @CatStr(src, _R) * 4 + 0400h * (t)]
|
||||
endm
|
||||
|
||||
CRC_XOR macro dest:req, src:req, t:req
|
||||
CRC xor, dest, src, t
|
||||
endm
|
||||
|
||||
CRC_MOV macro dest:req, src:req, t:req
|
||||
CRC mov, dest, src, t
|
||||
endm
|
||||
|
||||
MOVZXLO macro dest:req, src:req
|
||||
movzx dest, @CatStr(src, _L)
|
||||
endm
|
||||
|
||||
MOVZXHI macro dest:req, src:req
|
||||
movzx dest, @CatStr(src, _H)
|
||||
endm
|
||||
|
||||
; movzx x0, x0_L - is slow in some cpus (ivb), if same register for src and dest
|
||||
; movzx x3, x0_L sometimes is 0 cycles latency (not always)
|
||||
; movzx x3, x0_L sometimes is 0.5 cycles latency
|
||||
; movzx x3, x0_H is 2 cycles latency in some cpus
|
||||
|
||||
CRC1b macro
|
||||
movzx x6, byte ptr [rD]
|
||||
MOVZXLO x3, x0
|
||||
inc rD
|
||||
shr x0, 8
|
||||
xor x6, x3
|
||||
CRC_XOR x0, x6, 0
|
||||
dec rN
|
||||
endm
|
||||
|
||||
LOAD_1 macro dest:req, t:req, iter:req, index:req
|
||||
movzx dest, byte ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + index)]
|
||||
endm
|
||||
|
||||
LOAD_2 macro dest:req, t:req, iter:req, index:req
|
||||
movzx dest, word ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + index)]
|
||||
endm
|
||||
|
||||
CRC_QUAD macro nn, t:req, iter:req
|
||||
ifdef x64
|
||||
; paired memory loads give 1-3% speed gain, but it uses more registers
|
||||
LOAD_2 x3, t, iter, 0
|
||||
LOAD_2 x9, t, iter, 2
|
||||
MOVZXLO x6, x3
|
||||
shr x3, 8
|
||||
CRC_XOR nn, x6, t * 4 + 3
|
||||
MOVZXLO x6, x9
|
||||
shr x9, 8
|
||||
CRC_XOR nn, x3, t * 4 + 2
|
||||
CRC_XOR nn, x6, t * 4 + 1
|
||||
CRC_XOR nn, x9, t * 4 + 0
|
||||
elseif 0
|
||||
LOAD_2 x3, t, iter, 0
|
||||
MOVZXLO x6, x3
|
||||
shr x3, 8
|
||||
CRC_XOR nn, x6, t * 4 + 3
|
||||
CRC_XOR nn, x3, t * 4 + 2
|
||||
LOAD_2 x3, t, iter, 2
|
||||
MOVZXLO x6, x3
|
||||
shr x3, 8
|
||||
CRC_XOR nn, x6, t * 4 + 1
|
||||
CRC_XOR nn, x3, t * 4 + 0
|
||||
elseif 0
|
||||
LOAD_1 x3, t, iter, 0
|
||||
LOAD_1 x6, t, iter, 1
|
||||
CRC_XOR nn, x3, t * 4 + 3
|
||||
CRC_XOR nn, x6, t * 4 + 2
|
||||
LOAD_1 x3, t, iter, 2
|
||||
LOAD_1 x6, t, iter, 3
|
||||
CRC_XOR nn, x3, t * 4 + 1
|
||||
CRC_XOR nn, x6, t * 4 + 0
|
||||
else
|
||||
; 32-bit load is better if there is only one read port (core2)
|
||||
; but that code can be slower if there are 2 read ports (snb)
|
||||
mov x3, dword ptr [SRCDAT_1 (4 * (NUM_WORDS - 1 - t + iter * NUM_WORDS) + 0)]
|
||||
MOVZXLO x6, x3
|
||||
CRC_XOR nn, x6, t * 4 + 3
|
||||
MOVZXHI x6, x3
|
||||
shr x3, 16
|
||||
CRC_XOR nn, x6, t * 4 + 2
|
||||
MOVZXLO x6, x3
|
||||
shr x3, 8
|
||||
CRC_XOR nn, x6, t * 4 + 1
|
||||
CRC_XOR nn, x3, t * 4 + 0
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
LAST equ (4 * (NUM_WORDS - 1))
|
||||
|
||||
CRC_ITER macro qq, nn, iter
|
||||
mov nn, [SRCDAT_4 (NUM_WORDS * (1 + iter))]
|
||||
|
||||
i = 0
|
||||
rept NUM_WORDS - 1
|
||||
CRC_QUAD nn, i, iter
|
||||
i = i + 1
|
||||
endm
|
||||
|
||||
MOVZXLO x6, qq
|
||||
mov x3, qq
|
||||
shr x3, 24
|
||||
CRC_XOR nn, x6, LAST + 3
|
||||
CRC_XOR nn, x3, LAST + 0
|
||||
ror qq, 16
|
||||
MOVZXLO x6, qq
|
||||
shr qq, 24
|
||||
CRC_XOR nn, x6, LAST + 1
|
||||
if ((UNROLL_CNT and 1) eq 1) and (iter eq (UNROLL_CNT - 1))
|
||||
CRC_MOV qq, qq, LAST + 2
|
||||
xor qq, nn
|
||||
else
|
||||
CRC_XOR nn, qq, LAST + 2
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
; + 4 for prefetching next 4-bytes after current iteration
|
||||
NUM_BYTES_LIMIT equ (NUM_WORDS * 4 * UNROLL_CNT + 4)
|
||||
ALIGN_MASK equ 3
|
||||
|
||||
|
||||
; MY_PROC @CatStr(CrcUpdateT, 12), 4
|
||||
MY_PROC @CatStr(CrcUpdateT, %(NUM_WORDS * 4)), 4
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
ifdef x64
|
||||
mov x0, REG_ABI_PARAM_0_x ; x0 = x1(win) / x7(linux)
|
||||
mov rT, REG_ABI_PARAM_3 ; r5 = r9(win) / x1(linux)
|
||||
mov rN, REG_ABI_PARAM_2 ; r7 = r8(win) / r2(linux)
|
||||
; mov rD, REG_ABI_PARAM_1 ; r2 = r2(win)
|
||||
if (IS_LINUX gt 0)
|
||||
mov rD, REG_ABI_PARAM_1 ; r2 = r6
|
||||
endif
|
||||
else
|
||||
if (IS_CDECL gt 0)
|
||||
mov x0, [r4 + crc_OFFS]
|
||||
mov rD, [r4 + data_OFFS]
|
||||
else
|
||||
mov x0, REG_ABI_PARAM_0_x
|
||||
endif
|
||||
mov rN, [r4 + size_OFFS]
|
||||
mov rT, [r4 + table_OFFS]
|
||||
endif
|
||||
|
||||
cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK
|
||||
jb crc_end
|
||||
@@:
|
||||
test rD_x, ALIGN_MASK ; test rD, ALIGN_MASK
|
||||
jz @F
|
||||
CRC1b
|
||||
jmp @B
|
||||
@@:
|
||||
xor x0, dword ptr [rD]
|
||||
lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)]
|
||||
sub rD, rN
|
||||
|
||||
align 16
|
||||
@@:
|
||||
unr_index = 0
|
||||
while unr_index lt UNROLL_CNT
|
||||
if (unr_index and 1) eq 0
|
||||
CRC_ITER x0, x1, unr_index
|
||||
else
|
||||
CRC_ITER x1, x0, unr_index
|
||||
endif
|
||||
unr_index = unr_index + 1
|
||||
endm
|
||||
|
||||
add rD, NUM_WORDS * 4 * UNROLL_CNT
|
||||
jnc @B
|
||||
|
||||
if 0
|
||||
; byte verson
|
||||
add rD, rN
|
||||
xor x0, dword ptr [rD]
|
||||
add rN, NUM_BYTES_LIMIT - 1
|
||||
else
|
||||
; 4-byte version
|
||||
add rN, 4 * NUM_WORDS * UNROLL_CNT
|
||||
sub rD, 4 * NUM_WORDS * UNROLL_CNT
|
||||
@@:
|
||||
MOVZXLO x3, x0
|
||||
MOVZXHI x1, x0
|
||||
shr x0, 16
|
||||
MOVZXLO x6, x0
|
||||
shr x0, 8
|
||||
CRC_MOV x0, x0, 0
|
||||
CRC_XOR x0, x3, 3
|
||||
CRC_XOR x0, x1, 2
|
||||
CRC_XOR x0, x6, 1
|
||||
|
||||
add rD, 4
|
||||
if (NUM_WORDS * UNROLL_CNT) ne 1
|
||||
jc @F
|
||||
xor x0, [SRCDAT_4 0]
|
||||
jmp @B
|
||||
@@:
|
||||
endif
|
||||
add rD, rN
|
||||
add rN, 4 - 1
|
||||
|
||||
endif
|
||||
|
||||
sub rN, rD
|
||||
crc_end:
|
||||
test rN, rN
|
||||
jz func_end
|
||||
@@:
|
||||
CRC1b
|
||||
jnz @B
|
||||
|
||||
func_end:
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
MY_ENDP
|
||||
|
||||
end
|
||||
@@ -0,0 +1,742 @@
|
||||
; AesOpt.asm -- AES optimized code for x86 AES hardware instructions
|
||||
; 2021-12-25 : Igor Pavlov : Public domain
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
ifdef __ASMC__
|
||||
use_vaes_256 equ 1
|
||||
else
|
||||
ifdef ymm0
|
||||
use_vaes_256 equ 1
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifdef use_vaes_256
|
||||
ECHO "++ VAES 256"
|
||||
else
|
||||
ECHO "-- NO VAES 256"
|
||||
endif
|
||||
|
||||
ifdef x64
|
||||
ECHO "x86-64"
|
||||
else
|
||||
ECHO "x86"
|
||||
if (IS_CDECL gt 0)
|
||||
ECHO "ABI : CDECL"
|
||||
else
|
||||
ECHO "ABI : no CDECL : FASTCALL"
|
||||
endif
|
||||
endif
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
ECHO "ABI : LINUX"
|
||||
else
|
||||
ECHO "ABI : WINDOWS"
|
||||
endif
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
ifndef x64
|
||||
.686
|
||||
.xmm
|
||||
endif
|
||||
|
||||
|
||||
; MY_ALIGN EQU ALIGN(64)
|
||||
MY_ALIGN EQU
|
||||
|
||||
SEG_ALIGN EQU MY_ALIGN
|
||||
|
||||
MY_SEG_PROC macro name:req, numParams:req
|
||||
; seg_name equ @CatStr(_TEXT$, name)
|
||||
; seg_name SEGMENT SEG_ALIGN 'CODE'
|
||||
MY_PROC name, numParams
|
||||
endm
|
||||
|
||||
MY_SEG_ENDP macro
|
||||
; seg_name ENDS
|
||||
endm
|
||||
|
||||
|
||||
NUM_AES_KEYS_MAX equ 15
|
||||
|
||||
; the number of push operators in function PROLOG
|
||||
if (IS_LINUX eq 0) or (IS_X64 eq 0)
|
||||
num_regs_push equ 2
|
||||
stack_param_offset equ (REG_SIZE * (1 + num_regs_push))
|
||||
endif
|
||||
|
||||
ifdef x64
|
||||
num_param equ REG_ABI_PARAM_2
|
||||
else
|
||||
if (IS_CDECL gt 0)
|
||||
; size_t size
|
||||
; void * data
|
||||
; UInt32 * aes
|
||||
; ret-ip <- (r4)
|
||||
aes_OFFS equ (stack_param_offset)
|
||||
data_OFFS equ (REG_SIZE + aes_OFFS)
|
||||
size_OFFS equ (REG_SIZE + data_OFFS)
|
||||
num_param equ [r4 + size_OFFS]
|
||||
else
|
||||
num_param equ [r4 + stack_param_offset]
|
||||
endif
|
||||
endif
|
||||
|
||||
keys equ REG_PARAM_0 ; r1
|
||||
rD equ REG_PARAM_1 ; r2
|
||||
rN equ r0
|
||||
|
||||
koffs_x equ x7
|
||||
koffs_r equ r7
|
||||
|
||||
ksize_x equ x6
|
||||
ksize_r equ r6
|
||||
|
||||
keys2 equ r3
|
||||
|
||||
state equ xmm0
|
||||
key equ xmm0
|
||||
key_ymm equ ymm0
|
||||
key_ymm_n equ 0
|
||||
|
||||
ifdef x64
|
||||
ways = 11
|
||||
else
|
||||
ways = 4
|
||||
endif
|
||||
|
||||
ways_start_reg equ 1
|
||||
|
||||
iv equ @CatStr(xmm, %(ways_start_reg + ways))
|
||||
iv_ymm equ @CatStr(ymm, %(ways_start_reg + ways))
|
||||
|
||||
|
||||
WOP macro op, op2
|
||||
i = 0
|
||||
rept ways
|
||||
op @CatStr(xmm, %(ways_start_reg + i)), op2
|
||||
i = i + 1
|
||||
endm
|
||||
endm
|
||||
|
||||
|
||||
ifndef ABI_LINUX
|
||||
ifdef x64
|
||||
|
||||
; we use 32 bytes of home space in stack in WIN64-x64
|
||||
NUM_HOME_MM_REGS equ (32 / 16)
|
||||
; we preserve xmm registers starting from xmm6 in WIN64-x64
|
||||
MM_START_SAVE_REG equ 6
|
||||
|
||||
SAVE_XMM macro num_used_mm_regs:req
|
||||
num_save_mm_regs = num_used_mm_regs - MM_START_SAVE_REG
|
||||
if num_save_mm_regs GT 0
|
||||
num_save_mm_regs2 = num_save_mm_regs - NUM_HOME_MM_REGS
|
||||
; RSP is (16*x + 8) after entering the function in WIN64-x64
|
||||
stack_offset = 16 * num_save_mm_regs2 + (stack_param_offset mod 16)
|
||||
|
||||
i = 0
|
||||
rept num_save_mm_regs
|
||||
|
||||
if i eq NUM_HOME_MM_REGS
|
||||
sub r4, stack_offset
|
||||
endif
|
||||
|
||||
if i lt NUM_HOME_MM_REGS
|
||||
movdqa [r4 + stack_param_offset + i * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i))
|
||||
else
|
||||
movdqa [r4 + (i - NUM_HOME_MM_REGS) * 16], @CatStr(xmm, %(MM_START_SAVE_REG + i))
|
||||
endif
|
||||
|
||||
i = i + 1
|
||||
endm
|
||||
endif
|
||||
endm
|
||||
|
||||
RESTORE_XMM macro num_used_mm_regs:req
|
||||
if num_save_mm_regs GT 0
|
||||
i = 0
|
||||
if num_save_mm_regs2 GT 0
|
||||
rept num_save_mm_regs2
|
||||
movdqa @CatStr(xmm, %(MM_START_SAVE_REG + NUM_HOME_MM_REGS + i)), [r4 + i * 16]
|
||||
i = i + 1
|
||||
endm
|
||||
add r4, stack_offset
|
||||
endif
|
||||
|
||||
num_low_regs = num_save_mm_regs - i
|
||||
i = 0
|
||||
rept num_low_regs
|
||||
movdqa @CatStr(xmm, %(MM_START_SAVE_REG + i)), [r4 + stack_param_offset + i * 16]
|
||||
i = i + 1
|
||||
endm
|
||||
endif
|
||||
endm
|
||||
|
||||
endif ; x64
|
||||
endif ; ABI_LINUX
|
||||
|
||||
|
||||
MY_PROLOG macro num_used_mm_regs:req
|
||||
; num_regs_push: must be equal to the number of push operators
|
||||
; push r3
|
||||
; push r5
|
||||
if (IS_LINUX eq 0) or (IS_X64 eq 0)
|
||||
push r6
|
||||
push r7
|
||||
endif
|
||||
|
||||
mov rN, num_param ; don't move it; num_param can use stack pointer (r4)
|
||||
|
||||
if (IS_X64 eq 0)
|
||||
if (IS_CDECL gt 0)
|
||||
mov rD, [r4 + data_OFFS]
|
||||
mov keys, [r4 + aes_OFFS]
|
||||
endif
|
||||
elseif (IS_LINUX gt 0)
|
||||
MY_ABI_LINUX_TO_WIN_2
|
||||
endif
|
||||
|
||||
|
||||
ifndef ABI_LINUX
|
||||
ifdef x64
|
||||
SAVE_XMM num_used_mm_regs
|
||||
endif
|
||||
endif
|
||||
|
||||
mov ksize_x, [keys + 16]
|
||||
shl ksize_x, 5
|
||||
endm
|
||||
|
||||
|
||||
MY_EPILOG macro
|
||||
ifndef ABI_LINUX
|
||||
ifdef x64
|
||||
RESTORE_XMM num_save_mm_regs
|
||||
endif
|
||||
endif
|
||||
|
||||
if (IS_LINUX eq 0) or (IS_X64 eq 0)
|
||||
pop r7
|
||||
pop r6
|
||||
endif
|
||||
; pop r5
|
||||
; pop r3
|
||||
MY_ENDP
|
||||
endm
|
||||
|
||||
|
||||
OP_KEY macro op:req, offs:req
|
||||
op state, [keys + offs]
|
||||
endm
|
||||
|
||||
|
||||
WOP_KEY macro op:req, offs:req
|
||||
movdqa key, [keys + offs]
|
||||
WOP op, key
|
||||
endm
|
||||
|
||||
|
||||
; ---------- AES-CBC Decode ----------
|
||||
|
||||
|
||||
XOR_WITH_DATA macro reg, _ppp_
|
||||
pxor reg, [rD + i * 16]
|
||||
endm
|
||||
|
||||
WRITE_TO_DATA macro reg, _ppp_
|
||||
movdqa [rD + i * 16], reg
|
||||
endm
|
||||
|
||||
|
||||
; state0 equ @CatStr(xmm, %(ways_start_reg))
|
||||
|
||||
key0 equ @CatStr(xmm, %(ways_start_reg + ways + 1))
|
||||
key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1))
|
||||
|
||||
key_last equ @CatStr(xmm, %(ways_start_reg + ways + 2))
|
||||
key_last_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2))
|
||||
key_last_ymm_n equ (ways_start_reg + ways + 2)
|
||||
|
||||
NUM_CBC_REGS equ (ways_start_reg + ways + 3)
|
||||
|
||||
|
||||
MY_SEG_PROC AesCbc_Decode_HW, 3
|
||||
|
||||
AesCbc_Decode_HW_start::
|
||||
MY_PROLOG NUM_CBC_REGS
|
||||
|
||||
AesCbc_Decode_HW_start_2::
|
||||
movdqa iv, [keys]
|
||||
add keys, 32
|
||||
|
||||
movdqa key0, [keys + 1 * ksize_r]
|
||||
movdqa key_last, [keys]
|
||||
sub ksize_x, 16
|
||||
|
||||
jmp check2
|
||||
align 16
|
||||
nextBlocks2:
|
||||
WOP movdqa, [rD + i * 16]
|
||||
mov koffs_x, ksize_x
|
||||
; WOP_KEY pxor, ksize_r + 16
|
||||
WOP pxor, key0
|
||||
; align 16
|
||||
@@:
|
||||
WOP_KEY aesdec, 1 * koffs_r
|
||||
sub koffs_r, 16
|
||||
jnz @B
|
||||
; WOP_KEY aesdeclast, 0
|
||||
WOP aesdeclast, key_last
|
||||
|
||||
pxor @CatStr(xmm, %(ways_start_reg)), iv
|
||||
i = 1
|
||||
rept ways - 1
|
||||
pxor @CatStr(xmm, %(ways_start_reg + i)), [rD + i * 16 - 16]
|
||||
i = i + 1
|
||||
endm
|
||||
movdqa iv, [rD + ways * 16 - 16]
|
||||
WOP WRITE_TO_DATA
|
||||
|
||||
add rD, ways * 16
|
||||
AesCbc_Decode_HW_start_3::
|
||||
check2:
|
||||
sub rN, ways
|
||||
jnc nextBlocks2
|
||||
add rN, ways
|
||||
|
||||
sub ksize_x, 16
|
||||
|
||||
jmp check
|
||||
nextBlock:
|
||||
movdqa state, [rD]
|
||||
mov koffs_x, ksize_x
|
||||
; OP_KEY pxor, 1 * ksize_r + 32
|
||||
pxor state, key0
|
||||
; movdqa state0, [rD]
|
||||
; movdqa state, key0
|
||||
; pxor state, state0
|
||||
@@:
|
||||
OP_KEY aesdec, 1 * koffs_r + 16
|
||||
OP_KEY aesdec, 1 * koffs_r
|
||||
sub koffs_r, 32
|
||||
jnz @B
|
||||
OP_KEY aesdec, 16
|
||||
; OP_KEY aesdeclast, 0
|
||||
aesdeclast state, key_last
|
||||
|
||||
pxor state, iv
|
||||
movdqa iv, [rD]
|
||||
; movdqa iv, state0
|
||||
movdqa [rD], state
|
||||
|
||||
add rD, 16
|
||||
check:
|
||||
sub rN, 1
|
||||
jnc nextBlock
|
||||
|
||||
movdqa [keys - 32], iv
|
||||
MY_EPILOG
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------- AVX ----------
|
||||
|
||||
|
||||
AVX__WOP_n macro op
|
||||
i = 0
|
||||
rept ways
|
||||
op (ways_start_reg + i)
|
||||
i = i + 1
|
||||
endm
|
||||
endm
|
||||
|
||||
AVX__WOP macro op
|
||||
i = 0
|
||||
rept ways
|
||||
op @CatStr(ymm, %(ways_start_reg + i))
|
||||
i = i + 1
|
||||
endm
|
||||
endm
|
||||
|
||||
|
||||
AVX__WOP_KEY macro op:req, offs:req
|
||||
vmovdqa key_ymm, ymmword ptr [keys2 + offs]
|
||||
AVX__WOP_n op
|
||||
endm
|
||||
|
||||
|
||||
AVX__CBC_START macro reg
|
||||
; vpxor reg, key_ymm, ymmword ptr [rD + 32 * i]
|
||||
vpxor reg, key0_ymm, ymmword ptr [rD + 32 * i]
|
||||
endm
|
||||
|
||||
AVX__CBC_END macro reg
|
||||
if i eq 0
|
||||
vpxor reg, reg, iv_ymm
|
||||
else
|
||||
vpxor reg, reg, ymmword ptr [rD + i * 32 - 16]
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
AVX__WRITE_TO_DATA macro reg
|
||||
vmovdqu ymmword ptr [rD + 32 * i], reg
|
||||
endm
|
||||
|
||||
AVX__XOR_WITH_DATA macro reg
|
||||
vpxor reg, reg, ymmword ptr [rD + 32 * i]
|
||||
endm
|
||||
|
||||
AVX__CTR_START macro reg
|
||||
vpaddq iv_ymm, iv_ymm, one_ymm
|
||||
; vpxor reg, iv_ymm, key_ymm
|
||||
vpxor reg, iv_ymm, key0_ymm
|
||||
endm
|
||||
|
||||
|
||||
MY_VAES_INSTR_2 macro cmd, dest, a1, a2
|
||||
db 0c4H
|
||||
db 2 + 040H + 020h * (1 - (a2) / 8) + 080h * (1 - (dest) / 8)
|
||||
db 5 + 8 * ((not (a1)) and 15)
|
||||
db cmd
|
||||
db 0c0H + 8 * ((dest) and 7) + ((a2) and 7)
|
||||
endm
|
||||
|
||||
MY_VAES_INSTR macro cmd, dest, a
|
||||
MY_VAES_INSTR_2 cmd, dest, dest, a
|
||||
endm
|
||||
|
||||
MY_vaesenc macro dest, a
|
||||
MY_VAES_INSTR 0dcH, dest, a
|
||||
endm
|
||||
MY_vaesenclast macro dest, a
|
||||
MY_VAES_INSTR 0ddH, dest, a
|
||||
endm
|
||||
MY_vaesdec macro dest, a
|
||||
MY_VAES_INSTR 0deH, dest, a
|
||||
endm
|
||||
MY_vaesdeclast macro dest, a
|
||||
MY_VAES_INSTR 0dfH, dest, a
|
||||
endm
|
||||
|
||||
|
||||
AVX__VAES_DEC macro reg
|
||||
MY_vaesdec reg, key_ymm_n
|
||||
endm
|
||||
|
||||
AVX__VAES_DEC_LAST_key_last macro reg
|
||||
; MY_vaesdeclast reg, key_ymm_n
|
||||
MY_vaesdeclast reg, key_last_ymm_n
|
||||
endm
|
||||
|
||||
AVX__VAES_ENC macro reg
|
||||
MY_vaesenc reg, key_ymm_n
|
||||
endm
|
||||
|
||||
AVX__VAES_ENC_LAST macro reg
|
||||
MY_vaesenclast reg, key_ymm_n
|
||||
endm
|
||||
|
||||
AVX__vinserti128_TO_HIGH macro dest, src
|
||||
vinserti128 dest, dest, src, 1
|
||||
endm
|
||||
|
||||
|
||||
MY_PROC AesCbc_Decode_HW_256, 3
|
||||
ifdef use_vaes_256
|
||||
MY_PROLOG NUM_CBC_REGS
|
||||
|
||||
cmp rN, ways * 2
|
||||
jb AesCbc_Decode_HW_start_2
|
||||
|
||||
vmovdqa iv, xmmword ptr [keys]
|
||||
add keys, 32
|
||||
|
||||
vbroadcasti128 key0_ymm, xmmword ptr [keys + 1 * ksize_r]
|
||||
vbroadcasti128 key_last_ymm, xmmword ptr [keys]
|
||||
sub ksize_x, 16
|
||||
mov koffs_x, ksize_x
|
||||
add ksize_x, ksize_x
|
||||
|
||||
AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 2) * 32)
|
||||
push keys2
|
||||
sub r4, AVX_STACK_SUB
|
||||
; sub r4, 32
|
||||
; sub r4, ksize_r
|
||||
; lea keys2, [r4 + 32]
|
||||
mov keys2, r4
|
||||
and keys2, -32
|
||||
broad:
|
||||
vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r]
|
||||
vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm
|
||||
sub koffs_r, 16
|
||||
; jnc broad
|
||||
jnz broad
|
||||
|
||||
sub rN, ways * 2
|
||||
|
||||
align 16
|
||||
avx_cbcdec_nextBlock2:
|
||||
mov koffs_x, ksize_x
|
||||
; AVX__WOP_KEY AVX__CBC_START, 1 * koffs_r + 32
|
||||
AVX__WOP AVX__CBC_START
|
||||
@@:
|
||||
AVX__WOP_KEY AVX__VAES_DEC, 1 * koffs_r
|
||||
sub koffs_r, 32
|
||||
jnz @B
|
||||
; AVX__WOP_KEY AVX__VAES_DEC_LAST, 0
|
||||
AVX__WOP_n AVX__VAES_DEC_LAST_key_last
|
||||
|
||||
AVX__vinserti128_TO_HIGH iv_ymm, xmmword ptr [rD]
|
||||
AVX__WOP AVX__CBC_END
|
||||
|
||||
vmovdqa iv, xmmword ptr [rD + ways * 32 - 16]
|
||||
AVX__WOP AVX__WRITE_TO_DATA
|
||||
|
||||
add rD, ways * 32
|
||||
sub rN, ways * 2
|
||||
jnc avx_cbcdec_nextBlock2
|
||||
add rN, ways * 2
|
||||
|
||||
shr ksize_x, 1
|
||||
|
||||
; lea r4, [r4 + 1 * ksize_r + 32]
|
||||
add r4, AVX_STACK_SUB
|
||||
pop keys2
|
||||
|
||||
vzeroupper
|
||||
jmp AesCbc_Decode_HW_start_3
|
||||
else
|
||||
jmp AesCbc_Decode_HW_start
|
||||
endif
|
||||
MY_ENDP
|
||||
MY_SEG_ENDP
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------- AES-CBC Encode ----------
|
||||
|
||||
e0 equ xmm1
|
||||
|
||||
CENC_START_KEY equ 2
|
||||
CENC_NUM_REG_KEYS equ (3 * 2)
|
||||
; last_key equ @CatStr(xmm, %(CENC_START_KEY + CENC_NUM_REG_KEYS))
|
||||
|
||||
MY_SEG_PROC AesCbc_Encode_HW, 3
|
||||
MY_PROLOG (CENC_START_KEY + CENC_NUM_REG_KEYS + 0)
|
||||
|
||||
movdqa state, [keys]
|
||||
add keys, 32
|
||||
|
||||
i = 0
|
||||
rept CENC_NUM_REG_KEYS
|
||||
movdqa @CatStr(xmm, %(CENC_START_KEY + i)), [keys + i * 16]
|
||||
i = i + 1
|
||||
endm
|
||||
|
||||
add keys, ksize_r
|
||||
neg ksize_r
|
||||
add ksize_r, (16 * CENC_NUM_REG_KEYS)
|
||||
; movdqa last_key, [keys]
|
||||
jmp check_e
|
||||
|
||||
align 16
|
||||
nextBlock_e:
|
||||
movdqa e0, [rD]
|
||||
mov koffs_r, ksize_r
|
||||
pxor e0, @CatStr(xmm, %(CENC_START_KEY))
|
||||
pxor state, e0
|
||||
|
||||
i = 1
|
||||
rept (CENC_NUM_REG_KEYS - 1)
|
||||
aesenc state, @CatStr(xmm, %(CENC_START_KEY + i))
|
||||
i = i + 1
|
||||
endm
|
||||
|
||||
@@:
|
||||
OP_KEY aesenc, 1 * koffs_r
|
||||
OP_KEY aesenc, 1 * koffs_r + 16
|
||||
add koffs_r, 32
|
||||
jnz @B
|
||||
OP_KEY aesenclast, 0
|
||||
; aesenclast state, last_key
|
||||
|
||||
movdqa [rD], state
|
||||
add rD, 16
|
||||
check_e:
|
||||
sub rN, 1
|
||||
jnc nextBlock_e
|
||||
|
||||
; movdqa [keys - 32], state
|
||||
movdqa [keys + 1 * ksize_r - (16 * CENC_NUM_REG_KEYS) - 32], state
|
||||
MY_EPILOG
|
||||
MY_SEG_ENDP
|
||||
|
||||
|
||||
|
||||
; ---------- AES-CTR ----------
|
||||
|
||||
ifdef x64
|
||||
; ways = 11
|
||||
endif
|
||||
|
||||
|
||||
one equ @CatStr(xmm, %(ways_start_reg + ways + 1))
|
||||
one_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 1))
|
||||
key0 equ @CatStr(xmm, %(ways_start_reg + ways + 2))
|
||||
key0_ymm equ @CatStr(ymm, %(ways_start_reg + ways + 2))
|
||||
NUM_CTR_REGS equ (ways_start_reg + ways + 3)
|
||||
|
||||
INIT_CTR macro reg, _ppp_
|
||||
paddq iv, one
|
||||
movdqa reg, iv
|
||||
endm
|
||||
|
||||
|
||||
MY_SEG_PROC AesCtr_Code_HW, 3
|
||||
Ctr_start::
|
||||
MY_PROLOG NUM_CTR_REGS
|
||||
|
||||
Ctr_start_2::
|
||||
movdqa iv, [keys]
|
||||
add keys, 32
|
||||
movdqa key0, [keys]
|
||||
|
||||
add keys, ksize_r
|
||||
neg ksize_r
|
||||
add ksize_r, 16
|
||||
|
||||
Ctr_start_3::
|
||||
mov koffs_x, 1
|
||||
movd one, koffs_x
|
||||
jmp check2_c
|
||||
|
||||
align 16
|
||||
nextBlocks2_c:
|
||||
WOP INIT_CTR, 0
|
||||
mov koffs_r, ksize_r
|
||||
; WOP_KEY pxor, 1 * koffs_r -16
|
||||
WOP pxor, key0
|
||||
@@:
|
||||
WOP_KEY aesenc, 1 * koffs_r
|
||||
add koffs_r, 16
|
||||
jnz @B
|
||||
WOP_KEY aesenclast, 0
|
||||
|
||||
WOP XOR_WITH_DATA
|
||||
WOP WRITE_TO_DATA
|
||||
add rD, ways * 16
|
||||
check2_c:
|
||||
sub rN, ways
|
||||
jnc nextBlocks2_c
|
||||
add rN, ways
|
||||
|
||||
sub keys, 16
|
||||
add ksize_r, 16
|
||||
|
||||
jmp check_c
|
||||
|
||||
; align 16
|
||||
nextBlock_c:
|
||||
paddq iv, one
|
||||
; movdqa state, [keys + 1 * koffs_r - 16]
|
||||
movdqa state, key0
|
||||
mov koffs_r, ksize_r
|
||||
pxor state, iv
|
||||
|
||||
@@:
|
||||
OP_KEY aesenc, 1 * koffs_r
|
||||
OP_KEY aesenc, 1 * koffs_r + 16
|
||||
add koffs_r, 32
|
||||
jnz @B
|
||||
OP_KEY aesenc, 0
|
||||
OP_KEY aesenclast, 16
|
||||
|
||||
pxor state, [rD]
|
||||
movdqa [rD], state
|
||||
add rD, 16
|
||||
check_c:
|
||||
sub rN, 1
|
||||
jnc nextBlock_c
|
||||
|
||||
; movdqa [keys - 32], iv
|
||||
movdqa [keys + 1 * ksize_r - 16 - 32], iv
|
||||
MY_EPILOG
|
||||
|
||||
|
||||
MY_PROC AesCtr_Code_HW_256, 3
|
||||
ifdef use_vaes_256
|
||||
MY_PROLOG NUM_CTR_REGS
|
||||
|
||||
cmp rN, ways * 2
|
||||
jb Ctr_start_2
|
||||
|
||||
vbroadcasti128 iv_ymm, xmmword ptr [keys]
|
||||
add keys, 32
|
||||
vbroadcasti128 key0_ymm, xmmword ptr [keys]
|
||||
mov koffs_x, 1
|
||||
vmovd one, koffs_x
|
||||
vpsubq iv_ymm, iv_ymm, one_ymm
|
||||
vpaddq one, one, one
|
||||
AVX__vinserti128_TO_HIGH one_ymm, one
|
||||
|
||||
add keys, ksize_r
|
||||
sub ksize_x, 16
|
||||
neg ksize_r
|
||||
mov koffs_r, ksize_r
|
||||
add ksize_r, ksize_r
|
||||
|
||||
AVX_STACK_SUB = ((NUM_AES_KEYS_MAX + 1 - 1) * 32)
|
||||
push keys2
|
||||
lea keys2, [r4 - 32]
|
||||
sub r4, AVX_STACK_SUB
|
||||
and keys2, -32
|
||||
vbroadcasti128 key_ymm, xmmword ptr [keys]
|
||||
vmovdqa ymmword ptr [keys2], key_ymm
|
||||
@@:
|
||||
vbroadcasti128 key_ymm, xmmword ptr [keys + 1 * koffs_r]
|
||||
vmovdqa ymmword ptr [keys2 + koffs_r * 2], key_ymm
|
||||
add koffs_r, 16
|
||||
jnz @B
|
||||
|
||||
sub rN, ways * 2
|
||||
|
||||
align 16
|
||||
avx_ctr_nextBlock2:
|
||||
mov koffs_r, ksize_r
|
||||
AVX__WOP AVX__CTR_START
|
||||
; AVX__WOP_KEY AVX__CTR_START, 1 * koffs_r - 32
|
||||
@@:
|
||||
AVX__WOP_KEY AVX__VAES_ENC, 1 * koffs_r
|
||||
add koffs_r, 32
|
||||
jnz @B
|
||||
AVX__WOP_KEY AVX__VAES_ENC_LAST, 0
|
||||
|
||||
AVX__WOP AVX__XOR_WITH_DATA
|
||||
AVX__WOP AVX__WRITE_TO_DATA
|
||||
|
||||
add rD, ways * 32
|
||||
sub rN, ways * 2
|
||||
jnc avx_ctr_nextBlock2
|
||||
add rN, ways * 2
|
||||
|
||||
vextracti128 iv, iv_ymm, 1
|
||||
sar ksize_r, 1
|
||||
|
||||
add r4, AVX_STACK_SUB
|
||||
pop keys2
|
||||
|
||||
vzeroupper
|
||||
jmp Ctr_start_3
|
||||
else
|
||||
jmp Ctr_start
|
||||
endif
|
||||
MY_ENDP
|
||||
MY_SEG_ENDP
|
||||
|
||||
end
|
||||
@@ -0,0 +1,540 @@
|
||||
; LzFindOpt.asm -- ASM version of GetMatchesSpecN_2() function
|
||||
; 2024-06-18: Igor Pavlov : Public domain
|
||||
;
|
||||
|
||||
ifndef x64
|
||||
; x64=1
|
||||
; .err <x64_IS_REQUIRED>
|
||||
endif
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
ifndef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
|
||||
if (IS_LINUX gt 0)
|
||||
Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1
|
||||
else
|
||||
Z7_LZ_FIND_OPT_ASM_USE_SEGMENT equ 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
|
||||
_TEXT$LZFINDOPT SEGMENT ALIGN(64) 'CODE'
|
||||
MY_ALIGN macro num:req
|
||||
align num
|
||||
; align 16
|
||||
endm
|
||||
else
|
||||
MY_ALIGN macro num:req
|
||||
; We expect that ".text" is aligned for 16-bytes.
|
||||
; So we don't need large alignment inside our function.
|
||||
align 16
|
||||
endm
|
||||
endif
|
||||
|
||||
|
||||
MY_ALIGN_16 macro
|
||||
MY_ALIGN 16
|
||||
endm
|
||||
|
||||
MY_ALIGN_32 macro
|
||||
MY_ALIGN 32
|
||||
endm
|
||||
|
||||
MY_ALIGN_64 macro
|
||||
MY_ALIGN 64
|
||||
endm
|
||||
|
||||
|
||||
t0_L equ x0_L
|
||||
t0_x equ x0
|
||||
t0 equ r0
|
||||
t1_x equ x3
|
||||
t1 equ r3
|
||||
|
||||
cp_x equ t1_x
|
||||
cp_r equ t1
|
||||
m equ x5
|
||||
m_r equ r5
|
||||
len_x equ x6
|
||||
len equ r6
|
||||
diff_x equ x7
|
||||
diff equ r7
|
||||
len0 equ r10
|
||||
len1_x equ x11
|
||||
len1 equ r11
|
||||
maxLen_x equ x12
|
||||
maxLen equ r12
|
||||
d equ r13
|
||||
ptr0 equ r14
|
||||
ptr1 equ r15
|
||||
|
||||
d_lim equ m_r
|
||||
cycSize equ len_x
|
||||
hash_lim equ len0
|
||||
delta1_x equ len1_x
|
||||
delta1_r equ len1
|
||||
delta_x equ maxLen_x
|
||||
delta_r equ maxLen
|
||||
hash equ ptr0
|
||||
src equ ptr1
|
||||
|
||||
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
|
||||
; r1 r2 r8 r9 : win32
|
||||
; r7 r6 r2 r1 r8 r9 : linux
|
||||
|
||||
lenLimit equ r8
|
||||
lenLimit_x equ x8
|
||||
; pos_r equ r2
|
||||
pos equ x2
|
||||
cur equ r1
|
||||
son equ r9
|
||||
|
||||
else
|
||||
|
||||
lenLimit equ REG_ABI_PARAM_2
|
||||
lenLimit_x equ REG_ABI_PARAM_2_x
|
||||
pos equ REG_ABI_PARAM_1_x
|
||||
cur equ REG_ABI_PARAM_0
|
||||
son equ REG_ABI_PARAM_3
|
||||
|
||||
endif
|
||||
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
maxLen_OFFS equ (REG_SIZE * (6 + 1))
|
||||
else
|
||||
cutValue_OFFS equ (REG_SIZE * (8 + 1 + 4))
|
||||
d_OFFS equ (REG_SIZE + cutValue_OFFS)
|
||||
maxLen_OFFS equ (REG_SIZE + d_OFFS)
|
||||
endif
|
||||
hash_OFFS equ (REG_SIZE + maxLen_OFFS)
|
||||
limit_OFFS equ (REG_SIZE + hash_OFFS)
|
||||
size_OFFS equ (REG_SIZE + limit_OFFS)
|
||||
cycPos_OFFS equ (REG_SIZE + size_OFFS)
|
||||
cycSize_OFFS equ (REG_SIZE + cycPos_OFFS)
|
||||
posRes_OFFS equ (REG_SIZE + cycSize_OFFS)
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
else
|
||||
cutValue_PAR equ [r0 + cutValue_OFFS]
|
||||
d_PAR equ [r0 + d_OFFS]
|
||||
endif
|
||||
maxLen_PAR equ [r0 + maxLen_OFFS]
|
||||
hash_PAR equ [r0 + hash_OFFS]
|
||||
limit_PAR equ [r0 + limit_OFFS]
|
||||
size_PAR equ [r0 + size_OFFS]
|
||||
cycPos_PAR equ [r0 + cycPos_OFFS]
|
||||
cycSize_PAR equ [r0 + cycSize_OFFS]
|
||||
posRes_PAR equ [r0 + posRes_OFFS]
|
||||
|
||||
|
||||
cutValue_VAR equ DWORD PTR [r4 + 8 * 0]
|
||||
cutValueCur_VAR equ DWORD PTR [r4 + 8 * 0 + 4]
|
||||
cycPos_VAR equ DWORD PTR [r4 + 8 * 1 + 0]
|
||||
cycSize_VAR equ DWORD PTR [r4 + 8 * 1 + 4]
|
||||
hash_VAR equ QWORD PTR [r4 + 8 * 2]
|
||||
limit_VAR equ QWORD PTR [r4 + 8 * 3]
|
||||
size_VAR equ QWORD PTR [r4 + 8 * 4]
|
||||
distances equ QWORD PTR [r4 + 8 * 5]
|
||||
maxLen_VAR equ QWORD PTR [r4 + 8 * 6]
|
||||
|
||||
Old_RSP equ QWORD PTR [r4 + 8 * 7]
|
||||
LOCAL_SIZE equ 8 * 8
|
||||
|
||||
COPY_VAR_32 macro dest_var, src_var
|
||||
mov x3, src_var
|
||||
mov dest_var, x3
|
||||
endm
|
||||
|
||||
COPY_VAR_64 macro dest_var, src_var
|
||||
mov r3, src_var
|
||||
mov dest_var, r3
|
||||
endm
|
||||
|
||||
|
||||
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
|
||||
; MY_ALIGN_64
|
||||
else
|
||||
MY_ALIGN_16
|
||||
endif
|
||||
MY_PROC GetMatchesSpecN_2, 13
|
||||
MY_PUSH_PRESERVED_ABI_REGS
|
||||
mov r0, RSP
|
||||
lea r3, [r0 - LOCAL_SIZE]
|
||||
and r3, -64
|
||||
mov RSP, r3
|
||||
mov Old_RSP, r0
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
mov d, REG_ABI_PARAM_5 ; r13 = r9
|
||||
mov cutValue_VAR, REG_ABI_PARAM_4_x ; = r8
|
||||
mov son, REG_ABI_PARAM_3 ; r9 = r1
|
||||
mov r8, REG_ABI_PARAM_2 ; r8 = r2
|
||||
mov pos, REG_ABI_PARAM_1_x ; r2 = x6
|
||||
mov r1, REG_ABI_PARAM_0 ; r1 = r7
|
||||
else
|
||||
COPY_VAR_32 cutValue_VAR, cutValue_PAR
|
||||
mov d, d_PAR
|
||||
endif
|
||||
|
||||
COPY_VAR_64 limit_VAR, limit_PAR
|
||||
|
||||
mov hash_lim, size_PAR
|
||||
mov size_VAR, hash_lim
|
||||
|
||||
mov cp_x, cycPos_PAR
|
||||
mov hash, hash_PAR
|
||||
|
||||
mov cycSize, cycSize_PAR
|
||||
mov cycSize_VAR, cycSize
|
||||
|
||||
; we want cur in (rcx). So we change the cur and lenLimit variables
|
||||
sub lenLimit, cur
|
||||
neg lenLimit_x
|
||||
inc lenLimit_x
|
||||
|
||||
mov t0_x, maxLen_PAR
|
||||
sub t0, lenLimit
|
||||
mov maxLen_VAR, t0
|
||||
|
||||
jmp main_loop
|
||||
|
||||
MY_ALIGN_64
|
||||
fill_empty:
|
||||
; ptr0 = *ptr1 = kEmptyHashValue;
|
||||
mov QWORD PTR [ptr1], 0
|
||||
inc pos
|
||||
inc cp_x
|
||||
mov DWORD PTR [d - 4], 0
|
||||
cmp d, limit_VAR
|
||||
jae fin
|
||||
cmp hash, hash_lim
|
||||
je fin
|
||||
|
||||
; MY_ALIGN_64
|
||||
main_loop:
|
||||
; UInt32 delta = *hash++;
|
||||
mov diff_x, [hash] ; delta
|
||||
add hash, 4
|
||||
; mov cycPos_VAR, cp_x
|
||||
|
||||
inc cur
|
||||
add d, 4
|
||||
mov m, pos
|
||||
sub m, diff_x; ; matchPos
|
||||
|
||||
; CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;
|
||||
lea ptr1, [son + 8 * cp_r]
|
||||
; mov cycSize, cycSize_VAR
|
||||
cmp pos, cycSize
|
||||
jb directMode ; if (pos < cycSize_VAR)
|
||||
|
||||
; CYC MODE
|
||||
|
||||
cmp diff_x, cycSize
|
||||
jae fill_empty ; if (delta >= cycSize_VAR)
|
||||
|
||||
xor t0_x, t0_x
|
||||
mov cycPos_VAR, cp_x
|
||||
sub cp_x, diff_x
|
||||
; jae prepare_for_tree_loop
|
||||
; add cp_x, cycSize
|
||||
cmovb t0_x, cycSize
|
||||
add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0)
|
||||
jmp prepare_for_tree_loop
|
||||
|
||||
|
||||
directMode:
|
||||
cmp diff_x, pos
|
||||
je fill_empty ; if (delta == pos)
|
||||
jae fin_error ; if (delta >= pos)
|
||||
|
||||
mov cycPos_VAR, cp_x
|
||||
mov cp_x, m
|
||||
|
||||
prepare_for_tree_loop:
|
||||
mov len0, lenLimit
|
||||
mov hash_VAR, hash
|
||||
; CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1;
|
||||
lea ptr0, [ptr1 + 4]
|
||||
; UInt32 *_distances = ++d;
|
||||
mov distances, d
|
||||
|
||||
neg len0
|
||||
mov len1, len0
|
||||
|
||||
mov t0_x, cutValue_VAR
|
||||
mov maxLen, maxLen_VAR
|
||||
mov cutValueCur_VAR, t0_x
|
||||
|
||||
MY_ALIGN_32
|
||||
tree_loop:
|
||||
neg diff
|
||||
mov len, len0
|
||||
cmp len1, len0
|
||||
cmovb len, len1 ; len = (len1 < len0 ? len1 : len0);
|
||||
add diff, cur
|
||||
|
||||
mov t0_x, [son + cp_r * 8] ; prefetch
|
||||
movzx t0_x, BYTE PTR [diff + 1 * len]
|
||||
lea cp_r, [son + cp_r * 8]
|
||||
cmp [cur + 1 * len], t0_L
|
||||
je matched_1
|
||||
|
||||
jb left_0
|
||||
|
||||
mov [ptr1], m
|
||||
mov m, [cp_r + 4]
|
||||
lea ptr1, [cp_r + 4]
|
||||
sub diff, cur ; FIX32
|
||||
jmp next_node
|
||||
|
||||
MY_ALIGN_32
|
||||
left_0:
|
||||
mov [ptr0], m
|
||||
mov m, [cp_r]
|
||||
mov ptr0, cp_r
|
||||
sub diff, cur ; FIX32
|
||||
; jmp next_node
|
||||
|
||||
; ------------ NEXT NODE ------------
|
||||
; MY_ALIGN_32
|
||||
next_node:
|
||||
mov cycSize, cycSize_VAR
|
||||
dec cutValueCur_VAR
|
||||
je finish_tree
|
||||
|
||||
add diff_x, pos ; prev_match = pos + diff
|
||||
cmp m, diff_x
|
||||
jae fin_error ; if (new_match >= prev_match)
|
||||
|
||||
mov diff_x, pos
|
||||
sub diff_x, m ; delta = pos - new_match
|
||||
cmp pos, cycSize
|
||||
jae cyc_mode_2 ; if (pos >= cycSize)
|
||||
|
||||
mov cp_x, m
|
||||
test m, m
|
||||
jne tree_loop ; if (m != 0)
|
||||
|
||||
finish_tree:
|
||||
; ptr0 = *ptr1 = kEmptyHashValue;
|
||||
mov DWORD PTR [ptr0], 0
|
||||
mov DWORD PTR [ptr1], 0
|
||||
|
||||
inc pos
|
||||
|
||||
; _distances[-1] = (UInt32)(d - _distances);
|
||||
mov t0, distances
|
||||
mov t1, d
|
||||
sub t1, t0
|
||||
shr t1_x, 2
|
||||
mov [t0 - 4], t1_x
|
||||
|
||||
cmp d, limit_VAR
|
||||
jae fin ; if (d >= limit)
|
||||
|
||||
mov cp_x, cycPos_VAR
|
||||
mov hash, hash_VAR
|
||||
mov hash_lim, size_VAR
|
||||
inc cp_x
|
||||
cmp hash, hash_lim
|
||||
jne main_loop ; if (hash != size)
|
||||
jmp fin
|
||||
|
||||
|
||||
MY_ALIGN_32
|
||||
cyc_mode_2:
|
||||
cmp diff_x, cycSize
|
||||
jae finish_tree ; if (delta >= cycSize)
|
||||
|
||||
mov cp_x, cycPos_VAR
|
||||
xor t0_x, t0_x
|
||||
sub cp_x, diff_x ; cp_x = cycPos - delta
|
||||
cmovb t0_x, cycSize
|
||||
add cp_x, t0_x ; cp_x += (cycPos < delta ? cycSize : 0)
|
||||
jmp tree_loop
|
||||
|
||||
|
||||
MY_ALIGN_32
|
||||
matched_1:
|
||||
|
||||
inc len
|
||||
; cmp len_x, lenLimit_x
|
||||
je short lenLimit_reach
|
||||
movzx t0_x, BYTE PTR [diff + 1 * len]
|
||||
cmp [cur + 1 * len], t0_L
|
||||
jne mismatch
|
||||
|
||||
|
||||
MY_ALIGN_32
|
||||
match_loop:
|
||||
; while (++len != lenLimit) (len[diff] != len[0]) ;
|
||||
|
||||
inc len
|
||||
; cmp len_x, lenLimit_x
|
||||
je short lenLimit_reach
|
||||
movzx t0_x, BYTE PTR [diff + 1 * len]
|
||||
cmp BYTE PTR [cur + 1 * len], t0_L
|
||||
je match_loop
|
||||
|
||||
mismatch:
|
||||
jb left_2
|
||||
|
||||
mov [ptr1], m
|
||||
mov m, [cp_r + 4]
|
||||
lea ptr1, [cp_r + 4]
|
||||
mov len1, len
|
||||
|
||||
jmp max_update
|
||||
|
||||
MY_ALIGN_32
|
||||
left_2:
|
||||
mov [ptr0], m
|
||||
mov m, [cp_r]
|
||||
mov ptr0, cp_r
|
||||
mov len0, len
|
||||
|
||||
max_update:
|
||||
sub diff, cur ; restore diff
|
||||
|
||||
cmp maxLen, len
|
||||
jae next_node
|
||||
|
||||
mov maxLen, len
|
||||
add len, lenLimit
|
||||
mov [d], len_x
|
||||
mov t0_x, diff_x
|
||||
not t0_x
|
||||
mov [d + 4], t0_x
|
||||
add d, 8
|
||||
|
||||
jmp next_node
|
||||
|
||||
|
||||
|
||||
MY_ALIGN_32
|
||||
lenLimit_reach:
|
||||
|
||||
mov delta_r, cur
|
||||
sub delta_r, diff
|
||||
lea delta1_r, [delta_r - 1]
|
||||
|
||||
mov t0_x, [cp_r]
|
||||
mov [ptr1], t0_x
|
||||
mov t0_x, [cp_r + 4]
|
||||
mov [ptr0], t0_x
|
||||
|
||||
mov [d], lenLimit_x
|
||||
mov [d + 4], delta1_x
|
||||
add d, 8
|
||||
|
||||
; _distances[-1] = (UInt32)(d - _distances);
|
||||
mov t0, distances
|
||||
mov t1, d
|
||||
sub t1, t0
|
||||
shr t1_x, 2
|
||||
mov [t0 - 4], t1_x
|
||||
|
||||
mov hash, hash_VAR
|
||||
mov hash_lim, size_VAR
|
||||
|
||||
inc pos
|
||||
mov cp_x, cycPos_VAR
|
||||
inc cp_x
|
||||
|
||||
mov d_lim, limit_VAR
|
||||
mov cycSize, cycSize_VAR
|
||||
; if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)
|
||||
; break;
|
||||
cmp hash, hash_lim
|
||||
je fin
|
||||
cmp d, d_lim
|
||||
jae fin
|
||||
cmp delta_x, [hash]
|
||||
jne main_loop
|
||||
movzx t0_x, BYTE PTR [diff]
|
||||
cmp [cur], t0_L
|
||||
jne main_loop
|
||||
|
||||
; jmp main_loop ; bypass for debug
|
||||
|
||||
mov cycPos_VAR, cp_x
|
||||
shl len, 3 ; cycSize * 8
|
||||
sub diff, cur ; restore diff
|
||||
xor t0_x, t0_x
|
||||
cmp cp_x, delta_x ; cmp (cycPos_VAR, delta)
|
||||
lea cp_r, [son + 8 * cp_r] ; dest
|
||||
lea src, [cp_r + 8 * diff]
|
||||
cmovb t0, len ; t0 = (cycPos_VAR < delta ? cycSize * 8 : 0)
|
||||
add src, t0
|
||||
add len, son ; len = son + cycSize * 8
|
||||
|
||||
|
||||
MY_ALIGN_32
|
||||
long_loop:
|
||||
add hash, 4
|
||||
|
||||
; *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff];
|
||||
|
||||
mov t0, [src]
|
||||
add src, 8
|
||||
mov [cp_r], t0
|
||||
add cp_r, 8
|
||||
cmp src, len
|
||||
cmove src, son ; if end of (son) buffer is reached, we wrap to begin
|
||||
|
||||
mov DWORD PTR [d], 2
|
||||
mov [d + 4], lenLimit_x
|
||||
mov [d + 8], delta1_x
|
||||
add d, 12
|
||||
|
||||
inc cur
|
||||
|
||||
cmp hash, hash_lim
|
||||
je long_footer
|
||||
cmp delta_x, [hash]
|
||||
jne long_footer
|
||||
movzx t0_x, BYTE PTR [diff + 1 * cur]
|
||||
cmp [cur], t0_L
|
||||
jne long_footer
|
||||
cmp d, d_lim
|
||||
jb long_loop
|
||||
|
||||
long_footer:
|
||||
sub cp_r, son
|
||||
shr cp_r, 3
|
||||
add pos, cp_x
|
||||
sub pos, cycPos_VAR
|
||||
mov cycSize, cycSize_VAR
|
||||
|
||||
cmp d, d_lim
|
||||
jae fin
|
||||
cmp hash, hash_lim
|
||||
jne main_loop
|
||||
jmp fin
|
||||
|
||||
|
||||
|
||||
fin_error:
|
||||
xor d, d
|
||||
|
||||
fin:
|
||||
mov RSP, Old_RSP
|
||||
mov t0, [r4 + posRes_OFFS]
|
||||
mov [t0], pos
|
||||
mov r0, d
|
||||
|
||||
MY_POP_PRESERVED_ABI_REGS
|
||||
MY_ENDP
|
||||
|
||||
ifdef Z7_LZ_FIND_OPT_ASM_USE_SEGMENT
|
||||
_TEXT$LZFINDOPT ENDS
|
||||
endif
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,263 @@
|
||||
; Sha1Opt.asm -- SHA-1 optimized code for SHA-1 x86 hardware instructions
|
||||
; 2024-06-16 : Igor Pavlov : Public domain
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CONST SEGMENT READONLY
|
||||
|
||||
align 16
|
||||
Reverse_Endian_Mask db 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
CONST ENDS
|
||||
|
||||
; _TEXT$SHA1OPT SEGMENT 'CODE'
|
||||
|
||||
ifndef x64
|
||||
.686
|
||||
.xmm
|
||||
endif
|
||||
|
||||
ifdef x64
|
||||
rNum equ REG_ABI_PARAM_2
|
||||
if (IS_LINUX eq 0)
|
||||
LOCAL_SIZE equ (16 * 2)
|
||||
endif
|
||||
else
|
||||
rNum equ r0
|
||||
LOCAL_SIZE equ (16 * 1)
|
||||
endif
|
||||
|
||||
rState equ REG_ABI_PARAM_0
|
||||
rData equ REG_ABI_PARAM_1
|
||||
|
||||
|
||||
MY_sha1rnds4 macro a1, a2, imm
|
||||
db 0fH, 03aH, 0ccH, (0c0H + a1 * 8 + a2), imm
|
||||
endm
|
||||
|
||||
MY_SHA_INSTR macro cmd, a1, a2
|
||||
db 0fH, 038H, cmd, (0c0H + a1 * 8 + a2)
|
||||
endm
|
||||
|
||||
cmd_sha1nexte equ 0c8H
|
||||
cmd_sha1msg1 equ 0c9H
|
||||
cmd_sha1msg2 equ 0caH
|
||||
|
||||
MY_sha1nexte macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha1nexte, a1, a2
|
||||
endm
|
||||
|
||||
MY_sha1msg1 macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha1msg1, a1, a2
|
||||
endm
|
||||
|
||||
MY_sha1msg2 macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha1msg2, a1, a2
|
||||
endm
|
||||
|
||||
MY_PROLOG macro
|
||||
ifdef x64
|
||||
if (IS_LINUX eq 0)
|
||||
movdqa [r4 + 8], xmm6
|
||||
movdqa [r4 + 8 + 16], xmm7
|
||||
sub r4, LOCAL_SIZE + 8
|
||||
movdqa [r4 ], xmm8
|
||||
movdqa [r4 + 16], xmm9
|
||||
endif
|
||||
else ; x86
|
||||
if (IS_CDECL gt 0)
|
||||
mov rState, [r4 + REG_SIZE * 1]
|
||||
mov rData, [r4 + REG_SIZE * 2]
|
||||
mov rNum, [r4 + REG_SIZE * 3]
|
||||
else ; fastcall
|
||||
mov rNum, [r4 + REG_SIZE * 1]
|
||||
endif
|
||||
push r5
|
||||
mov r5, r4
|
||||
and r4, -16
|
||||
sub r4, LOCAL_SIZE
|
||||
endif
|
||||
endm
|
||||
|
||||
MY_EPILOG macro
|
||||
ifdef x64
|
||||
if (IS_LINUX eq 0)
|
||||
movdqa xmm8, [r4]
|
||||
movdqa xmm9, [r4 + 16]
|
||||
add r4, LOCAL_SIZE + 8
|
||||
movdqa xmm6, [r4 + 8]
|
||||
movdqa xmm7, [r4 + 8 + 16]
|
||||
endif
|
||||
else ; x86
|
||||
mov r4, r5
|
||||
pop r5
|
||||
endif
|
||||
MY_ENDP
|
||||
endm
|
||||
|
||||
|
||||
e0_N equ 0
|
||||
e1_N equ 1
|
||||
abcd_N equ 2
|
||||
e0_save_N equ 3
|
||||
w_regs equ 4
|
||||
|
||||
e0 equ @CatStr(xmm, %e0_N)
|
||||
e1 equ @CatStr(xmm, %e1_N)
|
||||
abcd equ @CatStr(xmm, %abcd_N)
|
||||
e0_save equ @CatStr(xmm, %e0_save_N)
|
||||
|
||||
|
||||
ifdef x64
|
||||
abcd_save equ xmm8
|
||||
mask2 equ xmm9
|
||||
else
|
||||
abcd_save equ [r4]
|
||||
mask2 equ e1
|
||||
endif
|
||||
|
||||
LOAD_MASK macro
|
||||
movdqa mask2, XMMWORD PTR Reverse_Endian_Mask
|
||||
endm
|
||||
|
||||
LOAD_W macro k:req
|
||||
movdqu @CatStr(xmm, %(w_regs + k)), [rData + (16 * (k))]
|
||||
pshufb @CatStr(xmm, %(w_regs + k)), mask2
|
||||
endm
|
||||
|
||||
|
||||
; pre2 can be 2 or 3 (recommended)
|
||||
pre2 equ 3
|
||||
pre1 equ (pre2 + 1)
|
||||
|
||||
NUM_ROUNDS4 equ 20
|
||||
|
||||
RND4 macro k
|
||||
movdqa @CatStr(xmm, %(e0_N + ((k + 1) mod 2))), abcd
|
||||
MY_sha1rnds4 abcd_N, (e0_N + (k mod 2)), k / 5
|
||||
|
||||
nextM = (w_regs + ((k + 1) mod 4))
|
||||
|
||||
if (k EQ NUM_ROUNDS4 - 1)
|
||||
nextM = e0_save_N
|
||||
endif
|
||||
|
||||
MY_sha1nexte (e0_N + ((k + 1) mod 2)), nextM
|
||||
|
||||
if (k GE (4 - pre2)) AND (k LT (NUM_ROUNDS4 - pre2))
|
||||
pxor @CatStr(xmm, %(w_regs + ((k + pre2) mod 4))), @CatStr(xmm, %(w_regs + ((k + pre2 - 2) mod 4)))
|
||||
endif
|
||||
|
||||
if (k GE (4 - pre1)) AND (k LT (NUM_ROUNDS4 - pre1))
|
||||
MY_sha1msg1 (w_regs + ((k + pre1) mod 4)), (w_regs + ((k + pre1 - 3) mod 4))
|
||||
endif
|
||||
|
||||
if (k GE (4 - pre2)) AND (k LT (NUM_ROUNDS4 - pre2))
|
||||
MY_sha1msg2 (w_regs + ((k + pre2) mod 4)), (w_regs + ((k + pre2 - 1) mod 4))
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
REVERSE_STATE macro
|
||||
; abcd ; dcba
|
||||
; e0 ; 000e
|
||||
pshufd abcd, abcd, 01bH ; abcd
|
||||
pshufd e0, e0, 01bH ; e000
|
||||
endm
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MY_PROC Sha1_UpdateBlocks_HW, 3
|
||||
MY_PROLOG
|
||||
|
||||
cmp rNum, 0
|
||||
je end_c
|
||||
|
||||
movdqu abcd, [rState] ; dcba
|
||||
movd e0, dword ptr [rState + 16] ; 000e
|
||||
|
||||
REVERSE_STATE
|
||||
|
||||
ifdef x64
|
||||
LOAD_MASK
|
||||
endif
|
||||
|
||||
align 16
|
||||
nextBlock:
|
||||
movdqa abcd_save, abcd
|
||||
movdqa e0_save, e0
|
||||
|
||||
ifndef x64
|
||||
LOAD_MASK
|
||||
endif
|
||||
|
||||
LOAD_W 0
|
||||
LOAD_W 1
|
||||
LOAD_W 2
|
||||
LOAD_W 3
|
||||
|
||||
paddd e0, @CatStr(xmm, %(w_regs))
|
||||
k = 0
|
||||
rept NUM_ROUNDS4
|
||||
RND4 k
|
||||
k = k + 1
|
||||
endm
|
||||
|
||||
paddd abcd, abcd_save
|
||||
|
||||
|
||||
add rData, 64
|
||||
sub rNum, 1
|
||||
jnz nextBlock
|
||||
|
||||
REVERSE_STATE
|
||||
|
||||
movdqu [rState], abcd
|
||||
movd dword ptr [rState + 16], e0
|
||||
|
||||
end_c:
|
||||
MY_EPILOG
|
||||
|
||||
; _TEXT$SHA1OPT ENDS
|
||||
|
||||
end
|
||||
@@ -0,0 +1,275 @@
|
||||
; Sha256Opt.asm -- SHA-256 optimized code for SHA-256 x86 hardware instructions
|
||||
; 2024-06-16 : Igor Pavlov : Public domain
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
; .data
|
||||
; public K
|
||||
|
||||
; we can use external SHA256_K_ARRAY defined in Sha256.c
|
||||
; but we must guarantee that SHA256_K_ARRAY is aligned for 16-bytes
|
||||
|
||||
COMMENT @
|
||||
ifdef x64
|
||||
K_CONST equ SHA256_K_ARRAY
|
||||
else
|
||||
K_CONST equ _SHA256_K_ARRAY
|
||||
endif
|
||||
EXTRN K_CONST:xmmword
|
||||
@
|
||||
|
||||
CONST SEGMENT READONLY
|
||||
|
||||
align 16
|
||||
Reverse_Endian_Mask db 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12
|
||||
|
||||
; COMMENT @
|
||||
align 16
|
||||
K_CONST \
|
||||
DD 0428a2f98H, 071374491H, 0b5c0fbcfH, 0e9b5dba5H
|
||||
DD 03956c25bH, 059f111f1H, 0923f82a4H, 0ab1c5ed5H
|
||||
DD 0d807aa98H, 012835b01H, 0243185beH, 0550c7dc3H
|
||||
DD 072be5d74H, 080deb1feH, 09bdc06a7H, 0c19bf174H
|
||||
DD 0e49b69c1H, 0efbe4786H, 00fc19dc6H, 0240ca1ccH
|
||||
DD 02de92c6fH, 04a7484aaH, 05cb0a9dcH, 076f988daH
|
||||
DD 0983e5152H, 0a831c66dH, 0b00327c8H, 0bf597fc7H
|
||||
DD 0c6e00bf3H, 0d5a79147H, 006ca6351H, 014292967H
|
||||
DD 027b70a85H, 02e1b2138H, 04d2c6dfcH, 053380d13H
|
||||
DD 0650a7354H, 0766a0abbH, 081c2c92eH, 092722c85H
|
||||
DD 0a2bfe8a1H, 0a81a664bH, 0c24b8b70H, 0c76c51a3H
|
||||
DD 0d192e819H, 0d6990624H, 0f40e3585H, 0106aa070H
|
||||
DD 019a4c116H, 01e376c08H, 02748774cH, 034b0bcb5H
|
||||
DD 0391c0cb3H, 04ed8aa4aH, 05b9cca4fH, 0682e6ff3H
|
||||
DD 0748f82eeH, 078a5636fH, 084c87814H, 08cc70208H
|
||||
DD 090befffaH, 0a4506cebH, 0bef9a3f7H, 0c67178f2H
|
||||
; @
|
||||
|
||||
CONST ENDS
|
||||
|
||||
; _TEXT$SHA256OPT SEGMENT 'CODE'
|
||||
|
||||
ifndef x64
|
||||
.686
|
||||
.xmm
|
||||
endif
|
||||
|
||||
; jwasm-based assemblers for linux and linker from new versions of binutils
|
||||
; can generate incorrect code for load [ARRAY + offset] instructions.
|
||||
; 22.00: we load K_CONST offset to (rTable) register to avoid jwasm+binutils problem
|
||||
rTable equ r0
|
||||
; rTable equ K_CONST
|
||||
|
||||
ifdef x64
|
||||
rNum equ REG_ABI_PARAM_2
|
||||
if (IS_LINUX eq 0)
|
||||
LOCAL_SIZE equ (16 * 2)
|
||||
endif
|
||||
else
|
||||
rNum equ r3
|
||||
LOCAL_SIZE equ (16 * 1)
|
||||
endif
|
||||
|
||||
rState equ REG_ABI_PARAM_0
|
||||
rData equ REG_ABI_PARAM_1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MY_SHA_INSTR macro cmd, a1, a2
|
||||
db 0fH, 038H, cmd, (0c0H + a1 * 8 + a2)
|
||||
endm
|
||||
|
||||
cmd_sha256rnds2 equ 0cbH
|
||||
cmd_sha256msg1 equ 0ccH
|
||||
cmd_sha256msg2 equ 0cdH
|
||||
|
||||
MY_sha256rnds2 macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha256rnds2, a1, a2
|
||||
endm
|
||||
|
||||
MY_sha256msg1 macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha256msg1, a1, a2
|
||||
endm
|
||||
|
||||
MY_sha256msg2 macro a1, a2
|
||||
MY_SHA_INSTR cmd_sha256msg2, a1, a2
|
||||
endm
|
||||
|
||||
MY_PROLOG macro
|
||||
ifdef x64
|
||||
if (IS_LINUX eq 0)
|
||||
movdqa [r4 + 8], xmm6
|
||||
movdqa [r4 + 8 + 16], xmm7
|
||||
sub r4, LOCAL_SIZE + 8
|
||||
movdqa [r4 ], xmm8
|
||||
movdqa [r4 + 16], xmm9
|
||||
endif
|
||||
else ; x86
|
||||
push r3
|
||||
push r5
|
||||
mov r5, r4
|
||||
NUM_PUSH_REGS equ 2
|
||||
PARAM_OFFSET equ (REG_SIZE * (1 + NUM_PUSH_REGS))
|
||||
if (IS_CDECL gt 0)
|
||||
mov rState, [r4 + PARAM_OFFSET]
|
||||
mov rData, [r4 + PARAM_OFFSET + REG_SIZE * 1]
|
||||
mov rNum, [r4 + PARAM_OFFSET + REG_SIZE * 2]
|
||||
else ; fastcall
|
||||
mov rNum, [r4 + PARAM_OFFSET]
|
||||
endif
|
||||
and r4, -16
|
||||
sub r4, LOCAL_SIZE
|
||||
endif
|
||||
endm
|
||||
|
||||
MY_EPILOG macro
|
||||
ifdef x64
|
||||
if (IS_LINUX eq 0)
|
||||
movdqa xmm8, [r4]
|
||||
movdqa xmm9, [r4 + 16]
|
||||
add r4, LOCAL_SIZE + 8
|
||||
movdqa xmm6, [r4 + 8]
|
||||
movdqa xmm7, [r4 + 8 + 16]
|
||||
endif
|
||||
else ; x86
|
||||
mov r4, r5
|
||||
pop r5
|
||||
pop r3
|
||||
endif
|
||||
MY_ENDP
|
||||
endm
|
||||
|
||||
|
||||
msg equ xmm0
|
||||
tmp equ xmm0
|
||||
state0_N equ 2
|
||||
state1_N equ 3
|
||||
w_regs equ 4
|
||||
|
||||
|
||||
state1_save equ xmm1
|
||||
state0 equ @CatStr(xmm, %state0_N)
|
||||
state1 equ @CatStr(xmm, %state1_N)
|
||||
|
||||
|
||||
ifdef x64
|
||||
state0_save equ xmm8
|
||||
mask2 equ xmm9
|
||||
else
|
||||
state0_save equ [r4]
|
||||
mask2 equ xmm0
|
||||
endif
|
||||
|
||||
LOAD_MASK macro
|
||||
movdqa mask2, XMMWORD PTR Reverse_Endian_Mask
|
||||
endm
|
||||
|
||||
LOAD_W macro k:req
|
||||
movdqu @CatStr(xmm, %(w_regs + k)), [rData + (16 * (k))]
|
||||
pshufb @CatStr(xmm, %(w_regs + k)), mask2
|
||||
endm
|
||||
|
||||
|
||||
; pre1 <= 4 && pre2 >= 1 && pre1 > pre2 && (pre1 - pre2) <= 1
|
||||
pre1 equ 3
|
||||
pre2 equ 2
|
||||
|
||||
|
||||
|
||||
RND4 macro k
|
||||
movdqa msg, xmmword ptr [rTable + (k) * 16]
|
||||
paddd msg, @CatStr(xmm, %(w_regs + ((k + 0) mod 4)))
|
||||
MY_sha256rnds2 state0_N, state1_N
|
||||
pshufd msg, msg, 0eH
|
||||
|
||||
if (k GE (4 - pre1)) AND (k LT (16 - pre1))
|
||||
; w4[0] = msg1(w4[-4], w4[-3])
|
||||
MY_sha256msg1 (w_regs + ((k + pre1) mod 4)), (w_regs + ((k + pre1 - 3) mod 4))
|
||||
endif
|
||||
|
||||
MY_sha256rnds2 state1_N, state0_N
|
||||
|
||||
if (k GE (4 - pre2)) AND (k LT (16 - pre2))
|
||||
movdqa tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 1) mod 4)))
|
||||
palignr tmp, @CatStr(xmm, %(w_regs + ((k + pre2 - 2) mod 4))), 4
|
||||
paddd @CatStr(xmm, %(w_regs + ((k + pre2) mod 4))), tmp
|
||||
; w4[0] = msg2(w4[0], w4[-1])
|
||||
MY_sha256msg2 %(w_regs + ((k + pre2) mod 4)), %(w_regs + ((k + pre2 - 1) mod 4))
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
REVERSE_STATE macro
|
||||
; state0 ; dcba
|
||||
; state1 ; hgfe
|
||||
pshufd tmp, state0, 01bH ; abcd
|
||||
pshufd state0, state1, 01bH ; efgh
|
||||
movdqa state1, state0 ; efgh
|
||||
punpcklqdq state0, tmp ; cdgh
|
||||
punpckhqdq state1, tmp ; abef
|
||||
endm
|
||||
|
||||
|
||||
MY_PROC Sha256_UpdateBlocks_HW, 3
|
||||
MY_PROLOG
|
||||
|
||||
lea rTable, [K_CONST]
|
||||
|
||||
cmp rNum, 0
|
||||
je end_c
|
||||
|
||||
movdqu state0, [rState] ; dcba
|
||||
movdqu state1, [rState + 16] ; hgfe
|
||||
|
||||
REVERSE_STATE
|
||||
|
||||
ifdef x64
|
||||
LOAD_MASK
|
||||
endif
|
||||
|
||||
align 16
|
||||
nextBlock:
|
||||
movdqa state0_save, state0
|
||||
movdqa state1_save, state1
|
||||
|
||||
ifndef x64
|
||||
LOAD_MASK
|
||||
endif
|
||||
|
||||
LOAD_W 0
|
||||
LOAD_W 1
|
||||
LOAD_W 2
|
||||
LOAD_W 3
|
||||
|
||||
|
||||
k = 0
|
||||
rept 16
|
||||
RND4 k
|
||||
k = k + 1
|
||||
endm
|
||||
|
||||
paddd state0, state0_save
|
||||
paddd state1, state1_save
|
||||
|
||||
add rData, 64
|
||||
sub rNum, 1
|
||||
jnz nextBlock
|
||||
|
||||
REVERSE_STATE
|
||||
|
||||
movdqu [rState], state0
|
||||
movdqu [rState + 16], state1
|
||||
|
||||
end_c:
|
||||
MY_EPILOG
|
||||
|
||||
; _TEXT$SHA256OPT ENDS
|
||||
|
||||
end
|
||||
@@ -0,0 +1,860 @@
|
||||
; SortTest.asm -- ASM version of HeapSort() function
|
||||
; Igor Pavlov : Public domain
|
||||
|
||||
include ../../../../Asm/x86/7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
ifndef Z7_SORT_ASM_USE_SEGMENT
|
||||
if (IS_LINUX gt 0)
|
||||
; Z7_SORT_ASM_USE_SEGMENT equ 1
|
||||
else
|
||||
; Z7_SORT_ASM_USE_SEGMENT equ 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef Z7_SORT_ASM_USE_SEGMENT
|
||||
_TEXT$Z7_SORT SEGMENT ALIGN(64) 'CODE'
|
||||
MY_ALIGN macro num:req
|
||||
align num
|
||||
endm
|
||||
else
|
||||
MY_ALIGN macro num:req
|
||||
; We expect that ".text" is aligned for 16-bytes.
|
||||
; So we don't need large alignment inside our function.
|
||||
align 16
|
||||
endm
|
||||
endif
|
||||
|
||||
|
||||
MY_ALIGN_16 macro
|
||||
MY_ALIGN 16
|
||||
endm
|
||||
|
||||
MY_ALIGN_32 macro
|
||||
MY_ALIGN 32
|
||||
endm
|
||||
|
||||
MY_ALIGN_64 macro
|
||||
MY_ALIGN 64
|
||||
endm
|
||||
|
||||
ifdef x64
|
||||
|
||||
NUM_PREFETCH_LEVELS equ 3 ; to prefetch 1x 64-bytes line (is good for most cases)
|
||||
; NUM_PREFETCH_LEVELS equ 4 ; to prefetch 2x 64-bytes lines (better for big arrays)
|
||||
|
||||
acc equ x0
|
||||
k equ r0
|
||||
k_x equ x0
|
||||
|
||||
p equ r1
|
||||
|
||||
s equ r2
|
||||
s_x equ x2
|
||||
|
||||
a0 equ x3
|
||||
t0 equ a0
|
||||
|
||||
a3 equ x5
|
||||
qq equ a3
|
||||
|
||||
a1 equ x6
|
||||
t1 equ a1
|
||||
t1_r equ r6
|
||||
|
||||
a2 equ x7
|
||||
t2 equ a2
|
||||
|
||||
i equ r8
|
||||
e0 equ x8
|
||||
|
||||
e1 equ x9
|
||||
|
||||
num_last equ r10
|
||||
num_last_x equ x10
|
||||
|
||||
next4_lim equ r11
|
||||
pref_lim equ r12
|
||||
|
||||
|
||||
|
||||
SORT_2_WITH_TEMP_REG macro b0, b1, temp_reg
|
||||
mov temp_reg, b0
|
||||
cmp b0, b1
|
||||
cmovae b0, b1 ; min
|
||||
cmovae b1, temp_reg ; max
|
||||
endm
|
||||
|
||||
SORT macro b0, b1
|
||||
SORT_2_WITH_TEMP_REG b0, b1, acc
|
||||
endm
|
||||
|
||||
LOAD macro dest:req, index:req
|
||||
mov dest, [p + 4 * index]
|
||||
endm
|
||||
|
||||
STORE macro reg:req, index:req
|
||||
mov [p + 4 * index], reg
|
||||
endm
|
||||
|
||||
|
||||
if (NUM_PREFETCH_LEVELS gt 3)
|
||||
num_prefetches equ (1 SHL (NUM_PREFETCH_LEVELS - 3))
|
||||
else
|
||||
num_prefetches equ 1
|
||||
endif
|
||||
|
||||
PREFETCH_OP macro offs
|
||||
cur_offset = 7 * 4 ; it's average offset in 64-bytes cache line.
|
||||
; cur_offset = 0 ; we can use zero offset, if we are sure that array is aligned for 64-bytes.
|
||||
rept num_prefetches
|
||||
if 1
|
||||
prefetcht0 byte ptr [p + offs + cur_offset]
|
||||
else
|
||||
mov pref_x, dword ptr [p + offs + cur_offset]
|
||||
endif
|
||||
cur_offset = cur_offset + 64
|
||||
endm
|
||||
endm
|
||||
|
||||
PREFETCH_MY macro
|
||||
if 1
|
||||
if 1
|
||||
shl k, NUM_PREFETCH_LEVELS + 3
|
||||
else
|
||||
; we delay prefetch instruction to improve main loads
|
||||
shl k, NUM_PREFETCH_LEVELS
|
||||
shl k, 3
|
||||
; shl k, 0
|
||||
endif
|
||||
PREFETCH_OP k
|
||||
elseif 1
|
||||
shl k, 3
|
||||
PREFETCH_OP k * (1 SHL NUM_PREFETCH_LEVELS) ; change it
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
STEP_1 macro exit_label, prefetch_macro
|
||||
use_cmov_1 equ 1 ; set 1 for cmov, but it's slower in some cases
|
||||
; set 0 for LOAD after adc s, 0
|
||||
cmp t0, t1
|
||||
if use_cmov_1
|
||||
cmovb t0, t1
|
||||
; STORE t0, k
|
||||
endif
|
||||
adc s, 0
|
||||
if use_cmov_1 eq 0
|
||||
LOAD t0, s
|
||||
endif
|
||||
cmp qq, t0
|
||||
jae exit_label
|
||||
if 1 ; use_cmov_1 eq 0
|
||||
STORE t0, k
|
||||
endif
|
||||
prefetch_macro
|
||||
mov t0, [p + s * 8]
|
||||
mov t1, [p + s * 8 + 4]
|
||||
mov k, s
|
||||
add s, s ; slower for some cpus
|
||||
; lea s, dword ptr [s + s] ; slower for some cpus
|
||||
; shl s, 1 ; faster for some cpus
|
||||
; lea s, dword ptr [s * 2] ; faster for some cpus
|
||||
rept 0 ; 1000 for debug : 0 for normal
|
||||
; number of calls in generate_stage : ~0.6 of number of items
|
||||
shl k, 0
|
||||
endm
|
||||
endm
|
||||
|
||||
|
||||
STEP_2 macro exit_label, prefetch_macro
|
||||
use_cmov_2 equ 0 ; set 1 for cmov, but it's slower in some cases
|
||||
; set 0 for LOAD after adc s, 0
|
||||
cmp t0, t1
|
||||
if use_cmov_2
|
||||
mov t2, t0
|
||||
cmovb t2, t1
|
||||
; STORE t2, k
|
||||
endif
|
||||
mov t0, [p + s * 8]
|
||||
mov t1, [p + s * 8 + 4]
|
||||
cmovb t0, [p + s * 8 + 8]
|
||||
cmovb t1, [p + s * 8 + 12]
|
||||
adc s, 0
|
||||
if use_cmov_2 eq 0
|
||||
LOAD t2, s
|
||||
endif
|
||||
cmp qq, t2
|
||||
jae exit_label
|
||||
if 1 ; use_cmov_2 eq 0
|
||||
STORE t2, k
|
||||
endif
|
||||
prefetch_macro
|
||||
mov k, s
|
||||
; add s, s
|
||||
; lea s, [s + s]
|
||||
shl s, 1
|
||||
; lea s, [s * 2]
|
||||
endm
|
||||
|
||||
|
||||
MOVE_SMALLEST_UP macro STEP, use_prefetch, num_unrolls
|
||||
LOCAL exit_1, exit_2, leaves, opt_loop, last_nodes
|
||||
|
||||
; s == k * 2
|
||||
; t0 == (p)[s]
|
||||
; t1 == (p)[s + 1]
|
||||
cmp k, next4_lim
|
||||
jae leaves
|
||||
|
||||
rept num_unrolls
|
||||
STEP exit_2
|
||||
cmp k, next4_lim
|
||||
jae leaves
|
||||
endm
|
||||
|
||||
if use_prefetch
|
||||
prefetch_macro equ PREFETCH_MY
|
||||
pref_lim_2 equ pref_lim
|
||||
; lea pref_lim, dword ptr [num_last + 1]
|
||||
; shr pref_lim, NUM_PREFETCH_LEVELS + 1
|
||||
cmp k, pref_lim_2
|
||||
jae last_nodes
|
||||
else
|
||||
prefetch_macro equ
|
||||
pref_lim_2 equ next4_lim
|
||||
endif
|
||||
|
||||
MY_ALIGN_16
|
||||
opt_loop:
|
||||
STEP exit_2, prefetch_macro
|
||||
cmp k, pref_lim_2
|
||||
jb opt_loop
|
||||
|
||||
last_nodes:
|
||||
; k >= pref_lim_2
|
||||
; 2 cases are possible:
|
||||
; case-1: num_after_prefetch_levels == 0 && next4_lim = pref_lim_2
|
||||
; case-2: num_after_prefetch_levels == NUM_PREFETCH_LEVELS - 1 &&
|
||||
; next4_lim = pref_lim_2 / (NUM_PREFETCH_LEVELS - 1)
|
||||
if use_prefetch
|
||||
yyy = NUM_PREFETCH_LEVELS - 1
|
||||
while yyy
|
||||
yyy = yyy - 1
|
||||
STEP exit_2
|
||||
if yyy
|
||||
cmp k, next4_lim
|
||||
jae leaves
|
||||
endif
|
||||
endm
|
||||
endif
|
||||
|
||||
leaves:
|
||||
; k >= next4_lim == (num_last + 1) / 4 must be provided by previous code.
|
||||
; we have 2 nodes in (s) level : always
|
||||
; we can have some nodes in (s * 2) level : low probability case
|
||||
; we have no nodes in (s * 4) level
|
||||
; s == k * 2
|
||||
; t0 == (p)[s]
|
||||
; t1 == (p)[s + 1]
|
||||
cmp t0, t1
|
||||
cmovb t0, t1
|
||||
adc s, 0
|
||||
STORE t0, k
|
||||
|
||||
; t0 == (p)[s]
|
||||
; s / 2 == k : (s) is index of max item from (p)[k * 2], (p)[k * 2 + 1]
|
||||
; we have 3 possible cases here:
|
||||
; s * 2 > num_last : (s) node has no childs
|
||||
; s * 2 == num_last : (s) node has 1 leaf child that is last item of array
|
||||
; s * 2 < num_last : (s) node has 2 leaf childs. We provide (s * 4 > num_last)
|
||||
; we check for (s * 2 > num_last) before "cmp qq, t0" check, because
|
||||
; we will replace conditional jump with cmov instruction later.
|
||||
lea t1_r, dword ptr [s + s]
|
||||
cmp t1_r, num_last
|
||||
ja exit_1 ; if (s * 2 > num_last), we have no childs : it's high probability branch
|
||||
|
||||
; it's low probability branch
|
||||
; s * 2 <= num_last
|
||||
cmp qq, t0
|
||||
jae exit_2
|
||||
|
||||
; qq < t0, so we go to next level
|
||||
; we check 1 or 2 childs in next level
|
||||
mov t0, [p + s * 8]
|
||||
mov k, s
|
||||
mov s, t1_r
|
||||
cmp t1_r, num_last
|
||||
je @F ; (s == num_last) means that we have single child in tree
|
||||
|
||||
; (s < num_last) : so we must read both childs and select max of them.
|
||||
mov t1, [p + k * 8 + 4]
|
||||
cmp t0, t1
|
||||
cmovb t0, t1
|
||||
adc s, 0
|
||||
@@:
|
||||
STORE t0, k
|
||||
exit_1:
|
||||
; t0 == (p)[s], s / 2 == k : (s) is index of max item from (p)[k * 2], (p)[k * 2 + 1]
|
||||
cmp qq, t0
|
||||
cmovb k, s
|
||||
exit_2:
|
||||
STORE qq, k
|
||||
endm
|
||||
|
||||
|
||||
|
||||
|
||||
ifdef Z7_SORT_ASM_USE_SEGMENT
|
||||
; MY_ALIGN_64
|
||||
else
|
||||
MY_ALIGN_16
|
||||
endif
|
||||
|
||||
MY_PROC HeapSort, 2
|
||||
|
||||
if (IS_LINUX gt 0)
|
||||
mov p, REG_ABI_PARAM_0 ; r1 <- r7 : linux
|
||||
endif
|
||||
mov num_last, REG_ABI_PARAM_1 ; r10 <- r6 : linux
|
||||
; r10 <- r2 : win64
|
||||
cmp num_last, 2
|
||||
jb end_1
|
||||
|
||||
; MY_PUSH_PRESERVED_ABI_REGS
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
push r12
|
||||
|
||||
cmp num_last, 4
|
||||
ja sort_5
|
||||
|
||||
LOAD a0, 0
|
||||
LOAD a1, 1
|
||||
SORT a0, a1
|
||||
cmp num_last, 3
|
||||
jb end_2
|
||||
|
||||
LOAD a2, 2
|
||||
je sort_3
|
||||
|
||||
LOAD a3, 3
|
||||
SORT a2, a3
|
||||
SORT a1, a3
|
||||
STORE a3, 3
|
||||
sort_3:
|
||||
SORT a0, a2
|
||||
SORT a1, a2
|
||||
STORE a2, 2
|
||||
jmp end_2
|
||||
|
||||
sort_5:
|
||||
; (num_last > 4) is required here
|
||||
; if (num_last >= 6) : we will use optimized loop for leaf nodes loop_down_1
|
||||
mov next4_lim, num_last
|
||||
shr next4_lim, 2
|
||||
|
||||
dec num_last
|
||||
mov k, num_last
|
||||
shr k, 1
|
||||
mov i, num_last
|
||||
shr i, 2
|
||||
test num_last, 1
|
||||
jnz size_even
|
||||
|
||||
; ODD number of items. So we compare parent with single child
|
||||
LOAD t1, num_last
|
||||
LOAD t0, k
|
||||
SORT_2_WITH_TEMP_REG t1, t0, t2
|
||||
STORE t1, num_last
|
||||
STORE t0, k
|
||||
dec k
|
||||
|
||||
size_even:
|
||||
cmp k, i
|
||||
jbe loop_down ; jump for num_last == 4 case
|
||||
|
||||
if 0 ; 1 for debug
|
||||
mov r15, k
|
||||
mov r14d, 1 ; 100
|
||||
loop_benchmark:
|
||||
endif
|
||||
; optimized loop for leaf nodes:
|
||||
mov t0, [p + k * 8]
|
||||
mov t1, [p + k * 8 + 4]
|
||||
|
||||
MY_ALIGN_16
|
||||
loop_down_1:
|
||||
; we compare parent with max of childs:
|
||||
; lea s, dword ptr [2 * k]
|
||||
mov s, k
|
||||
cmp t0, t1
|
||||
cmovb t0, t1
|
||||
adc s, s
|
||||
LOAD t2, k
|
||||
STORE t0, k
|
||||
cmp t2, t0
|
||||
cmovae s, k
|
||||
dec k
|
||||
; we preload next items before STORE operation for calculated address
|
||||
mov t0, [p + k * 8]
|
||||
mov t1, [p + k * 8 + 4]
|
||||
STORE t2, s
|
||||
cmp k, i
|
||||
jne loop_down_1
|
||||
|
||||
if 0 ; 1 for debug
|
||||
mov k, r15
|
||||
dec r14d
|
||||
jnz loop_benchmark
|
||||
; jmp end_debug
|
||||
endif
|
||||
|
||||
MY_ALIGN_16
|
||||
loop_down:
|
||||
mov t0, [p + i * 8]
|
||||
mov t1, [p + i * 8 + 4]
|
||||
LOAD qq, i
|
||||
mov k, i
|
||||
lea s, dword ptr [i + i]
|
||||
; jmp end_debug
|
||||
DOWN_use_prefetch equ 0
|
||||
DOWN_num_unrolls equ 0
|
||||
MOVE_SMALLEST_UP STEP_1, DOWN_use_prefetch, DOWN_num_unrolls
|
||||
sub i, 1
|
||||
jnb loop_down
|
||||
|
||||
; jmp end_debug
|
||||
LOAD e0, 0
|
||||
LOAD e1, 1
|
||||
|
||||
LEVEL_3_LIMIT equ 8 ; 8 is default, but 7 also can work
|
||||
|
||||
cmp num_last, LEVEL_3_LIMIT + 1
|
||||
jb main_loop_sort_5
|
||||
|
||||
MY_ALIGN_16
|
||||
main_loop_sort:
|
||||
; num_last > LEVEL_3_LIMIT
|
||||
; p[size--] = p[0];
|
||||
LOAD qq, num_last
|
||||
STORE e0, num_last
|
||||
mov e0, e1
|
||||
|
||||
mov next4_lim, num_last
|
||||
shr next4_lim, 2
|
||||
mov pref_lim, num_last
|
||||
shr pref_lim, NUM_PREFETCH_LEVELS + 1
|
||||
|
||||
dec num_last
|
||||
if 0 ; 1 for debug
|
||||
; that optional optimization can improve the performance, if there are identical items in array
|
||||
; 3 times improvement : if all items in array are identical
|
||||
; 20% improvement : if items are different for 1 bit only
|
||||
; 1-10% improvement : if items are different for (2+) bits
|
||||
; no gain : if items are different
|
||||
cmp qq, e1
|
||||
jae next_iter_main
|
||||
endif
|
||||
LOAD e1, 2
|
||||
LOAD t0, 3
|
||||
mov k_x, 2
|
||||
cmp e1, t0
|
||||
cmovb e1, t0
|
||||
mov t0, [p + 4 * (4 + 0)]
|
||||
mov t1, [p + 4 * (4 + 1)]
|
||||
cmovb t0, [p + 4 * (4 + 2)]
|
||||
cmovb t1, [p + 4 * (4 + 3)]
|
||||
adc k_x, 0
|
||||
; (qq <= e1), because the tree is correctly sorted
|
||||
; also here we could check (qq >= e1) or (qq == e1) for faster exit
|
||||
lea s, dword ptr [k + k]
|
||||
MAIN_use_prefetch equ 1
|
||||
MAIN_num_unrolls equ 0
|
||||
MOVE_SMALLEST_UP STEP_2, MAIN_use_prefetch, MAIN_num_unrolls
|
||||
|
||||
next_iter_main:
|
||||
cmp num_last, LEVEL_3_LIMIT
|
||||
jne main_loop_sort
|
||||
|
||||
; num_last == LEVEL_3_LIMIT
|
||||
main_loop_sort_5:
|
||||
; 4 <= num_last <= LEVEL_3_LIMIT
|
||||
; p[size--] = p[0];
|
||||
LOAD qq, num_last
|
||||
STORE e0, num_last
|
||||
mov e0, e1
|
||||
dec num_last_x
|
||||
|
||||
LOAD e1, 2
|
||||
LOAD t0, 3
|
||||
mov k_x, 2
|
||||
cmp e1, t0
|
||||
cmovb e1, t0
|
||||
adc k_x, 0
|
||||
|
||||
lea s_x, dword ptr [k * 2]
|
||||
cmp s_x, num_last_x
|
||||
ja exit_2
|
||||
|
||||
mov t0, [p + k * 8]
|
||||
je exit_1
|
||||
|
||||
; s < num_last
|
||||
mov t1, [p + k * 8 + 4]
|
||||
cmp t0, t1
|
||||
cmovb t0, t1
|
||||
adc s_x, 0
|
||||
exit_1:
|
||||
STORE t0, k
|
||||
cmp qq, t0
|
||||
cmovb k_x, s_x
|
||||
exit_2:
|
||||
STORE qq, k
|
||||
cmp num_last_x, 3
|
||||
jne main_loop_sort_5
|
||||
|
||||
; num_last == 3 (real_size == 4)
|
||||
LOAD a0, 2
|
||||
LOAD a1, 3
|
||||
STORE e1, 2
|
||||
STORE e0, 3
|
||||
SORT a0, a1
|
||||
end_2:
|
||||
STORE a0, 0
|
||||
STORE a1, 1
|
||||
; end_debug:
|
||||
; MY_POP_PRESERVED_ABI_REGS
|
||||
pop r12
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
end_1:
|
||||
MY_ENDP
|
||||
|
||||
|
||||
|
||||
else
|
||||
; ------------ x86 32-bit ------------
|
||||
|
||||
ifdef x64
|
||||
IS_CDECL = 0
|
||||
endif
|
||||
|
||||
acc equ x0
|
||||
k equ r0
|
||||
k_x equ acc
|
||||
|
||||
p equ r1
|
||||
|
||||
num_last equ r2
|
||||
num_last_x equ x2
|
||||
|
||||
a0 equ x3
|
||||
t0 equ a0
|
||||
|
||||
a3 equ x5
|
||||
i equ r5
|
||||
e0 equ a3
|
||||
|
||||
a1 equ x6
|
||||
qq equ a1
|
||||
|
||||
a2 equ x7
|
||||
s equ r7
|
||||
s_x equ a2
|
||||
|
||||
|
||||
SORT macro b0, b1
|
||||
cmp b1, b0
|
||||
jae @F
|
||||
if 1
|
||||
xchg b0, b1
|
||||
else
|
||||
mov acc, b0
|
||||
mov b0, b1 ; min
|
||||
mov b1, acc ; max
|
||||
endif
|
||||
@@:
|
||||
endm
|
||||
|
||||
LOAD macro dest:req, index:req
|
||||
mov dest, [p + 4 * index]
|
||||
endm
|
||||
|
||||
STORE macro reg:req, index:req
|
||||
mov [p + 4 * index], reg
|
||||
endm
|
||||
|
||||
|
||||
STEP_1 macro exit_label
|
||||
mov t0, [p + k * 8]
|
||||
cmp t0, [p + k * 8 + 4]
|
||||
adc s, 0
|
||||
LOAD t0, s
|
||||
STORE t0, k ; we lookahed stooring for most expected branch
|
||||
cmp qq, t0
|
||||
jae exit_label
|
||||
; STORE t0, k ; use if
|
||||
mov k, s
|
||||
add s, s
|
||||
; lea s, dword ptr [s + s]
|
||||
; shl s, 1
|
||||
; lea s, dword ptr [s * 2]
|
||||
endm
|
||||
|
||||
STEP_BRANCH macro exit_label
|
||||
mov t0, [p + k * 8]
|
||||
cmp t0, [p + k * 8 + 4]
|
||||
jae @F
|
||||
inc s
|
||||
mov t0, [p + k * 8 + 4]
|
||||
@@:
|
||||
cmp qq, t0
|
||||
jae exit_label
|
||||
STORE t0, k
|
||||
mov k, s
|
||||
add s, s
|
||||
endm
|
||||
|
||||
|
||||
|
||||
MOVE_SMALLEST_UP macro STEP, num_unrolls, exit_2
|
||||
LOCAL leaves, opt_loop, single
|
||||
|
||||
; s == k * 2
|
||||
rept num_unrolls
|
||||
cmp s, num_last
|
||||
jae leaves
|
||||
STEP_1 exit_2
|
||||
endm
|
||||
cmp s, num_last
|
||||
jb opt_loop
|
||||
|
||||
leaves:
|
||||
; (s >= num_last)
|
||||
jne exit_2
|
||||
single:
|
||||
; (s == num_last)
|
||||
mov t0, [p + k * 8]
|
||||
cmp qq, t0
|
||||
jae exit_2
|
||||
STORE t0, k
|
||||
mov k, s
|
||||
jmp exit_2
|
||||
|
||||
MY_ALIGN_16
|
||||
opt_loop:
|
||||
STEP exit_2
|
||||
cmp s, num_last
|
||||
jb opt_loop
|
||||
je single
|
||||
exit_2:
|
||||
STORE qq, k
|
||||
endm
|
||||
|
||||
|
||||
|
||||
|
||||
ifdef Z7_SORT_ASM_USE_SEGMENT
|
||||
; MY_ALIGN_64
|
||||
else
|
||||
MY_ALIGN_16
|
||||
endif
|
||||
|
||||
MY_PROC HeapSort, 2
|
||||
ifdef x64
|
||||
if (IS_LINUX gt 0)
|
||||
mov num_last, REG_ABI_PARAM_1 ; r2 <- r6 : linux
|
||||
mov p, REG_ABI_PARAM_0 ; r1 <- r7 : linux
|
||||
endif
|
||||
elseif (IS_CDECL gt 0)
|
||||
mov num_last, [r4 + REG_SIZE * 2]
|
||||
mov p, [r4 + REG_SIZE * 1]
|
||||
endif
|
||||
cmp num_last, 2
|
||||
jb end_1
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
|
||||
cmp num_last, 4
|
||||
ja sort_5
|
||||
|
||||
LOAD a0, 0
|
||||
LOAD a1, 1
|
||||
SORT a0, a1
|
||||
cmp num_last, 3
|
||||
jb end_2
|
||||
|
||||
LOAD a2, 2
|
||||
je sort_3
|
||||
|
||||
LOAD a3, 3
|
||||
SORT a2, a3
|
||||
SORT a1, a3
|
||||
STORE a3, 3
|
||||
sort_3:
|
||||
SORT a0, a2
|
||||
SORT a1, a2
|
||||
STORE a2, 2
|
||||
jmp end_2
|
||||
|
||||
sort_5:
|
||||
; num_last > 4
|
||||
lea i, dword ptr [num_last - 2]
|
||||
dec num_last
|
||||
test i, 1
|
||||
jz loop_down
|
||||
|
||||
; single child
|
||||
mov t0, [p + num_last * 4]
|
||||
mov qq, [p + num_last * 2]
|
||||
dec i
|
||||
cmp qq, t0
|
||||
jae loop_down
|
||||
|
||||
mov [p + num_last * 2], t0
|
||||
mov [p + num_last * 4], qq
|
||||
|
||||
MY_ALIGN_16
|
||||
loop_down:
|
||||
mov t0, [p + i * 4]
|
||||
cmp t0, [p + i * 4 + 4]
|
||||
mov k, i
|
||||
mov qq, [p + i * 2]
|
||||
adc k, 0
|
||||
LOAD t0, k
|
||||
cmp qq, t0
|
||||
jae down_next
|
||||
mov [p + i * 2], t0
|
||||
lea s, dword ptr [k + k]
|
||||
|
||||
DOWN_num_unrolls equ 0
|
||||
MOVE_SMALLEST_UP STEP_1, DOWN_num_unrolls, down_exit_label
|
||||
down_next:
|
||||
sub i, 2
|
||||
jnb loop_down
|
||||
; jmp end_debug
|
||||
|
||||
LOAD e0, 0
|
||||
|
||||
MY_ALIGN_16
|
||||
main_loop_sort:
|
||||
; num_last > 3
|
||||
mov t0, [p + 2 * 4]
|
||||
cmp t0, [p + 3 * 4]
|
||||
LOAD qq, num_last
|
||||
STORE e0, num_last
|
||||
LOAD e0, 1
|
||||
mov s_x, 2
|
||||
mov k_x, 1
|
||||
adc s, 0
|
||||
LOAD t0, s
|
||||
dec num_last
|
||||
cmp qq, t0
|
||||
jae main_exit_label
|
||||
STORE t0, 1
|
||||
mov k, s
|
||||
add s, s
|
||||
if 1
|
||||
; for branch data prefetch mode :
|
||||
; it's faster for large arrays : larger than (1 << 13) items.
|
||||
MAIN_num_unrolls equ 10
|
||||
STEP_LOOP equ STEP_BRANCH
|
||||
else
|
||||
MAIN_num_unrolls equ 0
|
||||
STEP_LOOP equ STEP_1
|
||||
endif
|
||||
|
||||
MOVE_SMALLEST_UP STEP_LOOP, MAIN_num_unrolls, main_exit_label
|
||||
|
||||
; jmp end_debug
|
||||
cmp num_last, 3
|
||||
jne main_loop_sort
|
||||
|
||||
; num_last == 3 (real_size == 4)
|
||||
LOAD a0, 2
|
||||
LOAD a1, 3
|
||||
LOAD a2, 1
|
||||
STORE e0, 3 ; e0 is alias for a3
|
||||
STORE a2, 2
|
||||
SORT a0, a1
|
||||
end_2:
|
||||
STORE a0, 0
|
||||
STORE a1, 1
|
||||
; end_debug:
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
end_1:
|
||||
MY_ENDP
|
||||
|
||||
endif
|
||||
|
||||
ifdef Z7_SORT_ASM_USE_SEGMENT
|
||||
_TEXT$Z7_SORT ENDS
|
||||
endif
|
||||
|
||||
if 0
|
||||
LEA_IS_D8 (R64) [R2 * 4 + 16]
|
||||
Lat : TP
|
||||
2 : 1 : adl-e
|
||||
2 : 3 p056 adl-p
|
||||
1 : 2 : p15 hsw-rocket
|
||||
1 : 2 : p01 snb-ivb
|
||||
1 : 1 : p1 conroe-wsm
|
||||
1 : 4 : zen3,zen4
|
||||
2 : 4 : zen1,zen2
|
||||
|
||||
LEA_B_IS (R64) [R2 + R3 * 4]
|
||||
Lat : TP
|
||||
1 : 1 : adl-e
|
||||
2 : 3 p056 adl-p
|
||||
1 : 2 : p15 hsw-rocket
|
||||
1 : 2 : p01 snb-ivb
|
||||
1 : 1 : p1 nhm-wsm
|
||||
1 : 1 : p0 conroe-wsm
|
||||
1 : 4 : zen3,zen4
|
||||
2 :2,4 : zen1,zen2
|
||||
|
||||
LEA_B_IS_D8 (R64) [R2 + R3 * 4 + 16]
|
||||
Lat : TP
|
||||
2 : 1 : adl-e
|
||||
2 : 3 p056 adl-p
|
||||
1 : 2 : p15 ice-rocket
|
||||
3 : 1 : p1/p15 hsw-rocket
|
||||
3 : 1 : p01 snb-ivb
|
||||
1 : 1 : p1 nhm-wsm
|
||||
1 : 1 : p0 conroe-wsm
|
||||
2,1 : 2 : zen3,zen4
|
||||
2 : 2 : zen1,zen2
|
||||
|
||||
CMOVB (R64, R64)
|
||||
Lat : TP
|
||||
1,2 : 2 : adl-e
|
||||
1 : 2 p06 adl-p
|
||||
1 : 2 : p06 bwd-rocket
|
||||
1,2 : 2 : p0156+p06 hsw
|
||||
1,2 :1.5 : p015+p05 snb-ivb
|
||||
1,2 : 1 : p015+p05 nhm
|
||||
1 : 1 : 2*p015 conroe
|
||||
1 : 2 : zen3,zen4
|
||||
1 : 4 : zen1,zen2
|
||||
|
||||
ADC (R64, 0)
|
||||
Lat : TP
|
||||
1,2 : 2 : adl-e
|
||||
1 : 2 p06 adl-p
|
||||
1 : 2 : p06 bwd-rocket
|
||||
1 :1.5 : p0156+p06 hsw
|
||||
1 :1.5 : p015+p05 snb-ivb
|
||||
2 : 1 : 2*p015 conroe-wstm
|
||||
1 : 2 : zen1,zen2,zen3,zen4
|
||||
|
||||
PREFETCHNTA : fetch data into non-temporal cache close to the processor, minimizing cache pollution.
|
||||
L1 : Pentium3
|
||||
L2 : NetBurst
|
||||
L1, not L2: Core duo, Core 2, Atom processors
|
||||
L1, not L2, may fetch into L3 with fast replacement: Nehalem, Westmere, Sandy Bridge, ...
|
||||
NEHALEM: Fills L1/L3, L1 LRU is not updated
|
||||
L3 with fast replacement: Xeon Processors based on Nehalem, Westmere, Sandy Bridge, ...
|
||||
PREFETCHT0 : fetch data into all cache levels.
|
||||
PREFETCHT1 : fetch data into L2 and L3
|
||||
endif
|
||||
|
||||
end
|
||||
@@ -0,0 +1,523 @@
|
||||
; XzCrc64Opt.asm -- CRC64 calculation : optimized version
|
||||
; 2023-12-08 : Igor Pavlov : Public domain
|
||||
|
||||
include 7zAsm.asm
|
||||
|
||||
MY_ASM_START
|
||||
|
||||
NUM_WORDS equ 3
|
||||
|
||||
if (NUM_WORDS lt 1) or (NUM_WORDS gt 64)
|
||||
.err <num_words_IS_INCORRECT>
|
||||
endif
|
||||
|
||||
NUM_SKIP_BYTES equ ((NUM_WORDS - 2) * 4)
|
||||
|
||||
|
||||
MOVZXLO macro dest:req, src:req
|
||||
movzx dest, @CatStr(src, _L)
|
||||
endm
|
||||
|
||||
MOVZXHI macro dest:req, src:req
|
||||
movzx dest, @CatStr(src, _H)
|
||||
endm
|
||||
|
||||
|
||||
ifdef x64
|
||||
|
||||
rD equ r11
|
||||
rN equ r10
|
||||
rT equ r9
|
||||
|
||||
CRC_OP macro op:req, dest:req, src:req, t:req
|
||||
op dest, QWORD PTR [rT + @CatStr(src, _R) * 8 + 0800h * (t)]
|
||||
endm
|
||||
|
||||
CRC_XOR macro dest:req, src:req, t:req
|
||||
CRC_OP xor, dest, src, t
|
||||
endm
|
||||
|
||||
CRC_MOV macro dest:req, src:req, t:req
|
||||
CRC_OP mov, dest, src, t
|
||||
endm
|
||||
|
||||
CRC1b macro
|
||||
movzx x6, BYTE PTR [rD]
|
||||
inc rD
|
||||
MOVZXLO x3, x0
|
||||
xor x6, x3
|
||||
shr r0, 8
|
||||
CRC_XOR r0, x6, 0
|
||||
dec rN
|
||||
endm
|
||||
|
||||
|
||||
; ALIGN_MASK is 3 or 7 bytes alignment:
|
||||
ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4)
|
||||
|
||||
if NUM_WORDS eq 1
|
||||
|
||||
src_rN_offset equ 4
|
||||
; + 4 for prefetching next 4-bytes after current iteration
|
||||
NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 4)
|
||||
SRCDAT4 equ DWORD PTR [rN + rD * 1]
|
||||
|
||||
XOR_NEXT macro
|
||||
mov x1, [rD]
|
||||
xor r0, r1
|
||||
endm
|
||||
|
||||
else ; NUM_WORDS > 1
|
||||
|
||||
src_rN_offset equ 8
|
||||
; + 8 for prefetching next 8-bytes after current iteration
|
||||
NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 8)
|
||||
|
||||
XOR_NEXT macro
|
||||
xor r0, QWORD PTR [rD] ; 64-bit read, can be unaligned
|
||||
endm
|
||||
|
||||
; 32-bit or 64-bit
|
||||
LOAD_SRC_MULT4 macro dest:req, word_index:req
|
||||
mov dest, [rN + rD * 1 + 4 * (word_index) - src_rN_offset];
|
||||
endm
|
||||
|
||||
endif
|
||||
|
||||
|
||||
|
||||
MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 4
|
||||
MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
|
||||
mov r0, REG_ABI_PARAM_0 ; r0 <- r1 / r7
|
||||
mov rD, REG_ABI_PARAM_1 ; r11 <- r2 / r6
|
||||
mov rN, REG_ABI_PARAM_2 ; r10 <- r8 / r2
|
||||
if (IS_LINUX gt 0)
|
||||
mov rT, REG_ABI_PARAM_3 ; r9 <- r9 / r1
|
||||
endif
|
||||
|
||||
cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK
|
||||
jb crc_end
|
||||
@@:
|
||||
test rD, ALIGN_MASK
|
||||
jz @F
|
||||
CRC1b
|
||||
jmp @B
|
||||
@@:
|
||||
XOR_NEXT
|
||||
lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)]
|
||||
sub rD, rN
|
||||
add rN, src_rN_offset
|
||||
|
||||
align 16
|
||||
@@:
|
||||
|
||||
if NUM_WORDS eq 1
|
||||
|
||||
mov x1, x0
|
||||
shr x1, 8
|
||||
MOVZXLO x3, x1
|
||||
MOVZXLO x2, x0
|
||||
shr x1, 8
|
||||
shr r0, 32
|
||||
xor x0, SRCDAT4
|
||||
CRC_XOR r0, x2, 3
|
||||
CRC_XOR r0, x3, 2
|
||||
MOVZXLO x2, x1
|
||||
shr x1, 8
|
||||
CRC_XOR r0, x2, 1
|
||||
CRC_XOR r0, x1, 0
|
||||
|
||||
else ; NUM_WORDS > 1
|
||||
|
||||
if NUM_WORDS ne 2
|
||||
k = 2
|
||||
while k lt NUM_WORDS
|
||||
|
||||
LOAD_SRC_MULT4 x1, k
|
||||
crc_op1 textequ <xor>
|
||||
|
||||
if k eq 2
|
||||
if (NUM_WORDS and 1)
|
||||
LOAD_SRC_MULT4 x7, NUM_WORDS ; aligned 32-bit
|
||||
LOAD_SRC_MULT4 x6, NUM_WORDS + 1 ; aligned 32-bit
|
||||
shl r6, 32
|
||||
else
|
||||
LOAD_SRC_MULT4 r6, NUM_WORDS ; aligned 64-bit
|
||||
crc_op1 textequ <mov>
|
||||
endif
|
||||
endif
|
||||
table = 4 * (NUM_WORDS - 1 - k)
|
||||
MOVZXLO x3, x1
|
||||
CRC_OP crc_op1, r7, x3, 3 + table
|
||||
MOVZXHI x3, x1
|
||||
shr x1, 16
|
||||
CRC_XOR r6, x3, 2 + table
|
||||
MOVZXLO x3, x1
|
||||
shr x1, 8
|
||||
CRC_XOR r7, x3, 1 + table
|
||||
CRC_XOR r6, x1, 0 + table
|
||||
k = k + 1
|
||||
endm
|
||||
crc_op2 textequ <xor>
|
||||
|
||||
else ; NUM_WORDS == 2
|
||||
LOAD_SRC_MULT4 r6, NUM_WORDS ; aligned 64-bit
|
||||
crc_op2 textequ <mov>
|
||||
endif ; NUM_WORDS == 2
|
||||
|
||||
MOVZXHI x3, x0
|
||||
MOVZXLO x2, x0
|
||||
mov r1, r0
|
||||
shr r1, 32
|
||||
shr x0, 16
|
||||
CRC_XOR r6, x2, NUM_SKIP_BYTES + 7
|
||||
CRC_OP crc_op2, r7, x3, NUM_SKIP_BYTES + 6
|
||||
MOVZXLO x2, x0
|
||||
MOVZXHI x5, x1
|
||||
MOVZXLO x3, x1
|
||||
shr x0, 8
|
||||
shr x1, 16
|
||||
CRC_XOR r7, x2, NUM_SKIP_BYTES + 5
|
||||
CRC_XOR r6, x3, NUM_SKIP_BYTES + 3
|
||||
CRC_XOR r7, x0, NUM_SKIP_BYTES + 4
|
||||
CRC_XOR r6, x5, NUM_SKIP_BYTES + 2
|
||||
MOVZXLO x2, x1
|
||||
shr x1, 8
|
||||
CRC_XOR r7, x2, NUM_SKIP_BYTES + 1
|
||||
CRC_MOV r0, x1, NUM_SKIP_BYTES + 0
|
||||
xor r0, r6
|
||||
xor r0, r7
|
||||
|
||||
endif ; NUM_WORDS > 1
|
||||
add rD, NUM_WORDS * 4
|
||||
jnc @B
|
||||
|
||||
sub rN, src_rN_offset
|
||||
add rD, rN
|
||||
XOR_NEXT
|
||||
add rN, NUM_BYTES_LIMIT - 1
|
||||
sub rN, rD
|
||||
|
||||
crc_end:
|
||||
test rN, rN
|
||||
jz func_end
|
||||
@@:
|
||||
CRC1b
|
||||
jnz @B
|
||||
func_end:
|
||||
MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
|
||||
MY_ENDP
|
||||
|
||||
|
||||
|
||||
else
|
||||
; ==================================================================
|
||||
; x86 (32-bit)
|
||||
|
||||
rD equ r7
|
||||
rN equ r1
|
||||
rT equ r5
|
||||
|
||||
xA equ x6
|
||||
xA_R equ r6
|
||||
|
||||
ifdef x64
|
||||
num_VAR equ r8
|
||||
else
|
||||
|
||||
crc_OFFS equ (REG_SIZE * 5)
|
||||
|
||||
if (IS_CDECL gt 0) or (IS_LINUX gt 0)
|
||||
; cdecl or (GNU fastcall) stack:
|
||||
; (UInt32 *) table
|
||||
; size_t size
|
||||
; void * data
|
||||
; (UInt64) crc
|
||||
; ret-ip <-(r4)
|
||||
data_OFFS equ (8 + crc_OFFS)
|
||||
size_OFFS equ (REG_SIZE + data_OFFS)
|
||||
table_OFFS equ (REG_SIZE + size_OFFS)
|
||||
num_VAR equ [r4 + size_OFFS]
|
||||
table_VAR equ [r4 + table_OFFS]
|
||||
else
|
||||
; Windows fastcall:
|
||||
; r1 = data, r2 = size
|
||||
; stack:
|
||||
; (UInt32 *) table
|
||||
; (UInt64) crc
|
||||
; ret-ip <-(r4)
|
||||
table_OFFS equ (8 + crc_OFFS)
|
||||
table_VAR equ [r4 + table_OFFS]
|
||||
num_VAR equ table_VAR
|
||||
endif
|
||||
endif ; x64
|
||||
|
||||
SRCDAT4 equ DWORD PTR [rN + rD * 1]
|
||||
|
||||
CRC_1 macro op:req, dest:req, src:req, t:req, word_index:req
|
||||
op dest, DWORD PTR [rT + @CatStr(src, _R) * 8 + 0800h * (t) + (word_index) * 4]
|
||||
endm
|
||||
|
||||
CRC macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req
|
||||
CRC_1 op0, dest0, src, t, 0
|
||||
CRC_1 op1, dest1, src, t, 1
|
||||
endm
|
||||
|
||||
CRC_XOR macro dest0:req, dest1:req, src:req, t:req
|
||||
CRC xor, xor, dest0, dest1, src, t
|
||||
endm
|
||||
|
||||
|
||||
CRC1b macro
|
||||
movzx xA, BYTE PTR [rD]
|
||||
inc rD
|
||||
MOVZXLO x3, x0
|
||||
xor xA, x3
|
||||
shrd x0, x2, 8
|
||||
shr x2, 8
|
||||
CRC_XOR x0, x2, xA, 0
|
||||
dec rN
|
||||
endm
|
||||
|
||||
|
||||
MY_PROLOG_BASE macro
|
||||
MY_PUSH_4_REGS
|
||||
ifdef x64
|
||||
mov r0, REG_ABI_PARAM_0 ; r0 <- r1 / r7
|
||||
mov rT, REG_ABI_PARAM_3 ; r5 <- r9 / r1
|
||||
mov rN, REG_ABI_PARAM_2 ; r1 <- r8 / r2
|
||||
mov rD, REG_ABI_PARAM_1 ; r7 <- r2 / r6
|
||||
mov r2, r0
|
||||
shr r2, 32
|
||||
mov x0, x0
|
||||
else
|
||||
if (IS_CDECL gt 0) or (IS_LINUX gt 0)
|
||||
proc_numParams = proc_numParams + 2 ; for ABI_LINUX
|
||||
mov rN, [r4 + size_OFFS]
|
||||
mov rD, [r4 + data_OFFS]
|
||||
else
|
||||
mov rD, REG_ABI_PARAM_0 ; r7 <- r1 : (data)
|
||||
mov rN, REG_ABI_PARAM_1 ; r1 <- r2 : (size)
|
||||
endif
|
||||
mov x0, [r4 + crc_OFFS]
|
||||
mov x2, [r4 + crc_OFFS + 4]
|
||||
mov rT, table_VAR
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
MY_EPILOG_BASE macro crc_end:req, func_end:req
|
||||
crc_end:
|
||||
test rN, rN
|
||||
jz func_end
|
||||
@@:
|
||||
CRC1b
|
||||
jnz @B
|
||||
func_end:
|
||||
ifdef x64
|
||||
shl r2, 32
|
||||
xor r0, r2
|
||||
endif
|
||||
MY_POP_4_REGS
|
||||
endm
|
||||
|
||||
|
||||
; ALIGN_MASK is 3 or 7 bytes alignment:
|
||||
ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4)
|
||||
|
||||
if (NUM_WORDS eq 1)
|
||||
|
||||
NUM_BYTES_LIMIT_T4 equ (NUM_WORDS * 4 + 4)
|
||||
|
||||
MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 5
|
||||
MY_PROLOG_BASE
|
||||
|
||||
cmp rN, NUM_BYTES_LIMIT_T4 + ALIGN_MASK
|
||||
jb crc_end_4
|
||||
@@:
|
||||
test rD, ALIGN_MASK
|
||||
jz @F
|
||||
CRC1b
|
||||
jmp @B
|
||||
@@:
|
||||
xor x0, [rD]
|
||||
lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT_T4 - 1)]
|
||||
sub rD, rN
|
||||
add rN, 4
|
||||
|
||||
MOVZXLO xA, x0
|
||||
align 16
|
||||
@@:
|
||||
mov x3, SRCDAT4
|
||||
xor x3, x2
|
||||
shr x0, 8
|
||||
CRC xor, mov, x3, x2, xA, 3
|
||||
MOVZXLO xA, x0
|
||||
shr x0, 8
|
||||
; MOVZXHI xA, x0
|
||||
; shr x0, 16
|
||||
CRC_XOR x3, x2, xA, 2
|
||||
|
||||
MOVZXLO xA, x0
|
||||
shr x0, 8
|
||||
CRC_XOR x3, x2, xA, 1
|
||||
CRC_XOR x3, x2, x0, 0
|
||||
MOVZXLO xA, x3
|
||||
mov x0, x3
|
||||
|
||||
add rD, 4
|
||||
jnc @B
|
||||
|
||||
sub rN, 4
|
||||
add rD, rN
|
||||
xor x0, [rD]
|
||||
add rN, NUM_BYTES_LIMIT_T4 - 1
|
||||
sub rN, rD
|
||||
MY_EPILOG_BASE crc_end_4, func_end_4
|
||||
MY_ENDP
|
||||
|
||||
else ; NUM_WORDS > 1
|
||||
|
||||
SHR_X macro x, imm
|
||||
shr x, imm
|
||||
endm
|
||||
|
||||
|
||||
ITER_1 macro v0, v1, a, off
|
||||
MOVZXLO xA, a
|
||||
SHR_X a, 8
|
||||
CRC_XOR v0, v1, xA, off
|
||||
endm
|
||||
|
||||
|
||||
ITER_4 macro v0, v1, a, off
|
||||
if 0 eq 0
|
||||
ITER_1 v0, v1, a, off + 3
|
||||
ITER_1 v0, v1, a, off + 2
|
||||
ITER_1 v0, v1, a, off + 1
|
||||
CRC_XOR v0, v1, a, off
|
||||
elseif 0 eq 0
|
||||
MOVZXLO xA, a
|
||||
CRC_XOR v0, v1, xA, off + 3
|
||||
mov xA, a
|
||||
ror a, 16 ; 32-bit ror
|
||||
shr xA, 24
|
||||
CRC_XOR v0, v1, xA, off
|
||||
MOVZXLO xA, a
|
||||
SHR_X a, 24
|
||||
CRC_XOR v0, v1, xA, off + 1
|
||||
CRC_XOR v0, v1, a, off + 2
|
||||
else
|
||||
; MOVZXHI provides smaller code, but MOVZX_HI_BYTE is not fast instruction
|
||||
MOVZXLO xA, a
|
||||
CRC_XOR v0, v1, xA, off + 3
|
||||
MOVZXHI xA, a
|
||||
SHR_X a, 16
|
||||
CRC_XOR v0, v1, xA, off + 2
|
||||
MOVZXLO xA, a
|
||||
SHR_X a, 8
|
||||
CRC_XOR v0, v1, xA, off + 1
|
||||
CRC_XOR v0, v1, a, off
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
|
||||
ITER_1_PAIR macro v0, v1, a0, a1, off
|
||||
ITER_1 v0, v1, a0, off + 4
|
||||
ITER_1 v0, v1, a1, off
|
||||
endm
|
||||
|
||||
src_rD_offset equ 8
|
||||
STEP_SIZE equ (NUM_WORDS * 4)
|
||||
|
||||
ITER_12_NEXT macro op, index, v0, v1
|
||||
op v0, DWORD PTR [rD + (index + 1) * STEP_SIZE - src_rD_offset]
|
||||
op v1, DWORD PTR [rD + (index + 1) * STEP_SIZE + 4 - src_rD_offset]
|
||||
endm
|
||||
|
||||
ITER_12 macro index, a0, a1, v0, v1
|
||||
|
||||
if NUM_SKIP_BYTES eq 0
|
||||
ITER_12_NEXT mov, index, v0, v1
|
||||
else
|
||||
k = 0
|
||||
while k lt NUM_SKIP_BYTES
|
||||
movzx xA, BYTE PTR [rD + (index) * STEP_SIZE + k + 8 - src_rD_offset]
|
||||
if k eq 0
|
||||
CRC mov, mov, v0, v1, xA, NUM_SKIP_BYTES - 1 - k
|
||||
else
|
||||
CRC_XOR v0, v1, xA, NUM_SKIP_BYTES - 1 - k
|
||||
endif
|
||||
k = k + 1
|
||||
endm
|
||||
ITER_12_NEXT xor, index, v0, v1
|
||||
endif
|
||||
|
||||
if 0 eq 0
|
||||
ITER_4 v0, v1, a0, NUM_SKIP_BYTES + 4
|
||||
ITER_4 v0, v1, a1, NUM_SKIP_BYTES
|
||||
else ; interleave version is faster/slower for different processors
|
||||
ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 3
|
||||
ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 2
|
||||
ITER_1_PAIR v0, v1, a0, a1, NUM_SKIP_BYTES + 1
|
||||
CRC_XOR v0, v1, a0, NUM_SKIP_BYTES + 4
|
||||
CRC_XOR v0, v1, a1, NUM_SKIP_BYTES
|
||||
endif
|
||||
endm
|
||||
|
||||
; we use (UNROLL_CNT > 1) to reduce read ports pressure (num_VAR reads)
|
||||
UNROLL_CNT equ (2 * 1)
|
||||
NUM_BYTES_LIMIT equ (STEP_SIZE * UNROLL_CNT + 8)
|
||||
|
||||
MY_PROC @CatStr(XzCrc64UpdateT, %(NUM_WORDS * 4)), 5
|
||||
MY_PROLOG_BASE
|
||||
|
||||
cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK
|
||||
jb crc_end_12
|
||||
@@:
|
||||
test rD, ALIGN_MASK
|
||||
jz @F
|
||||
CRC1b
|
||||
jmp @B
|
||||
@@:
|
||||
xor x0, [rD]
|
||||
xor x2, [rD + 4]
|
||||
add rD, src_rD_offset
|
||||
lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)]
|
||||
mov num_VAR, rN
|
||||
|
||||
align 16
|
||||
@@:
|
||||
i = 0
|
||||
rept UNROLL_CNT
|
||||
if (i and 1) eq 0
|
||||
ITER_12 i, x0, x2, x1, x3
|
||||
else
|
||||
ITER_12 i, x1, x3, x0, x2
|
||||
endif
|
||||
i = i + 1
|
||||
endm
|
||||
|
||||
if (UNROLL_CNT and 1)
|
||||
mov x0, x1
|
||||
mov x2, x3
|
||||
endif
|
||||
add rD, STEP_SIZE * UNROLL_CNT
|
||||
cmp rD, num_VAR
|
||||
jb @B
|
||||
|
||||
mov rN, num_VAR
|
||||
add rN, NUM_BYTES_LIMIT - 1
|
||||
sub rN, rD
|
||||
sub rD, src_rD_offset
|
||||
xor x0, [rD]
|
||||
xor x2, [rD + 4]
|
||||
|
||||
MY_EPILOG_BASE crc_end_12, func_end_12
|
||||
MY_ENDP
|
||||
|
||||
endif ; (NUM_WORDS > 1)
|
||||
endif ; ! x64
|
||||
end
|
||||
Reference in New Issue
Block a user