This commit is contained in:
Igor Pavlov 2024-05-14 00:00:00 +00:00
parent 5b39dc76f1
commit fc662341e6
501 changed files with 33187 additions and 10416 deletions

View file

@ -1,5 +1,5 @@
; 7zAsm.asm -- ASM macros ; 7zAsm.asm -- ASM macros
; 2022-05-16 : Igor Pavlov : Public domain ; 2023-12-08 : Igor Pavlov : Public domain
; UASM can require these changes ; UASM can require these changes
@ -43,7 +43,7 @@ else
endif endif
endif endif
OPTION PROLOGUE:NONE OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE OPTION EPILOGUE:NONE
MY_ASM_START macro MY_ASM_START macro
@ -121,10 +121,29 @@ endif
x2_H equ DH x2_H equ DH
x3_H equ BH 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 ifdef x64
x5_L equ BPL x5_L equ BPL
x6_L equ SIL x6_L equ SIL
x7_L equ DIL 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 r0 equ RAX
r1 equ RCX r1 equ RCX
@ -153,6 +172,22 @@ else
r7 equ x7 r7 equ x7
endif 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 x64
ifdef ABI_LINUX ifdef ABI_LINUX
@ -200,6 +235,14 @@ REG_ABI_PARAM_0 equ REG_PARAM_0
REG_ABI_PARAM_1_x equ REG_PARAM_1_x REG_ABI_PARAM_1_x equ REG_PARAM_1_x
REG_ABI_PARAM_1 equ REG_PARAM_1 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 else
; x64 ; x64
@ -261,12 +304,25 @@ endm
endif ; IS_LINUX endif ; IS_LINUX
MY_PUSH_PRESERVED_ABI_REGS macro MY_PUSH_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11 macro
if (IS_LINUX gt 0) if (IS_LINUX gt 0)
MY_PUSH_2_REGS MY_PUSH_2_REGS
else else
MY_PUSH_4_REGS MY_PUSH_4_REGS
endif 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 r12
push r13 push r13
push r14 push r14
@ -279,11 +335,7 @@ MY_POP_PRESERVED_ABI_REGS macro
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
if (IS_LINUX gt 0) MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
MY_POP_2_REGS
else
MY_POP_4_REGS
endif
endm endm
endif ; x64 endif ; x64

View file

@ -1,180 +1,258 @@
; 7zCrcOpt.asm -- CRC32 calculation : optimized version ; 7zCrcOpt.asm -- CRC32 calculation : optimized version
; 2021-02-07 : Igor Pavlov : Public domain ; 2023-12-08 : Igor Pavlov : Public domain
include 7zAsm.asm include 7zAsm.asm
MY_ASM_START MY_ASM_START
rD equ r2 NUM_WORDS equ 3
rN equ r7 UNROLL_CNT equ 2
rT equ r5
ifdef x64 if (NUM_WORDS lt 1) or (NUM_WORDS gt 64)
num_VAR equ r8 .err <NUM_WORDS_IS_INCORRECT>
table_VAR equ r9 endif
else if (UNROLL_CNT lt 1)
if (IS_CDECL gt 0) .err <UNROLL_CNT_IS_INCORRECT>
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)
num_VAR equ [r4 + size_OFFS]
table_VAR equ [r4 + table_OFFS]
endif endif
SRCDAT equ rD + rN * 1 + 4 * 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 CRC macro op:req, dest:req, src:req, t:req
op dest, DWORD PTR [rT + src * 4 + 0400h * t] op dest, dword ptr [rT + @CatStr(src, _R) * 4 + 0400h * (t)]
endm endm
CRC_XOR macro dest:req, src:req, t:req CRC_XOR macro dest:req, src:req, t:req
CRC xor, dest, src, t CRC xor, dest, src, t
endm endm
CRC_MOV macro dest:req, src:req, t:req CRC_MOV macro dest:req, src:req, t:req
CRC mov, dest, src, t CRC mov, dest, src, t
endm 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 CRC1b macro
movzx x6, BYTE PTR [rD] movzx x6, byte ptr [rD]
inc rD MOVZXLO x3, x0
movzx x3, x0_L inc rD
xor x6, x3 shr x0, 8
shr x0, 8 xor x6, x3
CRC xor, x0, r6, 0 CRC_XOR x0, x6, 0
dec rN dec rN
endm endm
MY_PROLOG macro crc_end:req 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 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) if (IS_LINUX gt 0)
MY_PUSH_2_REGS
mov x0, REG_ABI_PARAM_0_x ; x0 = x7
mov rT, REG_ABI_PARAM_3 ; r5 = r1
mov rN, REG_ABI_PARAM_2 ; r7 = r2
mov rD, REG_ABI_PARAM_1 ; r2 = r6 mov rD, REG_ABI_PARAM_1 ; r2 = r6
else
MY_PUSH_4_REGS
mov x0, REG_ABI_PARAM_0_x ; x0 = x1
mov rT, REG_ABI_PARAM_3 ; r5 = r9
mov rN, REG_ABI_PARAM_2 ; r7 = r8
; mov rD, REG_ABI_PARAM_1 ; r2 = r2
endif endif
else else
MY_PUSH_4_REGS
if (IS_CDECL gt 0) if (IS_CDECL gt 0)
mov x0, [r4 + crc_OFFS] mov x0, [r4 + crc_OFFS]
mov rD, [r4 + data_OFFS] mov rD, [r4 + data_OFFS]
else else
mov x0, REG_ABI_PARAM_0_x mov x0, REG_ABI_PARAM_0_x
endif endif
mov rN, num_VAR mov rN, [r4 + size_OFFS]
mov rT, table_VAR mov rT, [r4 + table_OFFS]
endif endif
test rN, rN cmp rN, NUM_BYTES_LIMIT + ALIGN_MASK
jz crc_end jb crc_end
@@: @@:
test rD, 7 test rD_x, ALIGN_MASK ; test rD, ALIGN_MASK
jz @F jz @F
CRC1b CRC1b
jnz @B jmp @B
@@: @@:
cmp rN, 16 xor x0, dword ptr [rD]
jb crc_end lea rN, [rD + rN * 1 - (NUM_BYTES_LIMIT - 1)]
add rN, rD sub rD, rN
mov num_VAR, rN
sub rN, 8 align 16
and rN, NOT 7 @@:
sub rD, rN unr_index = 0
xor x0, [SRCDAT 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 endm
MY_EPILOG macro crc_end:req add rD, NUM_WORDS * 4 * UNROLL_CNT
xor x0, [SRCDAT 0] jnc @B
mov rD, rN
mov rN, num_VAR
sub rN, rD
crc_end:
test rN, rN
jz @F
CRC1b
jmp crc_end
@@:
if (IS_X64 gt 0) and (IS_LINUX gt 0)
MY_POP_2_REGS
else
MY_POP_4_REGS
endif
endm
MY_PROC CrcUpdateT8, 4 if 0
MY_PROLOG crc_end_8 ; byte verson
mov x1, [SRCDAT 1] add rD, rN
align 16 xor x0, dword ptr [rD]
main_loop_8: add rN, NUM_BYTES_LIMIT - 1
mov x6, [SRCDAT 2] else
movzx x3, x1_L ; 4-byte version
CRC_XOR x6, r3, 3 add rN, 4 * NUM_WORDS * UNROLL_CNT
movzx x3, x1_H sub rD, 4 * NUM_WORDS * UNROLL_CNT
CRC_XOR x6, r3, 2 @@:
shr x1, 16 MOVZXLO x3, x0
movzx x3, x1_L MOVZXHI x1, x0
movzx x1, x1_H shr x0, 16
CRC_XOR x6, r3, 1 MOVZXLO x6, x0
movzx x3, x0_L shr x0, 8
CRC_XOR x6, r1, 0 CRC_MOV x0, x0, 0
CRC_XOR x0, x3, 3
CRC_XOR x0, x1, 2
CRC_XOR x0, x6, 1
mov x1, [SRCDAT 3] add rD, 4
CRC_XOR x6, r3, 7 if (NUM_WORDS * UNROLL_CNT) ne 1
movzx x3, x0_H jc @F
shr x0, 16 xor x0, [SRCDAT_4 0]
CRC_XOR x6, r3, 6 jmp @B
movzx x3, x0_L @@:
CRC_XOR x6, r3, 5 endif
movzx x3, x0_H add rD, rN
CRC_MOV x0, r3, 4 add rN, 4 - 1
xor x0, x6
add rD, 8 endif
jnz main_loop_8
sub rN, rD
crc_end:
test rN, rN
jz func_end
@@:
CRC1b
jnz @B
MY_EPILOG crc_end_8 func_end:
MY_ENDP MY_POP_PRESERVED_ABI_REGS_UP_TO_INCLUDING_R11
MY_PROC CrcUpdateT4, 4
MY_PROLOG crc_end_4
align 16
main_loop_4:
movzx x1, x0_L
movzx x3, x0_H
shr x0, 16
movzx x6, x0_H
and x0, 0FFh
CRC_MOV x1, r1, 3
xor x1, [SRCDAT 1]
CRC_XOR x1, r3, 2
CRC_XOR x1, r6, 0
CRC_XOR x1, r0, 1
movzx x0, x1_L
movzx x3, x1_H
shr x1, 16
movzx x6, x1_H
and x1, 0FFh
CRC_MOV x0, r0, 3
xor x0, [SRCDAT 2]
CRC_XOR x0, r3, 2
CRC_XOR x0, r6, 0
CRC_XOR x0, r1, 1
add rD, 8
jnz main_loop_4
MY_EPILOG crc_end_4
MY_ENDP MY_ENDP
end end

View file

@ -1,113 +1,231 @@
; XzCrc64Opt.asm -- CRC64 calculation : optimized version ; XzCrc64Opt.asm -- CRC64 calculation : optimized version
; 2021-02-06 : Igor Pavlov : Public domain ; 2023-12-08 : Igor Pavlov : Public domain
include 7zAsm.asm include 7zAsm.asm
MY_ASM_START 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 ifdef x64
rD equ r9 rD equ r11
rN equ r10 rN equ r10
rT equ r5 rT equ r9
num_VAR equ r8
CRC_OP macro op:req, dest:req, src:req, t:req
SRCDAT4 equ dword ptr [rD + rN * 1] op dest, QWORD PTR [rT + @CatStr(src, _R) * 8 + 0800h * (t)]
endm
CRC_XOR macro dest:req, src:req, t:req CRC_XOR macro dest:req, src:req, t:req
xor dest, QWORD PTR [rT + src * 8 + 0800h * t] CRC_OP xor, dest, src, t
endm
CRC_MOV macro dest:req, src:req, t:req
CRC_OP mov, dest, src, t
endm endm
CRC1b macro CRC1b macro
movzx x6, BYTE PTR [rD] movzx x6, BYTE PTR [rD]
inc rD inc rD
movzx x3, x0_L MOVZXLO x3, x0
xor x6, x3 xor x6, x3
shr r0, 8 shr r0, 8
CRC_XOR r0, r6, 0 CRC_XOR r0, x6, 0
dec rN dec rN
endm endm
MY_PROLOG macro crc_end:req
ifdef ABI_LINUX ; ALIGN_MASK is 3 or 7 bytes alignment:
MY_PUSH_2_REGS ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4)
else
MY_PUSH_4_REGS if NUM_WORDS eq 1
endif
mov r0, REG_ABI_PARAM_0 src_rN_offset equ 4
mov rN, REG_ABI_PARAM_2 ; + 4 for prefetching next 4-bytes after current iteration
mov rT, REG_ABI_PARAM_3 NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 4)
mov rD, REG_ABI_PARAM_1 SRCDAT4 equ DWORD PTR [rN + rD * 1]
test rN, rN
jz crc_end XOR_NEXT macro
@@: mov x1, [rD]
test rD, 3 xor r0, r1
jz @F
CRC1b
jnz @B
@@:
cmp rN, 8
jb crc_end
add rN, rD
mov num_VAR, rN
sub rN, 4
and rN, NOT 3
sub rD, rN
mov x1, SRCDAT4
xor r0, r1
add rN, 4
endm endm
MY_EPILOG macro crc_end:req else ; NUM_WORDS > 1
sub rN, 4
mov x1, SRCDAT4 src_rN_offset equ 8
xor r0, r1 ; + 8 for prefetching next 8-bytes after current iteration
mov rD, rN NUM_BYTES_LIMIT equ (NUM_WORDS * 4 + 8)
mov rN, num_VAR
sub rN, rD XOR_NEXT macro
crc_end: xor r0, QWORD PTR [rD] ; 64-bit read, can be unaligned
test rN, rN
jz @F
CRC1b
jmp crc_end
@@:
ifdef ABI_LINUX
MY_POP_2_REGS
else
MY_POP_4_REGS
endif
endm endm
MY_PROC XzCrc64UpdateT4, 4 ; 32-bit or 64-bit
MY_PROLOG crc_end_4 LOAD_SRC_MULT4 macro dest:req, word_index:req
align 16 mov dest, [rN + rD * 1 + 4 * (word_index) - src_rN_offset];
main_loop_4: endm
mov x1, SRCDAT4
movzx x2, x0_L
movzx x3, x0_H
shr r0, 16
movzx x6, x0_L
movzx x7, x0_H
shr r0, 16
CRC_XOR r1, r2, 3
CRC_XOR r0, r3, 2
CRC_XOR r1, r6, 1
CRC_XOR r0, r7, 0
xor r0, r1
add rD, 4 endif
jnz main_loop_4
MY_EPILOG crc_end_4
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 MY_ENDP
else else
; ==================================================================
; x86 (32-bit) ; x86 (32-bit)
rD equ r1 rD equ r7
rN equ r7 rN equ r1
rT equ r5 rT equ r5
xA equ x6
xA_R equ r6
ifdef x64
num_VAR equ r8
else
crc_OFFS equ (REG_SIZE * 5) crc_OFFS equ (REG_SIZE * 5)
if (IS_CDECL gt 0) or (IS_LINUX gt 0) if (IS_CDECL gt 0) or (IS_LINUX gt 0)
@ -133,107 +251,273 @@ else
table_VAR equ [r4 + table_OFFS] table_VAR equ [r4 + table_OFFS]
num_VAR equ table_VAR num_VAR equ table_VAR
endif endif
endif ; x64
SRCDAT4 equ dword ptr [rD + rN * 1] 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 macro op0:req, op1:req, dest0:req, dest1:req, src:req, t:req
op0 dest0, DWORD PTR [rT + src * 8 + 0800h * t] CRC_1 op0, dest0, src, t, 0
op1 dest1, DWORD PTR [rT + src * 8 + 0800h * t + 4] CRC_1 op1, dest1, src, t, 1
endm endm
CRC_XOR macro dest0:req, dest1:req, src:req, t:req CRC_XOR macro dest0:req, dest1:req, src:req, t:req
CRC xor, xor, dest0, dest1, src, t CRC xor, xor, dest0, dest1, src, t
endm endm
CRC1b macro CRC1b macro
movzx x6, BYTE PTR [rD] movzx xA, BYTE PTR [rD]
inc rD inc rD
movzx x3, x0_L MOVZXLO x3, x0
xor x6, x3 xor xA, x3
shrd r0, r2, 8 shrd x0, x2, 8
shr r2, 8 shr x2, 8
CRC_XOR r0, r2, r6, 0 CRC_XOR x0, x2, xA, 0
dec rN dec rN
endm endm
MY_PROLOG macro crc_end:req
MY_PUSH_4_REGS
if (IS_CDECL gt 0) or (IS_LINUX gt 0) MY_PROLOG_BASE macro
proc_numParams = proc_numParams + 2 ; for ABI_LINUX MY_PUSH_4_REGS
mov rN, [r4 + size_OFFS] ifdef x64
mov rD, [r4 + data_OFFS] mov r0, REG_ABI_PARAM_0 ; r0 <- r1 / r7
else mov rT, REG_ABI_PARAM_3 ; r5 <- r9 / r1
mov rN, r2 mov rN, REG_ABI_PARAM_2 ; r1 <- r8 / r2
endif mov rD, REG_ABI_PARAM_1 ; r7 <- r2 / r6
mov r2, r0
mov x0, [r4 + crc_OFFS] shr r2, 32
mov x2, [r4 + crc_OFFS + 4] mov x0, x0
mov rT, table_VAR else
test rN, rN if (IS_CDECL gt 0) or (IS_LINUX gt 0)
jz crc_end proc_numParams = proc_numParams + 2 ; for ABI_LINUX
@@: mov rN, [r4 + size_OFFS]
test rD, 3 mov rD, [r4 + data_OFFS]
jz @F else
CRC1b mov rD, REG_ABI_PARAM_0 ; r7 <- r1 : (data)
jnz @B mov rN, REG_ABI_PARAM_1 ; r1 <- r2 : (size)
@@: endif
cmp rN, 8 mov x0, [r4 + crc_OFFS]
jb crc_end mov x2, [r4 + crc_OFFS + 4]
add rN, rD mov rT, table_VAR
endif
mov num_VAR, rN
sub rN, 4
and rN, NOT 3
sub rD, rN
xor r0, SRCDAT4
add rN, 4
endm endm
MY_EPILOG macro crc_end:req
sub rN, 4
xor r0, SRCDAT4
mov rD, rN MY_EPILOG_BASE macro crc_end:req, func_end:req
mov rN, num_VAR crc_end:
sub rN, rD test rN, rN
crc_end: jz func_end
test rN, rN @@:
jz @F CRC1b
CRC1b jnz @B
jmp crc_end func_end:
@@: ifdef x64
MY_POP_4_REGS shl r2, 32
xor r0, r2
endif
MY_POP_4_REGS
endm endm
MY_PROC XzCrc64UpdateT4, 5
MY_PROLOG crc_end_4
movzx x6, x0_L
align 16
main_loop_4:
mov r3, SRCDAT4
xor r3, r2
CRC xor, mov, r3, r2, r6, 3 ; ALIGN_MASK is 3 or 7 bytes alignment:
movzx x6, x0_H ALIGN_MASK equ (7 - (NUM_WORDS and 1) * 4)
shr r0, 16
CRC_XOR r3, r2, r6, 2
movzx x6, x0_L if (NUM_WORDS eq 1)
movzx x0, x0_H
CRC_XOR r3, r2, r6, 1
CRC_XOR r3, r2, r0, 0
movzx x6, x3_L
mov r0, r3
add rD, 4 NUM_BYTES_LIMIT_T4 equ (NUM_WORDS * 4 + 4)
jnz main_loop_4
MY_EPILOG crc_end_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 MY_ENDP
endif ; ! x64 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 end

View file

@ -1,5 +1,5 @@
/* 7zArcIn.c -- 7z Input functions /* 7zArcIn.c -- 7z Input functions
2023-05-11 : Igor Pavlov : Public domain */ 2023-09-07 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -301,7 +301,7 @@ static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
{ {
Byte b = 0; unsigned b = 0;
unsigned m = 0; unsigned m = 0;
UInt32 sum = 0; UInt32 sum = 0;
for (; numItems != 0; numItems--) for (; numItems != 0; numItems--)
@ -312,7 +312,7 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
m = 8; m = 8;
} }
m--; m--;
sum += ((b >> m) & 1); sum += (UInt32)((b >> m) & 1);
} }
return sum; return sum;
} }

532
C/7zCrc.c
View file

@ -1,93 +1,96 @@
/* 7zCrc.c -- CRC32 calculation and init /* 7zCrc.c -- CRC32 calculation and init
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h" #include "CpuArch.h"
#define kCrcPoly 0xEDB88320 // for debug:
// #define __ARM_FEATURE_CRC32 1
#ifdef MY_CPU_LE #ifdef __ARM_FEATURE_CRC32
#define CRC_NUM_TABLES 8 // #pragma message("__ARM_FEATURE_CRC32")
#define Z7_CRC_HW_FORCE
#endif
// #define Z7_CRC_DEBUG_BE
#ifdef Z7_CRC_DEBUG_BE
#undef MY_CPU_LE
#define MY_CPU_BE
#endif
#ifdef Z7_CRC_HW_FORCE
#define Z7_CRC_NUM_TABLES_USE 1
#else #else
#define CRC_NUM_TABLES 9 #ifdef Z7_CRC_NUM_TABLES
#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); #else
UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table); #define Z7_CRC_NUM_TABLES_USE 12
#endif
#endif #endif
#ifndef MY_CPU_BE #if Z7_CRC_NUM_TABLES_USE < 1
UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif #endif
/* #if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)
extern #define Z7_CRC_NUM_TABLES_TOTAL Z7_CRC_NUM_TABLES_USE
CRC_FUNC g_CrcUpdateT4; #else
CRC_FUNC g_CrcUpdateT4; #define Z7_CRC_NUM_TABLES_TOTAL (Z7_CRC_NUM_TABLES_USE + 1)
*/ #endif
extern
CRC_FUNC g_CrcUpdateT8;
CRC_FUNC g_CrcUpdateT8;
extern
CRC_FUNC g_CrcUpdateT0_32;
CRC_FUNC g_CrcUpdateT0_32;
extern
CRC_FUNC g_CrcUpdateT0_64;
CRC_FUNC g_CrcUpdateT0_64;
extern
CRC_FUNC g_CrcUpdate;
CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; #ifndef Z7_CRC_HW_FORCE
UInt32 Z7_FASTCALL CrcUpdate(UInt32 v, const void *data, size_t size) #if Z7_CRC_NUM_TABLES_USE == 1 \
{
return g_CrcUpdate(v, data, size, g_CrcTable);
}
UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
{
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
}
#if CRC_NUM_TABLES < 4 \
|| (CRC_NUM_TABLES == 4 && defined(MY_CPU_BE)) \
|| (!defined(MY_CPU_LE) && !defined(MY_CPU_BE)) || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table); #define Z7_CRC_UPDATE_T1_FUNC_NAME CrcUpdateGT1
UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table) static UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size)
{ {
const UInt32 *table = g_CrcTable;
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
const Byte *pEnd = p + size; const Byte *lim = p + size;
for (; p != pEnd; p++) for (; p != lim; p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
#endif #endif
#if Z7_CRC_NUM_TABLES_USE != 1
#ifndef MY_CPU_BE
#define FUNC_NAME_LE_2(s) CrcUpdateT ## s
#define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)
#define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)
UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
#ifndef MY_CPU_LE
#define FUNC_NAME_BE_2(s) CrcUpdateT1_BeT ## s
#define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)
#define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)
UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
#endif
#endif // Z7_CRC_HW_FORCE
/* ---------- hardware CRC ---------- */ /* ---------- hardware CRC ---------- */
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#if defined(MY_CPU_ARM_OR_ARM64) #if defined(MY_CPU_ARM_OR_ARM64)
// #pragma message("ARM*") // #pragma message("ARM*")
#if defined(_MSC_VER) #if (defined(__clang__) && (__clang_major__ >= 3)) \
#if defined(MY_CPU_ARM64) || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \
#if (_MSC_VER >= 1910) || defined(__GNUC__) && (__GNUC__ >= 8)
#ifndef __clang__
#define USE_ARM64_CRC
#include <intrin.h>
#endif
#endif
#endif
#elif (defined(__clang__) && (__clang_major__ >= 3)) \
|| (defined(__GNUC__) && (__GNUC__ > 4))
#if !defined(__ARM_FEATURE_CRC32) #if !defined(__ARM_FEATURE_CRC32)
// #pragma message("!defined(__ARM_FEATURE_CRC32)")
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define __ARM_FEATURE_CRC32 1 #define __ARM_FEATURE_CRC32 1
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#define Z7_ARM_FEATURE_CRC32_WAS_SET
#if defined(__clang__) #if defined(__clang__)
#if defined(MY_CPU_ARM64) #if defined(MY_CPU_ARM64)
#define ATTRIB_CRC __attribute__((__target__("crc"))) #define ATTRIB_CRC __attribute__((__target__("crc")))
@ -96,100 +99,120 @@ UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UI
#endif #endif
#else #else
#if defined(MY_CPU_ARM64) #if defined(MY_CPU_ARM64)
#if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000)
#define ATTRIB_CRC __attribute__((__target__("+crc"))) #define ATTRIB_CRC __attribute__((__target__("+crc")))
#endif
#else #else
#if !defined(Z7_GCC_VERSION) || (__GNUC__ >= 8)
#if defined(__ARM_FP) && __GNUC__ >= 8
// for -mfloat-abi=hard: similar to <arm_acle.h>
#define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc+simd")))
#else
#define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc"))) #define ATTRIB_CRC __attribute__((__target__("arch=armv8-a+crc")))
#endif
#endif
#endif #endif
#endif #endif
#endif #endif
#if defined(__ARM_FEATURE_CRC32) #if defined(__ARM_FEATURE_CRC32)
#define USE_ARM64_CRC // #pragma message("<arm_acle.h>")
/*
arm_acle.h (GGC):
before Nov 17, 2017:
#ifdef __ARM_FEATURE_CRC32
Nov 17, 2017: gcc10.0 (gcc 9.2.0) checked"
#if __ARM_ARCH >= 8
#pragma GCC target ("arch=armv8-a+crc")
Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:
#ifdef __ARM_FEATURE_CRC32
#ifdef __ARM_FP
#pragma GCC target ("arch=armv8-a+crc+simd")
#else
#pragma GCC target ("arch=armv8-a+crc")
#endif
*/
#if defined(__ARM_ARCH) && __ARM_ARCH < 8
#if defined(Z7_GCC_VERSION) && (__GNUC__ == 8) && (Z7_GCC_VERSION < 80400) \
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 9) && (Z7_GCC_VERSION < 90201) \
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 10) && (Z7_GCC_VERSION < 100100)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
// #pragma message("#define __ARM_ARCH 8")
#undef __ARM_ARCH
#define __ARM_ARCH 8
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif
#define Z7_CRC_HW_USE
#include <arm_acle.h> #include <arm_acle.h>
#endif #endif
#elif defined(_MSC_VER)
#if defined(MY_CPU_ARM64)
#if (_MSC_VER >= 1910)
#ifdef __clang__
// #define Z7_CRC_HW_USE
// #include <arm_acle.h>
#else
#define Z7_CRC_HW_USE
#include <intrin.h>
#endif
#endif
#endif
#endif #endif
#else #else // non-ARM*
// no hardware CRC // #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code
#ifdef Z7_CRC_HW_USE
// #define USE_CRC_EMU #include "7zCrcEmu.h"
#ifdef USE_CRC_EMU
#pragma message("ARM64 CRC emulation")
Z7_FORCE_INLINE
UInt32 __crc32b(UInt32 v, UInt32 data)
{
const UInt32 *table = g_CrcTable;
v = CRC_UPDATE_BYTE_2(v, (Byte)data);
return v;
}
Z7_FORCE_INLINE
UInt32 __crc32w(UInt32 v, UInt32 data)
{
const UInt32 *table = g_CrcTable;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
return v;
}
Z7_FORCE_INLINE
UInt32 __crc32d(UInt32 v, UInt64 data)
{
const UInt32 *table = g_CrcTable;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
v = CRC_UPDATE_BYTE_2(v, (Byte)data); data >>= 8;
return v;
}
#endif // USE_CRC_EMU
#endif // defined(MY_CPU_ARM64) && defined(MY_CPU_LE)
#if defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
#define T0_32_UNROLL_BYTES (4 * 4)
#define T0_64_UNROLL_BYTES (4 * 8)
#ifndef ATTRIB_CRC
#define ATTRIB_CRC
#endif #endif
#endif // non-ARM*
#if defined(Z7_CRC_HW_USE)
// #pragma message("USE ARM HW CRC") // #pragma message("USE ARM HW CRC")
ATTRIB_CRC #ifdef MY_CPU_64BIT
UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table); #define CRC_HW_WORD_TYPE UInt64
ATTRIB_CRC #define CRC_HW_WORD_FUNC __crc32d
UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const UInt32 *table) #else
#define CRC_HW_WORD_TYPE UInt32
#define CRC_HW_WORD_FUNC __crc32w
#endif
#define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4)
#ifdef ATTRIB_CRC
ATTRIB_CRC
#endif
Z7_NO_INLINE
#ifdef Z7_CRC_HW_FORCE
UInt32 Z7_FASTCALL CrcUpdate
#else
static UInt32 Z7_FASTCALL CrcUpdate_HW
#endif
(UInt32 v, const void *data, size_t size)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
UNUSED_VAR(table); for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--)
for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_32_UNROLL_BYTES - 1)) != 0; size--)
v = __crc32b(v, *p++); v = __crc32b(v, *p++);
if (size >= CRC_HW_UNROLL_BYTES)
if (size >= T0_32_UNROLL_BYTES)
{ {
const Byte *lim = p + size; const Byte *lim = p + size;
size &= (T0_32_UNROLL_BYTES - 1); size &= CRC_HW_UNROLL_BYTES - 1;
lim -= size; lim -= size;
do do
{ {
v = __crc32w(v, *(const UInt32 *)(const void *)(p)); v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
v = __crc32w(v, *(const UInt32 *)(const void *)(p)); p += 2 * sizeof(CRC_HW_WORD_TYPE);
v = __crc32w(v, *(const UInt32 *)(const void *)(p + 4)); p += 2 * 4; v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));
v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));
p += 2 * sizeof(CRC_HW_WORD_TYPE);
} }
while (p != lim); while (p != lim);
} }
@ -200,141 +223,198 @@ UInt32 Z7_FASTCALL CrcUpdateT0_32(UInt32 v, const void *data, size_t size, const
return v; return v;
} }
ATTRIB_CRC #ifdef Z7_ARM_FEATURE_CRC32_WAS_SET
UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table); Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
ATTRIB_CRC #undef __ARM_FEATURE_CRC32
UInt32 Z7_FASTCALL CrcUpdateT0_64(UInt32 v, const void *data, size_t size, const UInt32 *table) Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
{ #undef Z7_ARM_FEATURE_CRC32_WAS_SET
const Byte *p = (const Byte *)data; #endif
UNUSED_VAR(table);
for (; size != 0 && ((unsigned)(ptrdiff_t)p & (T0_64_UNROLL_BYTES - 1)) != 0; size--)
v = __crc32b(v, *p++);
if (size >= T0_64_UNROLL_BYTES)
{
const Byte *lim = p + size;
size &= (T0_64_UNROLL_BYTES - 1);
lim -= size;
do
{
v = __crc32d(v, *(const UInt64 *)(const void *)(p));
v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
v = __crc32d(v, *(const UInt64 *)(const void *)(p));
v = __crc32d(v, *(const UInt64 *)(const void *)(p + 8)); p += 2 * 8;
}
while (p != lim);
}
for (; size != 0; size--)
v = __crc32b(v, *p++);
return v;
}
#undef T0_32_UNROLL_BYTES
#undef T0_64_UNROLL_BYTES
#endif // defined(USE_ARM64_CRC) || defined(USE_CRC_EMU)
#endif // defined(Z7_CRC_HW_USE)
#endif // MY_CPU_LE #endif // MY_CPU_LE
#ifndef Z7_CRC_HW_FORCE
#if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
/*
typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)
(UInt32 v, const void *data, size_t size, const UInt32 *table);
Z7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;
*/
static unsigned g_Crc_Algo;
#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
static unsigned g_Crc_Be;
#endif
#endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
Z7_NO_INLINE
#ifdef Z7_CRC_HW_USE
static UInt32 Z7_FASTCALL CrcUpdate_Base
#else
UInt32 Z7_FASTCALL CrcUpdate
#endif
(UInt32 crc, const void *data, size_t size)
{
#if Z7_CRC_NUM_TABLES_USE == 1
return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
#else // Z7_CRC_NUM_TABLES_USE != 1
#ifdef Z7_CRC_UPDATE_T1_FUNC_NAME
if (g_Crc_Algo == 1)
return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);
#endif
#ifdef MY_CPU_LE
return FUNC_NAME_LE(crc, data, size, g_CrcTable);
#elif defined(MY_CPU_BE)
return FUNC_NAME_BE(crc, data, size, g_CrcTable);
#else
if (g_Crc_Be)
return FUNC_NAME_BE(crc, data, size, g_CrcTable);
else
return FUNC_NAME_LE(crc, data, size, g_CrcTable);
#endif
#endif // Z7_CRC_NUM_TABLES_USE != 1
}
#ifdef Z7_CRC_HW_USE
Z7_NO_INLINE
UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)
{
if (g_Crc_Algo == 0)
return CrcUpdate_HW(crc, data, size);
return CrcUpdate_Base(crc, data, size);
}
#endif
#endif // !defined(Z7_CRC_HW_FORCE)
UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)
{
return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;
}
MY_ALIGN(64)
UInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL];
void Z7_FASTCALL CrcGenerateTable(void) void Z7_FASTCALL CrcGenerateTable(void)
{ {
UInt32 i; UInt32 i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
#if defined(Z7_CRC_HW_FORCE)
g_CrcTable[i] = __crc32b(i, 0);
#else
#define kCrcPoly 0xEDB88320
UInt32 r = i; UInt32 r = i;
unsigned j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
g_CrcTable[i] = r; g_CrcTable[i] = r;
#endif
} }
for (i = 256; i < 256 * CRC_NUM_TABLES; i++) for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++)
{ {
const UInt32 r = g_CrcTable[(size_t)i - 256]; const UInt32 r = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
} }
#if CRC_NUM_TABLES < 4 #if !defined(Z7_CRC_HW_FORCE) && \
g_CrcUpdate = CrcUpdateT1; (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))
#elif defined(MY_CPU_LE)
// g_CrcUpdateT4 = CrcUpdateT4; #if Z7_CRC_NUM_TABLES_USE <= 1
#if CRC_NUM_TABLES < 8 g_Crc_Algo = 1;
g_CrcUpdate = CrcUpdateT4; #else // Z7_CRC_NUM_TABLES_USE <= 1
#else // CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8; #if defined(MY_CPU_LE)
/* g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
#ifdef MY_CPU_X86_OR_AMD64 #else // !defined(MY_CPU_LE)
if (!CPU_Is_InOrder())
#endif
*/
g_CrcUpdate = CrcUpdateT8;
#endif
#else
{ {
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
UInt32 k = 0x01020304; UInt32 k = 0x01020304;
const Byte *p = (const Byte *)&k; const Byte *p = (const Byte *)&k;
if (p[0] == 4 && p[1] == 3) if (p[0] == 4 && p[1] == 3)
{ g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
#if CRC_NUM_TABLES < 8
// g_CrcUpdateT4 = CrcUpdateT4;
g_CrcUpdate = CrcUpdateT4;
#else // CRC_NUM_TABLES >= 8
g_CrcUpdateT8 = CrcUpdateT8;
g_CrcUpdate = CrcUpdateT8;
#endif
}
else if (p[0] != 1 || p[1] != 2) else if (p[0] != 1 || p[1] != 2)
g_CrcUpdate = CrcUpdateT1; g_Crc_Algo = 1;
else else
#endif // MY_CPU_BE #endif // MY_CPU_BE
{ {
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--)
{ {
const UInt32 x = g_CrcTable[(size_t)i - 256]; const UInt32 x = g_CrcTable[(size_t)i - 256];
g_CrcTable[i] = Z7_BSWAP32(x); g_CrcTable[i] = Z7_BSWAP32(x);
} }
#if CRC_NUM_TABLES <= 4 #if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)
g_CrcUpdate = CrcUpdateT1; g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;
#elif CRC_NUM_TABLES <= 8 #endif
// g_CrcUpdateT4 = CrcUpdateT1_BeT4; #if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))
g_CrcUpdate = CrcUpdateT1_BeT4; g_Crc_Be = 1;
#else // CRC_NUM_TABLES > 8 #endif
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
g_CrcUpdate = CrcUpdateT1_BeT8;
#endif
} }
} }
#endif // CRC_NUM_TABLES < 4 #endif // !defined(MY_CPU_LE)
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#ifdef USE_ARM64_CRC #ifdef Z7_CRC_HW_USE
if (CPU_IsSupported_CRC32()) if (CPU_IsSupported_CRC32())
{ g_Crc_Algo = 0;
g_CrcUpdateT0_32 = CrcUpdateT0_32; #endif // Z7_CRC_HW_USE
g_CrcUpdateT0_64 = CrcUpdateT0_64; #endif // MY_CPU_LE
g_CrcUpdate =
#if defined(MY_CPU_ARM) #endif // Z7_CRC_NUM_TABLES_USE <= 1
CrcUpdateT0_32; #endif // g_Crc_Algo was declared
#else }
CrcUpdateT0_64;
#endif Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)
} {
#endif if (algo == 0)
return &CrcUpdate;
#ifdef USE_CRC_EMU
g_CrcUpdateT0_32 = CrcUpdateT0_32; #if defined(Z7_CRC_HW_USE)
g_CrcUpdateT0_64 = CrcUpdateT0_64; if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)
g_CrcUpdate = CrcUpdateT0_64; {
#endif #ifdef Z7_CRC_HW_FORCE
return &CrcUpdate;
#else
if (g_Crc_Algo == 0)
return &CrcUpdate_HW;
#endif
}
#endif
#ifndef Z7_CRC_HW_FORCE
if (algo == Z7_CRC_NUM_TABLES_USE)
return
#ifdef Z7_CRC_HW_USE
&CrcUpdate_Base;
#else
&CrcUpdate;
#endif #endif
#endif
return NULL;
} }
#undef kCrcPoly #undef kCrcPoly
#undef CRC64_NUM_TABLES #undef Z7_CRC_NUM_TABLES_USE
#undef Z7_CRC_NUM_TABLES_TOTAL
#undef CRC_UPDATE_BYTE_2 #undef CRC_UPDATE_BYTE_2
#undef FUNC_NAME_LE_2
#undef FUNC_NAME_LE_1
#undef FUNC_NAME_LE
#undef FUNC_NAME_BE_2
#undef FUNC_NAME_BE_1
#undef FUNC_NAME_BE
#undef CRC_HW_UNROLL_BYTES
#undef CRC_HW_WORD_FUNC
#undef CRC_HW_WORD_TYPE

View file

@ -1,5 +1,5 @@
/* 7zCrc.h -- CRC32 calculation /* 7zCrc.h -- CRC32 calculation
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_7Z_CRC_H #ifndef ZIP7_INC_7Z_CRC_H
#define ZIP7_INC_7Z_CRC_H #define ZIP7_INC_7Z_CRC_H
@ -20,7 +20,8 @@ void Z7_FASTCALL CrcGenerateTable(void);
UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size); UInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size);
UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size); UInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size);
typedef UInt32 (Z7_FASTCALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); typedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size);
Z7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo);
EXTERN_C_END EXTERN_C_END

View file

@ -1,117 +1,199 @@
/* 7zCrcOpt.c -- CRC32 calculation /* 7zCrcOpt.c -- CRC32 calculation (optimized functions)
2023-04-02 : Igor Pavlov : Public domain */ 2023-12-07 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h" #include "CpuArch.h"
#if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1
// for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu
// #define Z7_CRC_DEBUG_BE
#ifdef Z7_CRC_DEBUG_BE
#undef MY_CPU_LE
#define MY_CPU_BE
#endif
// the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c
#ifdef Z7_CRC_NUM_TABLES
#define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
#else
#define Z7_CRC_NUM_TABLES_USE 12
#endif
#if Z7_CRC_NUM_TABLES_USE % 4 || \
Z7_CRC_NUM_TABLES_USE < 4 * 1 || \
Z7_CRC_NUM_TABLES_USE > 4 * 6
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
#endif
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); #define Q(n, d) \
UInt32 Z7_FASTCALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
#define R(a) *((const UInt32 *)(const void *)p + (a))
#define CRC_FUNC_PRE_LE2(step) \
UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
#define CRC_FUNC_PRE_LE(step) \
CRC_FUNC_PRE_LE2(step); \
CRC_FUNC_PRE_LE2(step)
CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) const Byte *lim;
for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4) lim = p + size;
if (size >= Z7_CRC_NUM_TABLES_USE)
{ {
v ^= *(const UInt32 *)(const void *)p; lim -= Z7_CRC_NUM_TABLES_USE;
v = do
(table + 0x300)[((v ) & 0xFF)] {
^ (table + 0x200)[((v >> 8) & 0xFF)] v ^= R(0);
^ (table + 0x100)[((v >> 16) & 0xFF)] {
^ (table + 0x000)[((v >> 24))]; #if Z7_CRC_NUM_TABLES_USE == 1 * 4
v = Q(0, v);
#else
#define U2(r, op) \
{ d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
UInt32 d, x;
U2(1, =)
#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
#define U(r) U2(r, ^=)
U(2)
#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
U(3)
#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
U(4)
#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
U(5)
#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
#endif
#endif
#endif
#endif
#endif
#undef U
#undef U2
v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
#endif
}
p += Z7_CRC_NUM_TABLES_USE;
}
while (p <= lim);
lim += Z7_CRC_NUM_TABLES_USE;
} }
for (; size > 0; size--, p++) for (; p < lim; p++)
v = CRC_UPDATE_BYTE_2(v, *p); v = CRC_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); #undef CRC_UPDATE_BYTE_2
UInt32 Z7_FASTCALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) #undef R
{ #undef Q
const Byte *p = (const Byte *)data; #undef CRC_FUNC_PRE_LE
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++) #undef CRC_FUNC_PRE_LE2
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)(const void *)p;
v =
(table + 0x700)[((v ) & 0xFF)]
^ (table + 0x600)[((v >> 8) & 0xFF)]
^ (table + 0x500)[((v >> 16) & 0xFF)]
^ (table + 0x400)[((v >> 24))];
d = *((const UInt32 *)(const void *)p + 1);
v ^=
(table + 0x300)[((d ) & 0xFF)]
^ (table + 0x200)[((d >> 8) & 0xFF)]
^ (table + 0x100)[((d >> 16) & 0xFF)]
^ (table + 0x000)[((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#endif #endif
#ifndef MY_CPU_LE #ifndef MY_CPU_LE
#define CRC_UINT32_SWAP(v) Z7_BSWAP32(v) #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8)) #define Q(n, d) \
( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
UInt32 Z7_FASTCALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) #ifdef Z7_CRC_DEBUG_BE
#define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))
#else
#define R(a) *((const UInt32 *)(const void *)p + (a))
#endif
#define CRC_FUNC_PRE_BE2(step) \
UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
#define CRC_FUNC_PRE_BE(step) \
CRC_FUNC_PRE_BE2(step); \
CRC_FUNC_PRE_BE2(step)
CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
const Byte *lim;
table += 0x100; table += 0x100;
v = CRC_UINT32_SWAP(v); v = Z7_BSWAP32(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4) lim = p + size;
if (size >= Z7_CRC_NUM_TABLES_USE)
{ {
v ^= *(const UInt32 *)(const void *)p; lim -= Z7_CRC_NUM_TABLES_USE;
v = do
(table + 0x000)[((v ) & 0xFF)] {
^ (table + 0x100)[((v >> 8) & 0xFF)] v ^= R(0);
^ (table + 0x200)[((v >> 16) & 0xFF)] {
^ (table + 0x300)[((v >> 24))]; #if Z7_CRC_NUM_TABLES_USE == 1 * 4
v = Q(0, v);
#else
#define U2(r, op) \
{ d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
UInt32 d, x;
U2(1, =)
#if Z7_CRC_NUM_TABLES_USE >= 3 * 4
#define U(r) U2(r, ^=)
U(2)
#if Z7_CRC_NUM_TABLES_USE >= 4 * 4
U(3)
#if Z7_CRC_NUM_TABLES_USE >= 5 * 4
U(4)
#if Z7_CRC_NUM_TABLES_USE >= 6 * 4
U(5)
#if Z7_CRC_NUM_TABLES_USE >= 7 * 4
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
#endif
#endif
#endif
#endif
#endif
#undef U
#undef U2
v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
#endif
}
p += Z7_CRC_NUM_TABLES_USE;
}
while (p <= lim);
lim += Z7_CRC_NUM_TABLES_USE;
} }
for (; size > 0; size--, p++) for (; p < lim; p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p); v = CRC_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT32_SWAP(v); return Z7_BSWAP32(v);
} }
UInt32 Z7_FASTCALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table) #undef CRC_UPDATE_BYTE_2_BE
{ #undef R
const Byte *p = (const Byte *)data; #undef Q
table += 0x100; #undef CRC_FUNC_PRE_BE
v = CRC_UINT32_SWAP(v); #undef CRC_FUNC_PRE_BE2
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 8; size -= 8, p += 8)
{
UInt32 d;
v ^= *(const UInt32 *)(const void *)p;
v =
(table + 0x400)[((v ) & 0xFF)]
^ (table + 0x500)[((v >> 8) & 0xFF)]
^ (table + 0x600)[((v >> 16) & 0xFF)]
^ (table + 0x700)[((v >> 24))];
d = *((const UInt32 *)(const void *)p + 1);
v ^=
(table + 0x000)[((d ) & 0xFF)]
^ (table + 0x100)[((d >> 8) & 0xFF)]
^ (table + 0x200)[((d >> 16) & 0xFF)]
^ (table + 0x300)[((d >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2_BE(v, *p);
return CRC_UINT32_SWAP(v);
}
#endif #endif
#undef Z7_CRC_NUM_TABLES_USE
#endif

View file

@ -1,5 +1,5 @@
/* 7zDec.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -51,6 +51,7 @@
#ifndef Z7_NO_METHODS_FILTERS #ifndef Z7_NO_METHODS_FILTERS
#define k_Delta 3 #define k_Delta 3
#define k_RISCV 0xb
#define k_BCJ 0x3030103 #define k_BCJ 0x3030103
#define k_PPC 0x3030205 #define k_PPC 0x3030205
#define k_IA64 0x3030401 #define k_IA64 0x3030401
@ -362,6 +363,7 @@ static SRes CheckSupportedFolder(const CSzFolder *f)
case k_IA64: case k_IA64:
case k_SPARC: case k_SPARC:
case k_ARM: case k_ARM:
case k_RISCV:
#endif #endif
#ifdef Z7_USE_FILTER_ARM64 #ifdef Z7_USE_FILTER_ARM64
case k_ARM64: case k_ARM64:
@ -535,10 +537,10 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
} }
} }
} }
#if defined(Z7_USE_BRANCH_FILTER) #if defined(Z7_USE_BRANCH_FILTER)
else if (ci == 1) else if (ci == 1)
{ {
#if !defined(Z7_NO_METHODS_FILTERS) #if !defined(Z7_NO_METHODS_FILTERS)
if (coder->MethodID == k_Delta) if (coder->MethodID == k_Delta)
{ {
if (coder->PropsSize != 1) if (coder->PropsSize != 1)
@ -550,22 +552,43 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
} }
continue; continue;
} }
#endif #endif
#ifdef Z7_USE_FILTER_ARM64 #ifdef Z7_USE_FILTER_ARM64
if (coder->MethodID == k_ARM64) if (coder->MethodID == k_ARM64)
{ {
UInt32 pc = 0; UInt32 pc = 0;
if (coder->PropsSize == 4) if (coder->PropsSize == 4)
{
pc = GetUi32(propsData + coder->PropsOffset); pc = GetUi32(propsData + coder->PropsOffset);
if (pc & 3)
return SZ_ERROR_UNSUPPORTED;
}
else if (coder->PropsSize != 0) else if (coder->PropsSize != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc); z7_BranchConv_ARM64_Dec(outBuffer, outSize, pc);
continue; continue;
} }
#endif #endif
#if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT) #if !defined(Z7_NO_METHODS_FILTERS)
if (coder->MethodID == k_RISCV)
{
UInt32 pc = 0;
if (coder->PropsSize == 4)
{
pc = GetUi32(propsData + coder->PropsOffset);
if (pc & 1)
return SZ_ERROR_UNSUPPORTED;
}
else if (coder->PropsSize != 0)
return SZ_ERROR_UNSUPPORTED;
z7_BranchConv_RISCV_Dec(outBuffer, outSize, pc);
continue;
}
#endif
#if !defined(Z7_NO_METHODS_FILTERS) || defined(Z7_USE_FILTER_ARMT)
{ {
if (coder->PropsSize != 0) if (coder->PropsSize != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
@ -579,7 +602,8 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0 z7_BranchConvSt_X86_Dec(outBuffer, outSize, 0, &state); // pc = 0
break; break;
} }
CASE_BRA_CONV(PPC) case k_PPC: Z7_BRANCH_CONV_DEC_2(BranchConv_PPC)(outBuffer, outSize, 0); break; // pc = 0;
// CASE_BRA_CONV(PPC)
CASE_BRA_CONV(IA64) CASE_BRA_CONV(IA64)
CASE_BRA_CONV(SPARC) CASE_BRA_CONV(SPARC)
CASE_BRA_CONV(ARM) CASE_BRA_CONV(ARM)
@ -592,9 +616,9 @@ static SRes SzFolder_Decode2(const CSzFolder *folder,
} }
continue; continue;
} }
#endif #endif
} // (c == 1) } // (c == 1)
#endif #endif // Z7_USE_BRANCH_FILTER
else else
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }

View file

@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types /* 7zTypes.h -- Basic types
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-24 : Igor Pavlov : Public domain */
#ifndef ZIP7_7Z_TYPES_H #ifndef ZIP7_7Z_TYPES_H
#define ZIP7_7Z_TYPES_H #define ZIP7_7Z_TYPES_H
@ -530,20 +530,20 @@ struct ISzAlloc
#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m) #define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m)
*/ */
#if defined (__clang__) || defined(__GNUC__) #if defined (__clang__) || defined(__GNUC__)
#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ #define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
_Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL \ #define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \
_Pragma("GCC diagnostic pop") _Pragma("GCC diagnostic pop")
#else #else
#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL #define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL
#define Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL #define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
#endif #endif
#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \ #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \
Z7_DIAGNOSCTIC_IGNORE_BEGIN_CAST_QUAL \ Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \
type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \ type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \
Z7_DIAGNOSCTIC_IGNORE_END_CAST_QUAL Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL
#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \ #define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \
Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p) Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p)

View file

@ -1,7 +1,7 @@
#define MY_VER_MAJOR 23 #define MY_VER_MAJOR 24
#define MY_VER_MINOR 01 #define MY_VER_MINOR 05
#define MY_VER_BUILD 0 #define MY_VER_BUILD 0
#define MY_VERSION_NUMBERS "23.01" #define MY_VERSION_NUMBERS "24.05"
#define MY_VERSION MY_VERSION_NUMBERS #define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME #ifdef MY_CPU_NAME
@ -10,12 +10,12 @@
#define MY_VERSION_CPU MY_VERSION #define MY_VERSION_CPU MY_VERSION
#endif #endif
#define MY_DATE "2023-06-20" #define MY_DATE "2024-05-14"
#undef MY_COPYRIGHT #undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE #undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov" #define MY_AUTHOR_NAME "Igor Pavlov"
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2023 Igor Pavlov" #define MY_COPYRIGHT_CR "Copyright (c) 1999-2024 Igor Pavlov"
#ifdef USE_COPYRIGHT_CR #ifdef USE_COPYRIGHT_CR
#define MY_COPYRIGHT MY_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR

View file

@ -22,8 +22,8 @@ CFLAGS_BASE_LIST = -c
# for ASM file # for ASM file
# CFLAGS_BASE_LIST = -S # CFLAGS_BASE_LIST = -S
FLAGS_FLTO =
FLAGS_FLTO = -flto FLAGS_FLTO = -flto
FLAGS_FLTO =
CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ CFLAGS_BASE = $(MY_ARCH_2) -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \
-DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
@ -329,7 +329,7 @@ endif
ifdef IS_ARM64 ifdef IS_ARM64
$O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S $O/LzmaDecOpt.o: ../../../Asm/arm64/LzmaDecOpt.S ../../../Asm/arm64/7zAsm.S
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $(ASM_FLAGS) $<
endif endif
$O/LzmaDec.o: ../../LzmaDec.c $O/LzmaDec.o: ../../LzmaDec.c

56
C/Aes.c
View file

@ -1,5 +1,5 @@
/* Aes.c -- AES encryption / decryption /* Aes.c -- AES encryption / decryption
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -13,7 +13,9 @@ AES_CODE_FUNC g_AesCtr_Code;
UInt32 g_Aes_SupportedFunctions_Flags; UInt32 g_Aes_SupportedFunctions_Flags;
#endif #endif
MY_ALIGN(64)
static UInt32 T[256 * 4]; static UInt32 T[256 * 4];
MY_ALIGN(64)
static const Byte Sbox[256] = { static const Byte Sbox[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
@ -33,7 +35,9 @@ static const Byte Sbox[256] = {
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
MY_ALIGN(64)
static UInt32 D[256 * 4]; static UInt32 D[256 * 4];
MY_ALIGN(64)
static Byte InvS[256]; static Byte InvS[256];
#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) #define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
@ -54,24 +58,54 @@ static Byte InvS[256];
// #define Z7_SHOW_AES_STATUS // #define Z7_SHOW_AES_STATUS
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#define USE_HW_AES
#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #if defined(__INTEL_COMPILER)
#if defined(__clang__) #if (__INTEL_COMPILER >= 1110)
#if (__clang_major__ >= 8) // fix that check
#define USE_HW_AES
#endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define USE_HW_AES #define USE_HW_AES
#if (__INTEL_COMPILER >= 1900)
#define USE_HW_VAES
#endif
#endif #endif
#elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400)
#define USE_HW_AES
#if defined(__clang__) && (__clang_major__ >= 8) \
|| defined(__GNUC__) && (__GNUC__ >= 8)
#define USE_HW_VAES
#endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#if _MSC_VER >= 1910 #define USE_HW_AES
#define USE_HW_VAES
#endif
#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
#if defined(__ARM_FEATURE_AES) \
|| defined(__ARM_FEATURE_CRYPTO)
#define USE_HW_AES
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define USE_HW_AES #define USE_HW_AES
#endif #endif
#endif
#endif
#endif #endif
#endif #endif
#ifdef USE_HW_AES #ifdef USE_HW_AES
// #pragma message("=== Aes.c USE_HW_AES === ")
#ifdef Z7_SHOW_AES_STATUS #ifdef Z7_SHOW_AES_STATUS
#include <stdio.h> #include <stdio.h>
#define PRF(x) x #define PRF(x) x
@ -136,6 +170,7 @@ void AesGenTables(void)
#endif #endif
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#ifdef USE_HW_VAES
if (CPU_IsSupported_VAES_AVX2()) if (CPU_IsSupported_VAES_AVX2())
{ {
PRF(printf("\n===vaes avx2\n")); PRF(printf("\n===vaes avx2\n"));
@ -146,6 +181,7 @@ void AesGenTables(void)
#endif #endif
} }
#endif #endif
#endif
} }
#endif #endif

View file

@ -1,5 +1,5 @@
/* AesOpt.c -- AES optimized code for x86 AES hardware instructions /* AesOpt.c -- AES optimized code for x86 AES hardware instructions
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -15,8 +15,8 @@
#define USE_INTEL_VAES #define USE_INTEL_VAES
#endif #endif
#endif #endif
#elif defined(__clang__) && (__clang_major__ > 3 || __clang_major__ == 3 && __clang_minor__ >= 8) \ #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4) || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400)
#define USE_INTEL_AES #define USE_INTEL_AES
#if !defined(__AES__) #if !defined(__AES__)
#define ATTRIB_AES __attribute__((__target__("aes"))) #define ATTRIB_AES __attribute__((__target__("aes")))
@ -35,27 +35,37 @@
#define USE_INTEL_VAES #define USE_INTEL_VAES
#endif #endif
#endif #endif
#ifndef USE_INTEL_AES
#define Z7_USE_AES_HW_STUB
#endif
#ifndef USE_INTEL_VAES
#define Z7_USE_VAES_HW_STUB
#endif
#endif #endif
#ifndef ATTRIB_AES #ifndef USE_INTEL_AES
#define ATTRIB_AES // #define Z7_USE_AES_HW_STUB // for debug
#endif #endif
#ifndef ATTRIB_VAES #ifndef USE_INTEL_VAES
#define ATTRIB_VAES // #define Z7_USE_VAES_HW_STUB // for debug
#endif #endif
#ifdef USE_INTEL_AES #ifdef USE_INTEL_AES
#include <wmmintrin.h> #include <wmmintrin.h>
#ifndef USE_INTEL_VAES #if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)
#define AES_TYPE_keys UInt32 #define AES_TYPE_keys UInt32
#define AES_TYPE_data Byte #define AES_TYPE_data Byte
// #define AES_TYPE_keys __m128i // #define AES_TYPE_keys __m128i
// #define AES_TYPE_data __m128i // #define AES_TYPE_data __m128i
#endif #endif
#ifndef ATTRIB_AES
#define ATTRIB_AES
#endif
#define AES_FUNC_START(name) \ #define AES_FUNC_START(name) \
void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks) void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks)
// void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks) // void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks)
@ -69,8 +79,6 @@ AES_FUNC_START (name)
#define MM_OP_m(op, src) MM_OP(op, m, src) #define MM_OP_m(op, src) MM_OP(op, m, src)
#define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src) #define MM_XOR( dest, src) MM_OP(_mm_xor_si128, dest, src)
#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
AES_FUNC_START2 (AesCbc_Encode_HW) AES_FUNC_START2 (AesCbc_Encode_HW)
{ {
@ -139,11 +147,6 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
#define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1]) #define XOR_data_M1(reg, ii) MM_XOR (reg, data[ii- 1])
#endif #endif
#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
#define MM_OP_key(op, reg) MM_OP(op, reg, key); #define MM_OP_key(op, reg) MM_OP(op, reg, key);
#define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg) #define AES_DEC( reg, ii) MM_OP_key (_mm_aesdec_si128, reg)
@ -152,27 +155,13 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
#define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg) #define AES_ENC_LAST( reg, ii) MM_OP_key (_mm_aesenclast_si128, reg)
#define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg) #define AES_XOR( reg, ii) MM_OP_key (_mm_xor_si128, reg)
#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
#define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr; #define CTR_START(reg, ii) MM_OP (_mm_add_epi64, ctr, one) reg = ctr;
#define CTR_END( reg, ii) MM_XOR (data[ii], reg) #define CTR_END( reg, ii) MM_XOR (data[ii], reg)
#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
#define WOP_KEY(op, n) { \ #define WOP_KEY(op, n) { \
const __m128i key = w[n]; \ const __m128i key = w[n]; \
WOP(op); } WOP(op); }
#define AVX_WOP_KEY(op, n) { \
const __m256i key = w[n]; \
WOP(op); }
#define WIDE_LOOP_START \ #define WIDE_LOOP_START \
dataEnd = data + numBlocks; \ dataEnd = data + numBlocks; \
@ -190,6 +179,40 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
for (; data < dataEnd; data++) for (; data < dataEnd; data++)
#ifdef USE_INTEL_VAES
#define AVX_XOR(dest, src) MM_OP(_mm256_xor_si256, dest, src)
#define AVX_DECLARE_VAR(reg, ii) __m256i reg;
#define AVX_LOAD_data( reg, ii) reg = ((const __m256i *)(const void *)data)[ii];
#define AVX_STORE_data( reg, ii) ((__m256i *)(void *)data)[ii] = reg;
/*
AVX_XOR_data_M1() needs unaligned memory load
if (we don't use _mm256_loadu_si256() here)
{
Most compilers with enabled optimizations generate fused AVX (LOAD + OP)
instruction that can load unaligned data.
But GCC and CLANG without -O2 or -O1 optimizations can generate separated
LOAD-ALIGNED (vmovdqa) instruction that will fail on execution.
}
Note: some compilers generate more instructions, if we use _mm256_loadu_si256() here.
v23.02: we use _mm256_loadu_si256() here, because we need compatibility with any compiler.
*/
#define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, _mm256_loadu_si256(&(((const __m256i *)(const void *)(data - 1))[ii])))
// for debug only: the following code will fail on execution, if compiled by some compilers:
// #define AVX_XOR_data_M1(reg, ii) AVX_XOR (reg, (((const __m256i *)(const void *)(data - 1))[ii]))
#define AVX_AES_DEC( reg, ii) MM_OP_key (_mm256_aesdec_epi128, reg)
#define AVX_AES_DEC_LAST( reg, ii) MM_OP_key (_mm256_aesdeclast_epi128, reg)
#define AVX_AES_ENC( reg, ii) MM_OP_key (_mm256_aesenc_epi128, reg)
#define AVX_AES_ENC_LAST( reg, ii) MM_OP_key (_mm256_aesenclast_epi128, reg)
#define AVX_AES_XOR( reg, ii) MM_OP_key (_mm256_xor_si256, reg)
#define AVX_CTR_START(reg, ii) MM_OP (_mm256_add_epi64, ctr2, two) reg = _mm256_xor_si256(ctr2, key);
#define AVX_CTR_END( reg, ii) AVX_XOR (((__m256i *)(void *)data)[ii], reg)
#define AVX_WOP_KEY(op, n) { \
const __m256i key = w[n]; \
WOP(op); }
#define NUM_AES_KEYS_MAX 15 #define NUM_AES_KEYS_MAX 15
#define WIDE_LOOP_START_AVX(OP) \ #define WIDE_LOOP_START_AVX(OP) \
@ -214,6 +237,9 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified, /* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified,
MSVC still can insert vzeroupper instruction. */ MSVC still can insert vzeroupper instruction. */
#endif
AES_FUNC_START2 (AesCbc_Decode_HW) AES_FUNC_START2 (AesCbc_Decode_HW)
{ {
@ -380,6 +406,9 @@ required that <immintrin.h> must be included before <avxintrin.h>.
#endif #endif
#endif // __clang__ && _MSC_VER #endif // __clang__ && _MSC_VER
#ifndef ATTRIB_VAES
#define ATTRIB_VAES
#endif
#define VAES_FUNC_START2(name) \ #define VAES_FUNC_START2(name) \
AES_FUNC_START (name); \ AES_FUNC_START (name); \
@ -519,10 +548,18 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
/* no USE_INTEL_AES */ /* no USE_INTEL_AES */
#if defined(Z7_USE_AES_HW_STUB)
// We can compile this file with another C compiler,
// or we can compile asm version.
// So we can generate real code instead of this stub function.
// #if defined(_MSC_VER)
#pragma message("AES HW_SW stub was used") #pragma message("AES HW_SW stub was used")
// #endif
#if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)
#define AES_TYPE_keys UInt32 #define AES_TYPE_keys UInt32
#define AES_TYPE_data Byte #define AES_TYPE_data Byte
#endif
#define AES_FUNC_START(name) \ #define AES_FUNC_START(name) \
void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \ void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \
@ -535,13 +572,16 @@ VAES_FUNC_START2 (AesCtr_Code_HW_256)
AES_COMPAT_STUB (AesCbc_Encode) AES_COMPAT_STUB (AesCbc_Encode)
AES_COMPAT_STUB (AesCbc_Decode) AES_COMPAT_STUB (AesCbc_Decode)
AES_COMPAT_STUB (AesCtr_Code) AES_COMPAT_STUB (AesCtr_Code)
#endif // Z7_USE_AES_HW_STUB
#endif // USE_INTEL_AES #endif // USE_INTEL_AES
#ifndef USE_INTEL_VAES #ifndef USE_INTEL_VAES
#if defined(Z7_USE_VAES_HW_STUB)
// #if defined(_MSC_VER)
#pragma message("VAES HW_SW stub was used") #pragma message("VAES HW_SW stub was used")
// #endif
#define VAES_COMPAT_STUB(name) \ #define VAES_COMPAT_STUB(name) \
void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \ void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \
@ -550,36 +590,59 @@ AES_COMPAT_STUB (AesCtr_Code)
VAES_COMPAT_STUB (AesCbc_Decode_HW) VAES_COMPAT_STUB (AesCbc_Decode_HW)
VAES_COMPAT_STUB (AesCtr_Code_HW) VAES_COMPAT_STUB (AesCtr_Code_HW)
#endif
#endif // ! USE_INTEL_VAES #endif // ! USE_INTEL_VAES
#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
#if defined(__clang__) #if defined(__ARM_FEATURE_AES) \
#if (__clang_major__ >= 8) // fix that check || defined(__ARM_FEATURE_CRYPTO)
#define USE_HW_AES
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define USE_HW_AES #define USE_HW_AES
#endif #endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define USE_HW_AES
#endif #endif
#elif defined(_MSC_VER)
#if _MSC_VER >= 1910
#define USE_HW_AES
#endif #endif
#endif #endif
#ifdef USE_HW_AES #ifdef USE_HW_AES
// #pragma message("=== AES HW === ") // #pragma message("=== AES HW === ")
// __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_AES
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
#if !defined(__ARM_FEATURE_AES) && \
!defined(__ARM_FEATURE_CRYPTO)
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
#if defined(__clang__)
#define ATTRIB_AES __attribute__((__target__("crypto")))
#else
#define ATTRIB_AES __attribute__((__target__("+crypto"))) #define ATTRIB_AES __attribute__((__target__("+crypto")))
#endif
#else #else
#if defined(__clang__)
#define ATTRIB_AES __attribute__((__target__("armv8-a,aes")))
#else
#define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #define ATTRIB_AES __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
#endif
#endif #endif
#endif
#else #else
// _MSC_VER // _MSC_VER
// for arm32 // for arm32
@ -590,11 +653,59 @@ VAES_COMPAT_STUB (AesCtr_Code_HW)
#define ATTRIB_AES #define ATTRIB_AES
#endif #endif
#if defined(_MSC_VER) && defined(MY_CPU_ARM64) #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
#include <arm_neon.h> /*
clang-17.0.1: error : Cannot select: intrinsic %llvm.arm.neon.aese
clang
3.8.1 : __ARM_NEON : defined(__ARM_FEATURE_CRYPTO)
7.0.1 : __ARM_NEON : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)
11.?.0 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)
13.0.1 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_AES)
16 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8
*/
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_AES) && \
!defined(__ARM_FEATURE_CRYPTO)
// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
// #if defined(__clang__) && __clang_major__ < 13
#define __ARM_FEATURE_CRYPTO 1
// #else
#define __ARM_FEATURE_AES 1
// #endif
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif #endif
#endif // clang
#if defined(__clang__)
#if defined(__ARM_ARCH) && __ARM_ARCH < 8
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
// #pragma message("#define __ARM_ARCH 8")
#undef __ARM_ARCH
#define __ARM_ARCH 8
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // clang
#include <arm_neon.h>
#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
defined(__ARM_FEATURE_CRYPTO) && \
defined(__ARM_FEATURE_AES)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#undef __ARM_FEATURE_CRYPTO
#undef __ARM_FEATURE_AES
#undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
#endif
#endif // Z7_MSC_VER_ORIGINAL
typedef uint8x16_t v128; typedef uint8x16_t v128;
@ -620,7 +731,7 @@ AES_FUNC_START (name)
AES_FUNC_START2 (AesCbc_Encode_HW) AES_FUNC_START2 (AesCbc_Encode_HW)
{ {
v128 *p = (v128*)(void*)ivAes; v128 * const p = (v128*)(void*)ivAes;
v128 *data = (v128*)(void*)data8; v128 *data = (v128*)(void*)data8;
v128 m = *p; v128 m = *p;
const v128 k0 = p[2]; const v128 k0 = p[2];
@ -639,7 +750,7 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
const v128 k_z0 = w[2]; const v128 k_z0 = w[2];
for (; numBlocks != 0; numBlocks--, data++) for (; numBlocks != 0; numBlocks--, data++)
{ {
MM_XOR_m (*data); MM_XOR_m (*data)
AES_E_MC_m (k0) AES_E_MC_m (k0)
AES_E_MC_m (k1) AES_E_MC_m (k1)
AES_E_MC_m (k2) AES_E_MC_m (k2)
@ -660,7 +771,7 @@ AES_FUNC_START2 (AesCbc_Encode_HW)
} }
} }
AES_E_m (k_z1) AES_E_m (k_z1)
MM_XOR_m (k_z0); MM_XOR_m (k_z0)
*data = m; *data = m;
} }
*p = m; *p = m;
@ -745,7 +856,7 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
while (w != p); while (w != p);
WOP_KEY (AES_D, 1) WOP_KEY (AES_D, 1)
WOP_KEY (AES_XOR, 0) WOP_KEY (AES_XOR, 0)
MM_XOR (m0, iv); MM_XOR (m0, iv)
WOP_M1 (XOR_data_M1) WOP_M1 (XOR_data_M1)
iv = data[NUM_WAYS - 1]; iv = data[NUM_WAYS - 1];
WOP (STORE_data) WOP (STORE_data)
@ -759,14 +870,14 @@ AES_FUNC_START2 (AesCbc_Decode_HW)
AES_D_IMC_m (w[2]) AES_D_IMC_m (w[2])
do do
{ {
AES_D_IMC_m (w[1]); AES_D_IMC_m (w[1])
AES_D_IMC_m (w[0]); AES_D_IMC_m (w[0])
w -= 2; w -= 2;
} }
while (w != p); while (w != p);
AES_D_m (w[1]); AES_D_m (w[1])
MM_XOR_m (w[0]); MM_XOR_m (w[0])
MM_XOR_m (iv); MM_XOR_m (iv)
iv = *data; iv = *data;
*data = m; *data = m;
} }
@ -783,6 +894,12 @@ AES_FUNC_START2 (AesCtr_Code_HW)
const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2; const v128 *wEnd = p + ((size_t)*(const UInt32 *)(p + 1)) * 2;
const v128 *dataEnd; const v128 *dataEnd;
uint64x2_t one = vdupq_n_u64(0); uint64x2_t one = vdupq_n_u64(0);
// the bug in clang:
// __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2);
#if defined(__clang__) && (__clang_major__ <= 9)
#pragma GCC diagnostic ignored "-Wvector-conversion"
#endif
one = vsetq_lane_u64(1, one, 0); one = vsetq_lane_u64(1, one, 0);
p += 2; p += 2;
@ -809,11 +926,11 @@ AES_FUNC_START2 (AesCtr_Code_HW)
{ {
const v128 *w = p; const v128 *w = p;
v128 m; v128 m;
CTR_START (m, 0); CTR_START (m, 0)
do do
{ {
AES_E_MC_m (w[0]); AES_E_MC_m (w[0])
AES_E_MC_m (w[1]); AES_E_MC_m (w[1])
w += 2; w += 2;
} }
while (w != wEnd); while (w != wEnd);

174
C/Alloc.c
View file

@ -1,5 +1,5 @@
/* Alloc.c -- Memory allocation functions /* Alloc.c -- Memory allocation functions
2023-04-02 : Igor Pavlov : Public domain */ 2024-02-18 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -10,19 +10,18 @@
#include "Alloc.h" #include "Alloc.h"
#ifdef _WIN32 #if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \
#ifdef Z7_LARGE_PAGES (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502) // < Win2003 (xp-64)
#if defined(__clang__) || defined(__GNUC__) #define Z7_USE_DYN_GetLargePageMinimum
typedef void (*Z7_voidFunction)(void); #endif
#define MY_CAST_FUNC (Z7_voidFunction)
#elif defined(_MSC_VER) && _MSC_VER > 1920 // for debug:
#define MY_CAST_FUNC (void *) #if 0
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()' #if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
#else // #pragma message("=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === ")
#define MY_CAST_FUNC #define Z7_ALLOC_NO_OFFSET_ALLOCATOR
#endif
#endif #endif
#endif // Z7_LARGE_PAGES
#endif // _WIN32
// #define SZ_ALLOC_DEBUG // #define SZ_ALLOC_DEBUG
/* #define SZ_ALLOC_DEBUG */ /* #define SZ_ALLOC_DEBUG */
@ -146,7 +145,9 @@ static void PrintAddr(void *p)
#define PRINT_FREE(name, cnt, ptr) #define PRINT_FREE(name, cnt, ptr)
#define Print(s) #define Print(s)
#define PrintLn() #define PrintLn()
#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
#define PrintHex(v, align) #define PrintHex(v, align)
#endif
#define PrintAddr(p) #define PrintAddr(p)
#endif #endif
@ -246,9 +247,9 @@ void MidFree(void *address)
#ifdef Z7_LARGE_PAGES #ifdef Z7_LARGE_PAGES
#ifdef MEM_LARGE_PAGES #ifdef MEM_LARGE_PAGES
#define MY__MEM_LARGE_PAGES MEM_LARGE_PAGES #define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES
#else #else
#define MY__MEM_LARGE_PAGES 0x20000000 #define MY_MEM_LARGE_PAGES 0x20000000
#endif #endif
extern extern
@ -258,19 +259,23 @@ typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
void SetLargePageSize(void) void SetLargePageSize(void)
{ {
#ifdef Z7_LARGE_PAGES
SIZE_T size; SIZE_T size;
#ifdef Z7_USE_DYN_GetLargePageMinimum
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
const const
Func_GetLargePageMinimum fn = Func_GetLargePageMinimum fn =
(Func_GetLargePageMinimum) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
"GetLargePageMinimum"); "GetLargePageMinimum");
if (!fn) if (!fn)
return; return;
size = fn(); size = fn();
#else
size = GetLargePageMinimum();
#endif
if (size == 0 || (size & (size - 1)) != 0) if (size == 0 || (size & (size - 1)) != 0)
return; return;
g_LargePageSize = size; g_LargePageSize = size;
#endif
} }
#endif // Z7_LARGE_PAGES #endif // Z7_LARGE_PAGES
@ -292,7 +297,7 @@ void *BigAlloc(size_t size)
size2 = (size + ps) & ~ps; size2 = (size + ps) & ~ps;
if (size2 >= size) if (size2 >= size)
{ {
void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY__MEM_LARGE_PAGES, PAGE_READWRITE); void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE);
if (p) if (p)
{ {
PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p)
@ -328,20 +333,7 @@ const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
#endif #endif
/* #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
uintptr_t : <stdint.h> C99 (optional)
: unsupported in VS6
*/
#ifdef _WIN32
typedef UINT_PTR UIntPtr;
#else
/*
typedef uintptr_t UIntPtr;
*/
typedef ptrdiff_t UIntPtr;
#endif
#define ADJUST_ALLOC_SIZE 0 #define ADJUST_ALLOC_SIZE 0
/* /*
@ -352,14 +344,36 @@ const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
MyAlloc() can return address that is NOT multiple of sizeof(void *). MyAlloc() can return address that is NOT multiple of sizeof(void *).
*/ */
/* /*
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) uintptr_t : <stdint.h> C99 (optional)
: unsupported in VS6
*/ */
#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) typedef
#ifdef _WIN32
UINT_PTR
#elif 1
uintptr_t
#else
ptrdiff_t
#endif
MY_uintptr_t;
#if 0 \
|| (defined(__CHERI__) \
|| defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8))
// for 128-bit pointers (cheri):
#define MY_ALIGN_PTR_DOWN(p, align) \
((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1))))
#else
#define MY_ALIGN_PTR_DOWN(p, align) \
((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1))))
#endif
#if !defined(_WIN32) && defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) #endif
#if !defined(_WIN32) \
&& (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \
|| defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
#define USE_posix_memalign #define USE_posix_memalign
#endif #endif
@ -399,14 +413,13 @@ static int posix_memalign(void **ptr, size_t align, size_t size)
#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) #define ALLOC_ALIGN_SIZE ((size_t)1 << 7)
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) void *z7_AlignedAlloc(size_t size)
{ {
#ifndef USE_posix_memalign #ifndef USE_posix_memalign
void *p; void *p;
void *pAligned; void *pAligned;
size_t newSize; size_t newSize;
UNUSED_VAR(pp)
/* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned
block to prevent cache line sharing with another allocated blocks */ block to prevent cache line sharing with another allocated blocks */
@ -431,10 +444,9 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
return pAligned; return pAligned;
#else #else
void *p; void *p;
UNUSED_VAR(pp)
if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))
return NULL; return NULL;
@ -443,19 +455,37 @@ static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
return p; return p;
#endif #endif
}
void z7_AlignedFree(void *address)
{
#ifndef USE_posix_memalign
if (address)
MyFree(((void **)address)[-1]);
#else
free(address);
#endif
}
static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)
{
UNUSED_VAR(pp)
return z7_AlignedAlloc(size);
} }
static void SzAlignedFree(ISzAllocPtr pp, void *address) static void SzAlignedFree(ISzAllocPtr pp, void *address)
{ {
UNUSED_VAR(pp) UNUSED_VAR(pp)
#ifndef USE_posix_memalign #ifndef USE_posix_memalign
if (address) if (address)
MyFree(((void **)address)[-1]); MyFree(((void **)address)[-1]);
#else #else
free(address); free(address);
#endif #endif
} }
@ -463,16 +493,44 @@ const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ /* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */
#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] #ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
/* #if 1
#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] #define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *))
*/ #define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]
#else
// we can use this simplified code,
// if (CAlignOffsetAlloc::offset == (k * sizeof(void *))
#define REAL_BLOCK_PTR_VAR(p) (((void **)(p))[-1])
#endif
#endif
#if 0
#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR
#include <stdio.h>
static void PrintPtr(const char *s, const void *p)
{
const Byte *p2 = (const Byte *)&p;
unsigned i;
printf("%s %p ", s, p);
for (i = sizeof(p); i != 0;)
{
i--;
printf("%02x", p2[i]);
}
printf("\n");
}
#endif
#endif
static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
{ {
#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
UNUSED_VAR(pp)
return z7_AlignedAlloc(size);
#else
const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
void *adr; void *adr;
void *pAligned; void *pAligned;
@ -501,6 +559,12 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +
alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;
#if 0
printf("\nalignSize = %6x, offset=%6x, size=%8x \n", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size);
PrintPtr("base", adr);
PrintPtr("alig", pAligned);
#endif
PrintLn(); PrintLn();
Print("- Aligned: "); Print("- Aligned: ");
Print(" size="); PrintHex(size, 8); Print(" size="); PrintHex(size, 8);
@ -512,11 +576,16 @@ static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)
REAL_BLOCK_PTR_VAR(pAligned) = adr; REAL_BLOCK_PTR_VAR(pAligned) = adr;
return pAligned; return pAligned;
#endif
} }
static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
{ {
#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)
UNUSED_VAR(pp)
z7_AlignedFree(address);
#else
if (address) if (address)
{ {
const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt); const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);
@ -525,6 +594,7 @@ static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)
PrintLn(); PrintLn();
ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));
} }
#endif
} }

View file

@ -1,5 +1,5 @@
/* Alloc.h -- Memory allocation functions /* Alloc.h -- Memory allocation functions
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_ALLOC_H #ifndef ZIP7_INC_ALLOC_H
#define ZIP7_INC_ALLOC_H #define ZIP7_INC_ALLOC_H
@ -22,6 +22,9 @@ void *MyAlloc(size_t size);
void MyFree(void *address); void MyFree(void *address);
void *MyRealloc(void *address, size_t size); void *MyRealloc(void *address, size_t size);
void *z7_AlignedAlloc(size_t size);
void z7_AlignedFree(void *p);
#ifdef _WIN32 #ifdef _WIN32
#ifdef Z7_LARGE_PAGES #ifdef Z7_LARGE_PAGES
@ -33,12 +36,14 @@ void MidFree(void *address);
void *BigAlloc(size_t size); void *BigAlloc(size_t size);
void BigFree(void *address); void BigFree(void *address);
/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */
#else #else
#define MidAlloc(size) MyAlloc(size) #define MidAlloc(size) z7_AlignedAlloc(size)
#define MidFree(address) MyFree(address) #define MidFree(address) z7_AlignedFree(address)
#define BigAlloc(size) MyAlloc(size) #define BigAlloc(size) z7_AlignedAlloc(size)
#define BigFree(address) MyFree(address) #define BigFree(address) z7_AlignedFree(address)
#endif #endif

12
C/Asm_c.mak Normal file
View file

@ -0,0 +1,12 @@
!IFDEF ASM_OBJS
!IF "$(PLATFORM)" == "arm64"
$(ASM_OBJS): ../../../Asm/arm64/$(*B).S
$(COMPL_ASM_CLANG)
!ELSEIF "$(PLATFORM)" == "arm"
$(ASM_OBJS): ../../../Asm/arm/$(*B).asm
$(COMPL_ASM)
!ELSEIF "$(PLATFORM)" != "ia64" && "$(PLATFORM)" != "mips"
$(ASM_OBJS): ../../../Asm/x86/$(*B).asm
$(COMPL_ASM)
!ENDIF
!ENDIF

View file

@ -1,47 +1,104 @@
/* Blake2.h -- BLAKE2 Hash /* Blake2.h -- BLAKE2sp Hash
2023-03-04 : Igor Pavlov : Public domain 2024-01-17 : Igor Pavlov : Public domain */
2015 : Samuel Neves : Public domain */
#ifndef ZIP7_INC_BLAKE2_H #ifndef ZIP7_INC_BLAKE2_H
#define ZIP7_INC_BLAKE2_H #define ZIP7_INC_BLAKE2_H
#include "7zTypes.h" #include "7zTypes.h"
#if 0
#include "Compiler.h"
#include "CpuArch.h"
#if defined(MY_CPU_X86_OR_AMD64)
#if defined(__SSE2__) \
|| defined(_MSC_VER) && _MSC_VER > 1200 \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
|| defined(__clang__) \
|| defined(__INTEL_COMPILER)
#include <emmintrin.h> // SSE2
#endif
#if defined(__AVX2__) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
|| defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
|| defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
#include <immintrin.h>
#if defined(__clang__)
#include <avxintrin.h>
#include <avx2intrin.h>
#endif
#endif // avx2
#endif // MY_CPU_X86_OR_AMD64
#endif // 0
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define BLAKE2S_BLOCK_SIZE 64 #define Z7_BLAKE2S_BLOCK_SIZE 64
#define BLAKE2S_DIGEST_SIZE 32 #define Z7_BLAKE2S_DIGEST_SIZE 32
#define BLAKE2SP_PARALLEL_DEGREE 8 #define Z7_BLAKE2SP_PARALLEL_DEGREE 8
#define Z7_BLAKE2SP_NUM_STRUCT_WORDS 16
#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_COMPRESS)(UInt32 *states, const Byte *data, const Byte *end);
typedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_INIT)(UInt32 *states);
#endif
// it's required that CBlake2sp is aligned for 32-bytes,
// because the code can use unaligned access with sse and avx256.
// but 64-bytes alignment can be better.
MY_ALIGN(64)
typedef struct typedef struct
{ {
UInt32 h[8]; union
UInt32 t[2]; {
UInt32 f[2]; #if 0
Byte buf[BLAKE2S_BLOCK_SIZE]; #if defined(MY_CPU_X86_OR_AMD64)
UInt32 bufPos; #if defined(__SSE2__) \
UInt32 lastNode_f1; || defined(_MSC_VER) && _MSC_VER > 1200 \
UInt32 dummy[2]; /* for sizeof(CBlake2s) alignment */ || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \
} CBlake2s; || defined(__clang__) \
|| defined(__INTEL_COMPILER)
__m128i _pad_align_128bit[4];
#endif // sse2
#if defined(__AVX2__) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
|| defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
|| defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
__m256i _pad_align_256bit[2];
#endif // avx2
#endif // x86
#endif // 0
/* You need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0() */ void * _pad_align_ptr[8];
/* UInt32 _pad_align_32bit[16];
void Blake2s_Init0(CBlake2s *p); struct
void Blake2s_Update(CBlake2s *p, const Byte *data, size_t size); {
void Blake2s_Final(CBlake2s *p, Byte *digest); unsigned cycPos;
*/ unsigned _pad_unused;
#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)
Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Fast;
typedef struct Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Single;
{ Z7_BLAKE2SP_FUNC_INIT func_Init;
CBlake2s S[BLAKE2SP_PARALLEL_DEGREE]; Z7_BLAKE2SP_FUNC_INIT func_Final;
unsigned bufPos; #endif
} header;
} u;
// MY_ALIGN(64)
UInt32 states[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS];
// MY_ALIGN(64)
UInt32 buf32[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS * 2];
} CBlake2sp; } CBlake2sp;
BoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo);
void Blake2sp_Init(CBlake2sp *p); void Blake2sp_Init(CBlake2sp *p);
void Blake2sp_InitState(CBlake2sp *p);
void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size); void Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);
void Blake2sp_Final(CBlake2sp *p, Byte *digest); void Blake2sp_Final(CBlake2sp *p, Byte *digest);
void z7_Black2sp_Prepare(void);
EXTERN_C_END EXTERN_C_END

File diff suppressed because it is too large Load diff

325
C/Bra.c
View file

@ -1,11 +1,11 @@
/* Bra.c -- Branch converters for RISC code /* Bra.c -- Branch converters for RISC code
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-20 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h"
#include "RotateDefs.h" #include "RotateDefs.h"
#include "CpuArch.h"
#if defined(MY_CPU_SIZEOF_POINTER) \ #if defined(MY_CPU_SIZEOF_POINTER) \
&& ( MY_CPU_SIZEOF_POINTER == 4 \ && ( MY_CPU_SIZEOF_POINTER == 4 \
@ -26,7 +26,7 @@
#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c; #define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;
// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c; // #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;
#define Z7_BRANCH_CONV(name) z7_BranchConv_ ## name #define Z7_BRANCH_CONV(name) z7_ ## name
#define Z7_BRANCH_FUNC_MAIN(name) \ #define Z7_BRANCH_FUNC_MAIN(name) \
static \ static \
@ -42,11 +42,11 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
#ifdef Z7_EXTRACT_ONLY #ifdef Z7_EXTRACT_ONLY
#define Z7_BRANCH_FUNCS_IMP(name) \ #define Z7_BRANCH_FUNCS_IMP(name) \
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)
#else #else
#define Z7_BRANCH_FUNCS_IMP(name) \ #define Z7_BRANCH_FUNCS_IMP(name) \
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC, 0) \ Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \
Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC, 1) Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)
#endif #endif
#if defined(__clang__) #if defined(__clang__)
@ -72,7 +72,7 @@ Byte *m(name)(Byte *data, SizeT size, UInt32 pc) \
#endif #endif
Z7_BRANCH_FUNC_MAIN(ARM64) Z7_BRANCH_FUNC_MAIN(BranchConv_ARM64)
{ {
// Byte *p = data; // Byte *p = data;
const Byte *lim; const Byte *lim;
@ -121,10 +121,10 @@ Z7_BRANCH_FUNC_MAIN(ARM64)
} }
} }
} }
Z7_BRANCH_FUNCS_IMP(ARM64) Z7_BRANCH_FUNCS_IMP(BranchConv_ARM64)
Z7_BRANCH_FUNC_MAIN(ARM) Z7_BRANCH_FUNC_MAIN(BranchConv_ARM)
{ {
// Byte *p = data; // Byte *p = data;
const Byte *lim; const Byte *lim;
@ -152,10 +152,10 @@ Z7_BRANCH_FUNC_MAIN(ARM)
} }
} }
} }
Z7_BRANCH_FUNCS_IMP(ARM) Z7_BRANCH_FUNCS_IMP(BranchConv_ARM)
Z7_BRANCH_FUNC_MAIN(PPC) Z7_BRANCH_FUNC_MAIN(BranchConv_PPC)
{ {
// Byte *p = data; // Byte *p = data;
const Byte *lim; const Byte *lim;
@ -192,14 +192,14 @@ Z7_BRANCH_FUNC_MAIN(PPC)
} }
} }
} }
Z7_BRANCH_FUNCS_IMP(PPC) Z7_BRANCH_FUNCS_IMP(BranchConv_PPC)
#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED #ifdef Z7_CPU_FAST_ROTATE_SUPPORTED
#define BR_SPARC_USE_ROTATE #define BR_SPARC_USE_ROTATE
#endif #endif
Z7_BRANCH_FUNC_MAIN(SPARC) Z7_BRANCH_FUNC_MAIN(BranchConv_SPARC)
{ {
// Byte *p = data; // Byte *p = data;
const Byte *lim; const Byte *lim;
@ -254,10 +254,10 @@ Z7_BRANCH_FUNC_MAIN(SPARC)
} }
} }
} }
Z7_BRANCH_FUNCS_IMP(SPARC) Z7_BRANCH_FUNCS_IMP(BranchConv_SPARC)
Z7_BRANCH_FUNC_MAIN(ARMT) Z7_BRANCH_FUNC_MAIN(BranchConv_ARMT)
{ {
// Byte *p = data; // Byte *p = data;
Byte *lim; Byte *lim;
@ -335,12 +335,12 @@ Z7_BRANCH_FUNC_MAIN(ARMT)
// return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2)); // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));
// return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2)); // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));
} }
Z7_BRANCH_FUNCS_IMP(ARMT) Z7_BRANCH_FUNCS_IMP(BranchConv_ARMT)
// #define BR_IA64_NO_INLINE // #define BR_IA64_NO_INLINE
Z7_BRANCH_FUNC_MAIN(IA64) Z7_BRANCH_FUNC_MAIN(BranchConv_IA64)
{ {
// Byte *p = data; // Byte *p = data;
const Byte *lim; const Byte *lim;
@ -417,4 +417,293 @@ Z7_BRANCH_FUNC_MAIN(IA64)
} }
} }
} }
Z7_BRANCH_FUNCS_IMP(IA64) Z7_BRANCH_FUNCS_IMP(BranchConv_IA64)
#define BR_CONVERT_VAL_ENC(v) v += BR_PC_GET;
#define BR_CONVERT_VAL_DEC(v) v -= BR_PC_GET;
#if 1 && defined(MY_CPU_LE_UNALIGN)
#define RISCV_USE_UNALIGNED_LOAD
#endif
#ifdef RISCV_USE_UNALIGNED_LOAD
#define RISCV_GET_UI32(p) GetUi32(p)
#define RISCV_SET_UI32(p, v) { SetUi32(p, v) }
#else
#define RISCV_GET_UI32(p) \
((UInt32)GetUi16a(p) + \
((UInt32)GetUi16a((p) + 2) << 16))
#define RISCV_SET_UI32(p, v) { \
SetUi16a(p, (UInt16)(v)) \
SetUi16a((p) + 2, (UInt16)(v >> 16)) }
#endif
#if 1 && defined(MY_CPU_LE)
#define RISCV_USE_16BIT_LOAD
#endif
#ifdef RISCV_USE_16BIT_LOAD
#define RISCV_LOAD_VAL(p) GetUi16a(p)
#else
#define RISCV_LOAD_VAL(p) (*(p))
#endif
#define RISCV_INSTR_SIZE 2
#define RISCV_STEP_1 (4 + RISCV_INSTR_SIZE)
#define RISCV_STEP_2 4
#define RISCV_REG_VAL (2 << 7)
#define RISCV_CMD_VAL 3
#if 1
// for code size optimization:
#define RISCV_DELTA_7F 0x7f
#else
#define RISCV_DELTA_7F 0
#endif
#define RISCV_CHECK_1(v, b) \
(((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)
#if 1
#define RISCV_CHECK_2(v, r) \
((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \
<< 18) \
< ((r) & 0x1d))
#else
// this branch gives larger code, because
// compilers generate larger code for big constants.
#define RISCV_CHECK_2(v, r) \
((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
& ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \
< ((r) & 0x1d))
#endif
#define RISCV_SCAN_LOOP \
Byte *lim; \
size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \
if (size <= 6) return p; \
size -= 6; \
lim = p + size; \
BR_PC_INIT \
for (;;) \
{ \
UInt32 a, v; \
/* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \
for (;;) \
{ \
if Z7_UNLIKELY(p >= lim) { return p; } \
a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \
if ((a & 0x77) == 0) break; \
a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \
p += RISCV_INSTR_SIZE * 2; \
if ((a & 0x77) == 0) \
{ \
p -= RISCV_INSTR_SIZE; \
if Z7_UNLIKELY(p >= lim) { return p; } \
break; \
} \
}
// (xx6f ^ 10) + 1 = xx7f + 1 = xx80 : JAL
// (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL
// (xx17 ^ 10) + 1 = xx07 + 1 = xx08 : AUIPC
// (xx97 ^ 10) + 1 = xx87 + 1 = xx88 : AUIPC
Byte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)
{
RISCV_SCAN_LOOP
v = a;
a = RISCV_GET_UI32(p);
#ifndef RISCV_USE_16BIT_LOAD
v += (UInt32)p[1] << 8;
#endif
if ((v & 8) == 0) // JAL
{
if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)
{
p += RISCV_INSTR_SIZE;
continue;
}
{
v = ((a & 1u << 31) >> 11)
| ((a & 0x3ff << 21) >> 20)
| ((a & 1 << 20) >> 9)
| (a & 0xff << 12);
BR_CONVERT_VAL_ENC(v)
// ((v & 1) == 0)
// v: bits [1 : 20] contain offset bits
#if 0 && defined(RISCV_USE_UNALIGNED_LOAD)
a &= 0xfff;
a |= ((UInt32)(v << 23))
| ((UInt32)(v << 7) & ((UInt32)0xff << 16))
| ((UInt32)(v >> 5) & ((UInt32)0xf0 << 8));
RISCV_SET_UI32(p, a)
#else // aligned
#if 0
SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))
#else
p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));
#endif
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
v <<= 15;
v = Z7_BSWAP32(v);
SetUi16a(p + 2, (UInt16)v)
#else
p[2] = (Byte)(v >> 9);
p[3] = (Byte)(v >> 1);
#endif
#endif // aligned
}
p += 4;
continue;
} // JAL
{
// AUIPC
if (v & 0xe80) // (not x0) and (not x2)
{
const UInt32 b = RISCV_GET_UI32(p + 4);
if (RISCV_CHECK_1(v, b))
{
{
const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);
RISCV_SET_UI32(p, temp)
}
a &= 0xfffff000;
{
#if 1
const int t = -1 >> 1;
if (t != -1)
a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation
else
#endif
a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).
}
BR_CONVERT_VAL_ENC(a)
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
a = Z7_BSWAP32(a);
RISCV_SET_UI32(p + 4, a)
#else
SetBe32(p + 4, a)
#endif
p += 8;
}
else
p += RISCV_STEP_1;
}
else
{
UInt32 r = a >> 27;
if (RISCV_CHECK_2(v, r))
{
v = RISCV_GET_UI32(p + 4);
r = (r << 7) + 0x17 + (v & 0xfffff000);
a = (a >> 12) | (v << 20);
RISCV_SET_UI32(p, r)
RISCV_SET_UI32(p + 4, a)
p += 8;
}
else
p += RISCV_STEP_2;
}
}
} // for
}
Byte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)
{
RISCV_SCAN_LOOP
#ifdef RISCV_USE_16BIT_LOAD
if ((a & 8) == 0)
{
#else
v = a;
a += (UInt32)p[1] << 8;
if ((v & 8) == 0)
{
#endif
// JAL
a -= 0x100 - RISCV_DELTA_7F;
if (a & 0xd80)
{
p += RISCV_INSTR_SIZE;
continue;
}
{
const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;
#if 0 // unaligned
a = GetUi32(p);
v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)
| (UInt32)(a >> 7) & ((UInt32)0xff << 9)
#elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
v = GetUi16a(p + 2);
v = Z7_BSWAP32(v) >> 15
#else
v = (UInt32)p[3] << 1
| (UInt32)p[2] << 9
#endif
| (UInt32)((a & 0xf000) << 5);
BR_CONVERT_VAL_DEC(v)
a = a_old
| (v << 11 & 1u << 31)
| (v << 20 & 0x3ff << 21)
| (v << 9 & 1 << 20)
| (v & 0xff << 12);
RISCV_SET_UI32(p, a)
}
p += 4;
continue;
} // JAL
{
// AUIPC
v = a;
#if 1 && defined(RISCV_USE_UNALIGNED_LOAD)
a = GetUi32(p);
#else
a |= (UInt32)GetUi16a(p + 2) << 16;
#endif
if ((v & 0xe80) == 0) // x0/x2
{
const UInt32 r = a >> 27;
if (RISCV_CHECK_2(v, r))
{
UInt32 b;
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)
b = RISCV_GET_UI32(p + 4);
b = Z7_BSWAP32(b);
#else
b = GetBe32(p + 4);
#endif
v = a >> 12;
BR_CONVERT_VAL_DEC(b)
a = (r << 7) + 0x17;
a += (b + 0x800) & 0xfffff000;
v |= b << 20;
RISCV_SET_UI32(p, a)
RISCV_SET_UI32(p + 4, v)
p += 8;
}
else
p += RISCV_STEP_2;
}
else
{
const UInt32 b = RISCV_GET_UI32(p + 4);
if (!RISCV_CHECK_1(v, b))
p += RISCV_STEP_1;
else
{
v = (a & 0xfffff000) | (b >> 20);
a = (b << 12) | (0x17 + RISCV_REG_VAL);
RISCV_SET_UI32(p, a)
RISCV_SET_UI32(p + 4, v)
p += 8;
}
}
}
} // for
}

36
C/Bra.h
View file

@ -1,5 +1,5 @@
/* Bra.h -- Branch converters for executables /* Bra.h -- Branch converters for executables
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-20 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_BRA_H #ifndef ZIP7_INC_BRA_H
#define ZIP7_INC_BRA_H #define ZIP7_INC_BRA_H
@ -8,8 +8,12 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
#define Z7_BRANCH_CONV_DEC(name) z7_BranchConv_ ## name ## _Dec /* #define PPC BAD_PPC_11 // for debug */
#define Z7_BRANCH_CONV_ENC(name) z7_BranchConv_ ## name ## _Enc
#define Z7_BRANCH_CONV_DEC_2(name) z7_ ## name ## _Dec
#define Z7_BRANCH_CONV_ENC_2(name) z7_ ## name ## _Enc
#define Z7_BRANCH_CONV_DEC(name) Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name)
#define Z7_BRANCH_CONV_ENC(name) Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name)
#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec #define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec
#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc #define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc
@ -20,19 +24,20 @@ typedef Z7_BRANCH_CONV_DECL( (*z7_Func_BranchConv));
typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt)); typedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt));
#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0 #define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0
Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_DEC(X86)); Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86));
Z7_BRANCH_CONV_ST_DECL(Z7_BRANCH_CONV_ST_ENC(X86)); Z7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86));
#define Z7_BRANCH_FUNCS_DECL(name) \ #define Z7_BRANCH_FUNCS_DECL(name) \
Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_DEC(name)); \ Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \
Z7_BRANCH_CONV_DECL(Z7_BRANCH_CONV_ENC(name)); Z7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name));
Z7_BRANCH_FUNCS_DECL(ARM64) Z7_BRANCH_FUNCS_DECL (BranchConv_ARM64)
Z7_BRANCH_FUNCS_DECL(ARM) Z7_BRANCH_FUNCS_DECL (BranchConv_ARM)
Z7_BRANCH_FUNCS_DECL(ARMT) Z7_BRANCH_FUNCS_DECL (BranchConv_ARMT)
Z7_BRANCH_FUNCS_DECL(PPC) Z7_BRANCH_FUNCS_DECL (BranchConv_PPC)
Z7_BRANCH_FUNCS_DECL(SPARC) Z7_BRANCH_FUNCS_DECL (BranchConv_SPARC)
Z7_BRANCH_FUNCS_DECL(IA64) Z7_BRANCH_FUNCS_DECL (BranchConv_IA64)
Z7_BRANCH_FUNCS_DECL (BranchConv_RISCV)
/* /*
These functions convert data that contain CPU instructions. These functions convert data that contain CPU instructions.
@ -49,14 +54,14 @@ and one for decoding (_Enc/_Dec postfixes in function name).
In params: In params:
data : data buffer data : data buffer
size : size of data size : size of data
pc : current virtual Program Counter (Instruction Pinter) value pc : current virtual Program Counter (Instruction Pointer) value
In/Out param: In/Out param:
state : pointer to state variable (for X86 converter only) state : pointer to state variable (for X86 converter only)
Return: Return:
The pointer to position in (data) buffer after last byte that was processed. The pointer to position in (data) buffer after last byte that was processed.
If the caller calls converter again, it must call it starting with that position. If the caller calls converter again, it must call it starting with that position.
But the caller is allowed to move data in buffer. so pointer to But the caller is allowed to move data in buffer. So pointer to
current processed position also will be changed for next call. current processed position also will be changed for next call.
Also the caller must increase internal (pc) value for next call. Also the caller must increase internal (pc) value for next call.
@ -65,6 +70,7 @@ Each converter has some characteristics: Endian, Alignment, LookAhead.
X86 little 1 4 X86 little 1 4
ARMT little 2 2 ARMT little 2 2
RISCV little 2 6
ARM little 4 0 ARM little 4 0
ARM64 little 4 0 ARM64 little 4 0
PPC big 4 0 PPC big 4 0

View file

@ -1,5 +1,5 @@
/* Compiler.h : Compiler specific defines and pragmas /* Compiler.h : Compiler specific defines and pragmas
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_COMPILER_H #ifndef ZIP7_INC_COMPILER_H
#define ZIP7_INC_COMPILER_H #define ZIP7_INC_COMPILER_H
@ -25,11 +25,79 @@
#define Z7_MINGW #define Z7_MINGW
#endif #endif
#if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__))
#define Z7_MCST_LCC
#define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__)
#endif
/*
#if defined(__AVX2__) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|| defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \
|| defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \
|| defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)
#define Z7_COMPILER_AVX2_SUPPORTED
#endif
#endif
*/
// #pragma GCC diagnostic ignored "-Wunknown-pragmas" // #pragma GCC diagnostic ignored "-Wunknown-pragmas"
#ifdef __clang__ #ifdef __clang__
// padding size of '' with 4 bytes to alignment boundary // padding size of '' with 4 bytes to alignment boundary
#pragma GCC diagnostic ignored "-Wpadded" #pragma GCC diagnostic ignored "-Wpadded"
#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \
&& defined(__FreeBSD__)
// freebsd:
#pragma GCC diagnostic ignored "-Wexcess-padding"
#endif
#if __clang_major__ >= 16
#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
#endif
#if __clang_major__ == 13
#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
// cheri
#pragma GCC diagnostic ignored "-Wcapability-to-integer-cast"
#endif
#endif
#if __clang_major__ == 13
// for <arm_neon.h>
#pragma GCC diagnostic ignored "-Wreserved-identifier"
#endif
#endif // __clang__
#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16
// #pragma GCC diagnostic ignored "-Wcast-function-type-strict"
#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \
_Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"")
#else
#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
#endif
typedef void (*Z7_void_Function)(void);
#if defined(__clang__) || defined(__GNUC__)
#define Z7_CAST_FUNC_C (Z7_void_Function)
#elif defined(_MSC_VER) && _MSC_VER > 1920
#define Z7_CAST_FUNC_C (void *)
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
#else
#define Z7_CAST_FUNC_C
#endif
/*
#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)
// #pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
*/
#ifdef __GNUC__
#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000)
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
#endif #endif
@ -101,7 +169,8 @@
_Pragma("clang loop unroll(disable)") \ _Pragma("clang loop unroll(disable)") \
_Pragma("clang loop vectorize(disable)") _Pragma("clang loop vectorize(disable)")
#define Z7_ATTRIB_NO_VECTORIZE #define Z7_ATTRIB_NO_VECTORIZE
#elif defined(__GNUC__) && (__GNUC__ >= 5) #elif defined(__GNUC__) && (__GNUC__ >= 5) \
&& (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610))
#define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
// __attribute__((optimize("no-unroll-loops"))); // __attribute__((optimize("no-unroll-loops")));
#define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE
@ -142,15 +211,23 @@
#endif #endif
#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 36000)) #if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600))
#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
#if (Z7_CLANG_VERSION < 130000)
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wreserved-id-macro\"")
#else
#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \
_Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"") _Pragma("GCC diagnostic ignored \"-Wreserved-macro-identifier\"")
#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \ #endif
#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \
_Pragma("GCC diagnostic pop") _Pragma("GCC diagnostic pop")
#else #else
#define Z7_DIAGNOSCTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER #define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define Z7_DIAGNOSCTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER #define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif #endif
#define UNUSED_VAR(x) (void)x; #define UNUSED_VAR(x) (void)x;

View file

@ -1,5 +1,5 @@
/* CpuArch.c -- CPU specific code /* CpuArch.c -- CPU specific code
2023-05-18 : Igor Pavlov : Public domain */ 2024-03-02 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -226,7 +226,7 @@ void __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!! DON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!
*/ */
static static
Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(UInt32 subFunction, UInt32 func, int *CPUInfo) Z7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)
{ {
UNUSED_VAR(subFunction) UNUSED_VAR(subFunction)
__cpuid(CPUInfo, func); __cpuid(CPUInfo, func);
@ -242,13 +242,13 @@ Z7_NO_INLINE
#endif #endif
void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func) void Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)
{ {
MY_cpuidex((int *)p, (int)func, 0); MY_cpuidex((Int32 *)p, (Int32)func, 0);
} }
Z7_NO_INLINE Z7_NO_INLINE
UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void) UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)
{ {
int a[4]; Int32 a[4];
MY_cpuidex(a, 0, 0); MY_cpuidex(a, 0, 0);
return a[0]; return a[0];
} }
@ -384,7 +384,7 @@ BoolInt CPU_IsSupported_CMOV(void)
UInt32 a[4]; UInt32 a[4];
if (!x86cpuid_Func_1(&a[0])) if (!x86cpuid_Func_1(&a[0]))
return 0; return 0;
return (a[3] >> 15) & 1; return (BoolInt)(a[3] >> 15) & 1;
} }
BoolInt CPU_IsSupported_SSE(void) BoolInt CPU_IsSupported_SSE(void)
@ -393,7 +393,7 @@ BoolInt CPU_IsSupported_SSE(void)
CHECK_SYS_SSE_SUPPORT CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_Func_1(&a[0])) if (!x86cpuid_Func_1(&a[0]))
return 0; return 0;
return (a[3] >> 25) & 1; return (BoolInt)(a[3] >> 25) & 1;
} }
BoolInt CPU_IsSupported_SSE2(void) BoolInt CPU_IsSupported_SSE2(void)
@ -402,7 +402,7 @@ BoolInt CPU_IsSupported_SSE2(void)
CHECK_SYS_SSE_SUPPORT CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_Func_1(&a[0])) if (!x86cpuid_Func_1(&a[0]))
return 0; return 0;
return (a[3] >> 26) & 1; return (BoolInt)(a[3] >> 26) & 1;
} }
#endif #endif
@ -419,17 +419,17 @@ static UInt32 x86cpuid_Func_1_ECX(void)
BoolInt CPU_IsSupported_AES(void) BoolInt CPU_IsSupported_AES(void)
{ {
return (x86cpuid_Func_1_ECX() >> 25) & 1; return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;
} }
BoolInt CPU_IsSupported_SSSE3(void) BoolInt CPU_IsSupported_SSSE3(void)
{ {
return (x86cpuid_Func_1_ECX() >> 9) & 1; return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;
} }
BoolInt CPU_IsSupported_SSE41(void) BoolInt CPU_IsSupported_SSE41(void)
{ {
return (x86cpuid_Func_1_ECX() >> 19) & 1; return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;
} }
BoolInt CPU_IsSupported_SHA(void) BoolInt CPU_IsSupported_SHA(void)
@ -441,7 +441,7 @@ BoolInt CPU_IsSupported_SHA(void)
{ {
UInt32 d[4]; UInt32 d[4];
z7_x86_cpuid(d, 7); z7_x86_cpuid(d, 7);
return (d[1] >> 29) & 1; return (BoolInt)(d[1] >> 29) & 1;
} }
} }
@ -640,8 +640,8 @@ BoolInt CPU_IsSupported_AVX(void)
const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK); const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);
// printf("\n=== XGetBV=%d\n", bm); // printf("\n=== XGetBV=%d\n", bm);
return 1 return 1
& (bm >> 1) // SSE state is supported (set by OS) for storing/restoring & (BoolInt)(bm >> 1) // SSE state is supported (set by OS) for storing/restoring
& (bm >> 2); // AVX state is supported (set by OS) for storing/restoring & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring
} }
// since Win7SP1: we can use GetEnabledXStateFeatures(); // since Win7SP1: we can use GetEnabledXStateFeatures();
} }
@ -658,10 +658,29 @@ BoolInt CPU_IsSupported_AVX2(void)
z7_x86_cpuid(d, 7); z7_x86_cpuid(d, 7);
// printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
return 1 return 1
& (d[1] >> 5); // avx2 & (BoolInt)(d[1] >> 5); // avx2
} }
} }
/*
// fix it:
BoolInt CPU_IsSupported_AVX512F_AVX512VL(void)
{
if (!CPU_IsSupported_AVX())
return False;
if (z7_x86_cpuid_GetMaxFunc() < 7)
return False;
{
UInt32 d[4];
z7_x86_cpuid(d, 7);
// printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
return 1
& (BoolInt)(d[1] >> 16) // avx512-f
& (BoolInt)(d[1] >> 31); // avx512-Vl
}
}
*/
BoolInt CPU_IsSupported_VAES_AVX2(void) BoolInt CPU_IsSupported_VAES_AVX2(void)
{ {
if (!CPU_IsSupported_AVX()) if (!CPU_IsSupported_AVX())
@ -673,9 +692,9 @@ BoolInt CPU_IsSupported_VAES_AVX2(void)
z7_x86_cpuid(d, 7); z7_x86_cpuid(d, 7);
// printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]); // printf("\ncpuid(7): ebx=%8x ecx=%8x\n", d[1], d[2]);
return 1 return 1
& (d[1] >> 5) // avx2 & (BoolInt)(d[1] >> 5) // avx2
// & (d[1] >> 31) // avx512vl // & (d[1] >> 31) // avx512vl
& (d[2] >> 9); // vaes // VEX-256/EVEX & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX
} }
} }
@ -688,7 +707,7 @@ BoolInt CPU_IsSupported_PageGB(void)
if (d[0] < 0x80000001) if (d[0] < 0x80000001)
return False; return False;
z7_x86_cpuid(d, 0x80000001); z7_x86_cpuid(d, 0x80000001);
return (d[3] >> 26) & 1; return (BoolInt)(d[3] >> 26) & 1;
} }
} }
@ -760,32 +779,65 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
#else // __APPLE__ #else // __APPLE__
#include <sys/auxv.h> #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
#define Z7_GETAUXV_AVAILABLE
#else
// #pragma message("=== is not NEW GLIBC === ")
#if defined __has_include
#if __has_include (<sys/auxv.h>)
// #pragma message("=== sys/auxv.h is avail=== ")
#define Z7_GETAUXV_AVAILABLE
#endif
#endif
#endif
#ifdef Z7_GETAUXV_AVAILABLE
// #pragma message("=== Z7_GETAUXV_AVAILABLE === ")
#include <sys/auxv.h>
#define USE_HWCAP #define USE_HWCAP
#endif
#ifdef USE_HWCAP #ifdef USE_HWCAP
#if defined(__FreeBSD__)
static unsigned long MY_getauxval(int aux)
{
unsigned long val;
if (elf_aux_info(aux, &val, sizeof(val)))
return 0;
return val;
}
#else
#define MY_getauxval getauxval
#if defined __has_include
#if __has_include (<asm/hwcap.h>)
#include <asm/hwcap.h> #include <asm/hwcap.h>
#endif
#endif
#endif
#define MY_HWCAP_CHECK_FUNC_2(name1, name2) \ #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \
BoolInt CPU_IsSupported_ ## name1() { return (getauxval(AT_HWCAP) & (HWCAP_ ## name2)) ? 1 : 0; } BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP) & (HWCAP_ ## name2)); }
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
#define MY_HWCAP_CHECK_FUNC(name) \ #define MY_HWCAP_CHECK_FUNC(name) \
MY_HWCAP_CHECK_FUNC_2(name, name) MY_HWCAP_CHECK_FUNC_2(name, name)
#if 1 || defined(__ARM_NEON)
BoolInt CPU_IsSupported_NEON(void) { return True; }
#else
MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD) MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)
#endif
// MY_HWCAP_CHECK_FUNC (ASIMD) // MY_HWCAP_CHECK_FUNC (ASIMD)
#elif defined(MY_CPU_ARM) #elif defined(MY_CPU_ARM)
#define MY_HWCAP_CHECK_FUNC(name) \ #define MY_HWCAP_CHECK_FUNC(name) \
BoolInt CPU_IsSupported_ ## name() { return (getauxval(AT_HWCAP2) & (HWCAP2_ ## name)) ? 1 : 0; } BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }
MY_HWCAP_CHECK_FUNC_2(NEON, NEON) MY_HWCAP_CHECK_FUNC_2(NEON, NEON)
#endif #endif
#else // USE_HWCAP #else // USE_HWCAP
#define MY_HWCAP_CHECK_FUNC(name) \ #define MY_HWCAP_CHECK_FUNC(name) \
BoolInt CPU_IsSupported_ ## name() { return 0; } BoolInt CPU_IsSupported_ ## name(void) { return 0; }
MY_HWCAP_CHECK_FUNC(NEON) MY_HWCAP_CHECK_FUNC(NEON)
#endif // USE_HWCAP #endif // USE_HWCAP

View file

@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code /* CpuArch.h -- CPU specific code
2023-04-02 : Igor Pavlov : Public domain */ 2024-05-13 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_CPU_ARCH_H #ifndef ZIP7_INC_CPU_ARCH_H
#define ZIP7_INC_CPU_ARCH_H #define ZIP7_INC_CPU_ARCH_H
@ -20,6 +20,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8) MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8)
*/ */
#if !defined(_M_ARM64EC)
#if defined(_M_X64) \ #if defined(_M_X64) \
|| defined(_M_AMD64) \ || defined(_M_AMD64) \
|| defined(__x86_64__) \ || defined(__x86_64__) \
@ -35,6 +36,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#endif #endif
#define MY_CPU_64BIT #define MY_CPU_64BIT
#endif #endif
#endif
#if defined(_M_IX86) \ #if defined(_M_IX86) \
@ -47,17 +49,26 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#if defined(_M_ARM64) \ #if defined(_M_ARM64) \
|| defined(_M_ARM64EC) \
|| defined(__AARCH64EL__) \ || defined(__AARCH64EL__) \
|| defined(__AARCH64EB__) \ || defined(__AARCH64EB__) \
|| defined(__aarch64__) || defined(__aarch64__)
#define MY_CPU_ARM64 #define MY_CPU_ARM64
#ifdef __ILP32__ #if defined(__ILP32__) \
|| defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
#define MY_CPU_NAME "arm64-32" #define MY_CPU_NAME "arm64-32"
#define MY_CPU_SIZEOF_POINTER 4 #define MY_CPU_SIZEOF_POINTER 4
#else #elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)
#define MY_CPU_NAME "arm64-128"
#define MY_CPU_SIZEOF_POINTER 16
#else
#if defined(_M_ARM64EC)
#define MY_CPU_NAME "arm64ec"
#else
#define MY_CPU_NAME "arm64" #define MY_CPU_NAME "arm64"
#endif
#define MY_CPU_SIZEOF_POINTER 8 #define MY_CPU_SIZEOF_POINTER 8
#endif #endif
#define MY_CPU_64BIT #define MY_CPU_64BIT
#endif #endif
@ -133,8 +144,36 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#endif #endif
#if defined(__sparc__) \
|| defined(__sparc)
#define MY_CPU_SPARC
#if defined(__LP64__) \
|| defined(_LP64) \
|| defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
#define MY_CPU_NAME "sparcv9"
#define MY_CPU_SIZEOF_POINTER 8
#define MY_CPU_64BIT
#elif defined(__sparc_v9__) \
|| defined(__sparcv9)
#define MY_CPU_64BIT
#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
#define MY_CPU_NAME "sparcv9-32"
#else
#define MY_CPU_NAME "sparcv9m"
#endif
#elif defined(__sparc_v8__) \
|| defined(__sparcv8)
#define MY_CPU_NAME "sparcv8"
#define MY_CPU_SIZEOF_POINTER 4
#else
#define MY_CPU_NAME "sparc"
#endif
#endif
#if defined(__riscv) \ #if defined(__riscv) \
|| defined(__riscv__) || defined(__riscv__)
#define MY_CPU_RISCV
#if __riscv_xlen == 32 #if __riscv_xlen == 32
#define MY_CPU_NAME "riscv32" #define MY_CPU_NAME "riscv32"
#elif __riscv_xlen == 64 #elif __riscv_xlen == 64
@ -145,6 +184,39 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#endif #endif
#if defined(__loongarch__)
#define MY_CPU_LOONGARCH
#if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64)
#define MY_CPU_64BIT
#endif
#if defined(__loongarch64)
#define MY_CPU_NAME "loongarch64"
#define MY_CPU_LOONGARCH64
#else
#define MY_CPU_NAME "loongarch"
#endif
#endif
// #undef MY_CPU_NAME
// #undef MY_CPU_SIZEOF_POINTER
// #define __e2k__
// #define __SIZEOF_POINTER__ 4
#if defined(__e2k__)
#define MY_CPU_E2K
#if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)
#define MY_CPU_NAME "e2k-32"
#define MY_CPU_SIZEOF_POINTER 4
#else
#define MY_CPU_NAME "e2k"
#if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)
#define MY_CPU_SIZEOF_POINTER 8
#endif
#endif
#define MY_CPU_64BIT
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) #if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64 #define MY_CPU_X86_OR_AMD64
#endif #endif
@ -175,6 +247,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
|| defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM_LE) \
|| defined(MY_CPU_ARM64_LE) \ || defined(MY_CPU_ARM64_LE) \
|| defined(MY_CPU_IA64_LE) \ || defined(MY_CPU_IA64_LE) \
|| defined(_LITTLE_ENDIAN) \
|| defined(__LITTLE_ENDIAN__) \ || defined(__LITTLE_ENDIAN__) \
|| defined(__ARMEL__) \ || defined(__ARMEL__) \
|| defined(__THUMBEL__) \ || defined(__THUMBEL__) \
@ -251,6 +324,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#ifndef MY_CPU_NAME #ifndef MY_CPU_NAME
// #define MY_CPU_IS_UNKNOWN
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#define MY_CPU_NAME "LE" #define MY_CPU_NAME "LE"
#elif defined(MY_CPU_BE) #elif defined(MY_CPU_BE)
@ -295,9 +369,19 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#define Z7_BSWAP64(v) _byteswap_uint64(v) #define Z7_BSWAP64(v) _byteswap_uint64(v)
#define Z7_CPU_FAST_BSWAP_SUPPORTED #define Z7_CPU_FAST_BSWAP_SUPPORTED
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ /* GCC can generate slow code that calls function for __builtin_bswap32() for:
|| (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) - GCC for RISCV, if Zbb extension is not used.
- GCC for SPARC.
The code from CLANG for SPARC also is not fastest.
So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases.
*/
#elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb)) \
&& !defined(MY_CPU_SPARC) \
&& ( \
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|| (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \
)
#define Z7_BSWAP16(v) __builtin_bswap16(v) #define Z7_BSWAP16(v) __builtin_bswap16(v)
#define Z7_BSWAP32(v) __builtin_bswap32(v) #define Z7_BSWAP32(v) __builtin_bswap32(v)
#define Z7_BSWAP64(v) __builtin_bswap64(v) #define Z7_BSWAP64(v) __builtin_bswap64(v)
@ -329,13 +413,48 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#ifdef MY_CPU_LE #ifdef MY_CPU_LE
#if defined(MY_CPU_X86_OR_AMD64) \ #if defined(MY_CPU_X86_OR_AMD64) \
|| defined(MY_CPU_ARM64) || defined(MY_CPU_ARM64) \
|| defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \
|| defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6)
#define MY_CPU_LE_UNALIGN #define MY_CPU_LE_UNALIGN
#define MY_CPU_LE_UNALIGN_64 #define MY_CPU_LE_UNALIGN_64
#elif defined(__ARM_FEATURE_UNALIGNED) #elif defined(__ARM_FEATURE_UNALIGNED)
/* gcc9 for 32-bit arm can use LDRD instruction that requires 32-bit alignment. /* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions.
So we can't use unaligned 64-bit operations. */ Description of problems:
#define MY_CPU_LE_UNALIGN problem-1 : 32-bit ARM architecture:
multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM)
require 32-bit (WORD) alignment (by 32-bit ARM architecture).
So there is "Alignment fault exception", if data is not aligned for 32-bit.
problem-2 : 32-bit kernels and arm64 kernels:
32-bit linux kernels provide fixup for these "paired" instruction "Alignment fault exception".
So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux.
But some arm64 kernels do not handle these faults in 32-bit programs.
So we have unhandled exception for such instructions.
Probably some new arm64 kernels have fixed it, and unaligned
paired-access instructions work in new kernels?
problem-3 : compiler for 32-bit arm:
Compilers use LDRD/STRD/LDM/STM for UInt64 accesses
and for another cases where two 32-bit accesses are fused
to one multi-access instruction.
So UInt64 variables must be aligned for 32-bit, and each
32-bit access must be aligned for 32-bit, if we want to
avoid "Alignment fault" exception (handled or unhandled).
problem-4 : performace:
Even if unaligned access is handled by kernel, it will be slow.
So if we allow unaligned access, we can get fast unaligned
single-access, and slow unaligned paired-access.
We don't allow unaligned access on 32-bit arm, because compiler
genarates paired-access instructions that require 32-bit alignment,
and some arm64 kernels have no handler for these instructions.
Also unaligned paired-access instructions will be slow, if kernel handles them.
*/
// it must be disabled:
// #define MY_CPU_LE_UNALIGN
#endif #endif
#endif #endif
@ -439,6 +558,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#if defined(MY_CPU_BE) #if defined(MY_CPU_BE)
#define GetBe64a(p) (*(const UInt64 *)(const void *)(p))
#define GetBe32a(p) (*(const UInt32 *)(const void *)(p)) #define GetBe32a(p) (*(const UInt32 *)(const void *)(p))
#define GetBe16a(p) (*(const UInt16 *)(const void *)(p)) #define GetBe16a(p) (*(const UInt16 *)(const void *)(p))
#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
@ -456,6 +576,7 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
#define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetUi32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
#define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); } #define SetUi16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
#define GetBe64a(p) GetBe64(p)
#define GetBe32a(p) GetBe32(p) #define GetBe32a(p) GetBe32(p)
#define GetBe16a(p) GetBe16(p) #define GetBe16a(p) GetBe16(p)
#define SetBe32a(p, v) SetBe32(p, v) #define SetBe32a(p, v) SetBe32(p, v)
@ -486,6 +607,7 @@ UInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void);
BoolInt CPU_IsSupported_AES(void); BoolInt CPU_IsSupported_AES(void);
BoolInt CPU_IsSupported_AVX(void); BoolInt CPU_IsSupported_AVX(void);
BoolInt CPU_IsSupported_AVX2(void); BoolInt CPU_IsSupported_AVX2(void);
// BoolInt CPU_IsSupported_AVX512F_AVX512VL(void);
BoolInt CPU_IsSupported_VAES_AVX2(void); BoolInt CPU_IsSupported_VAES_AVX2(void);
BoolInt CPU_IsSupported_CMOV(void); BoolInt CPU_IsSupported_CMOV(void);
BoolInt CPU_IsSupported_SSE(void); BoolInt CPU_IsSupported_SSE(void);

View file

@ -1,5 +1,5 @@
/* DllSecur.c -- DLL loading security /* DllSecur.c -- DLL loading security
2023-04-02 : Igor Pavlov : Public domain */ 2023-12-03 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -11,19 +11,7 @@
#ifndef UNDER_CE #ifndef UNDER_CE
#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__) Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
// #pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
#if defined(__clang__) || defined(__GNUC__)
typedef void (*Z7_voidFunction)(void);
#define MY_CAST_FUNC (Z7_voidFunction)
#elif defined(_MSC_VER) && _MSC_VER > 1920
#define MY_CAST_FUNC (void *)
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
#else
#define MY_CAST_FUNC
#endif
typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags); typedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);
@ -61,7 +49,7 @@ static const char * const g_Dlls =
if ((UInt16)GetVersion() != 6) { \ if ((UInt16)GetVersion() != 6) { \
const \ const \
Func_SetDefaultDllDirectories setDllDirs = \ Func_SetDefaultDllDirectories setDllDirs = \
(Func_SetDefaultDllDirectories) MY_CAST_FUNC GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \ (Func_SetDefaultDllDirectories) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), \
"SetDefaultDllDirectories"); \ "SetDefaultDllDirectories"); \
if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; } if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; }

View file

@ -1,5 +1,5 @@
/* HuffEnc.c -- functions for Huffman encoding /* HuffEnc.c -- functions for Huffman encoding
2023-03-04 : Igor Pavlov : Public domain */ 2023-09-07 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -8,7 +8,7 @@
#define kMaxLen 16 #define kMaxLen 16
#define NUM_BITS 10 #define NUM_BITS 10
#define MASK (((unsigned)1 << NUM_BITS) - 1) #define MASK ((1u << NUM_BITS) - 1)
#define NUM_COUNTERS 64 #define NUM_COUNTERS 64

View file

@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms /* LzFind.c -- Match finder for LZ algorithms
2023-03-14 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -108,9 +108,15 @@ static int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr all
return (p->bufBase != NULL); return (p->bufBase != NULL);
} }
static const Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } static const Byte *MatchFinder_GetPointerToCurrentPos(void *p)
{
return ((CMatchFinder *)p)->buffer;
}
static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return GET_AVAIL_BYTES(p); } static UInt32 MatchFinder_GetNumAvailableBytes(void *p)
{
return GET_AVAIL_BYTES((CMatchFinder *)p);
}
Z7_NO_INLINE Z7_NO_INLINE
@ -571,8 +577,9 @@ void MatchFinder_Init_4(CMatchFinder *p)
#define CYC_TO_POS_OFFSET 0 #define CYC_TO_POS_OFFSET 0
// #define CYC_TO_POS_OFFSET 1 // for debug // #define CYC_TO_POS_OFFSET 1 // for debug
void MatchFinder_Init(CMatchFinder *p) void MatchFinder_Init(void *_p)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
MatchFinder_Init_HighHash(p); MatchFinder_Init_HighHash(p);
MatchFinder_Init_LowHash(p); MatchFinder_Init_LowHash(p);
MatchFinder_Init_4(p); MatchFinder_Init_4(p);
@ -607,16 +614,16 @@ void MatchFinder_Init(CMatchFinder *p)
#endif #endif
#endif #endif
// #elif defined(MY_CPU_ARM_OR_ARM64) #elif defined(MY_CPU_ARM64) \
#elif defined(MY_CPU_ARM64) /* || (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) */
#if defined(__clang__) && (__clang_major__ >= 8) \ #if defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 8) || defined(__GNUC__) && (__GNUC__ >= 6)
#define USE_LZFIND_SATUR_SUB_128 #define USE_LZFIND_SATUR_SUB_128
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
// #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(""))) // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("")))
#else #else
// #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #define LZFIND_ATTRIB_SSE41 __attribute__((__target__("fpu=neon")))
#endif #endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
@ -625,7 +632,7 @@ void MatchFinder_Init(CMatchFinder *p)
#endif #endif
#endif #endif
#if defined(_MSC_VER) && defined(MY_CPU_ARM64) #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
#include <arm_neon.h> #include <arm_neon.h>
@ -1082,9 +1089,11 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
#define MOVE_POS \ #define MOVE_POS \
++p->cyclicBufferPos; \ p->cyclicBufferPos++; \
p->buffer++; \ p->buffer++; \
{ const UInt32 pos1 = p->pos + 1; p->pos = pos1; if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); } { const UInt32 pos1 = p->pos + 1; \
p->pos = pos1; \
if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); }
#define MOVE_POS_RET MOVE_POS return distances; #define MOVE_POS_RET MOVE_POS return distances;
@ -1103,20 +1112,26 @@ static void MatchFinder_MovePos(CMatchFinder *p)
} }
#define GET_MATCHES_HEADER2(minLen, ret_op) \ #define GET_MATCHES_HEADER2(minLen, ret_op) \
unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ UInt32 hv; const Byte *cur; UInt32 curMatch; \
lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ UInt32 lenLimit = p->lenLimit; \
if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; } \
cur = p->buffer; cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances) #define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances)
#define SKIP_HEADER(minLen) do { GET_MATCHES_HEADER2(minLen, continue) #define SKIP_HEADER(minLen) \
do { GET_MATCHES_HEADER2(minLen, continue)
#define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue #define MF_PARAMS(p) lenLimit, curMatch, p->pos, p->buffer, p->son, \
p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define SKIP_FOOTER SkipMatchesSpec(MF_PARAMS(p)); MOVE_POS } while (--num); #define SKIP_FOOTER \
SkipMatchesSpec(MF_PARAMS(p)); \
MOVE_POS \
} while (--num);
#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \ #define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \
distances = func(MF_PARAMS(p), \ distances = func(MF_PARAMS(p), distances, (UInt32)_maxLen_); \
distances, (UInt32)_maxLen_); MOVE_POS_RET MOVE_POS_RET
#define GET_MATCHES_FOOTER_BT(_maxLen_) \ #define GET_MATCHES_FOOTER_BT(_maxLen_) \
GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1) GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1)
@ -1133,8 +1148,9 @@ static void MatchFinder_MovePos(CMatchFinder *p)
for (; c != lim; c++) if (*(c + diff) != *c) break; \ for (; c != lim; c++) if (*(c + diff) != *c) break; \
maxLen = (unsigned)(c - cur); } maxLen = (unsigned)(c - cur); }
static UInt32* Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32* Bt2_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
GET_MATCHES_HEADER(2) GET_MATCHES_HEADER(2)
HASH2_CALC HASH2_CALC
curMatch = p->hash[hv]; curMatch = p->hash[hv];
@ -1158,8 +1174,9 @@ UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
mmm = pos; mmm = pos;
static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32* Bt3_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
UInt32 mmm; UInt32 mmm;
UInt32 h2, d2, pos; UInt32 h2, d2, pos;
unsigned maxLen; unsigned maxLen;
@ -1199,8 +1216,9 @@ static UInt32* Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
} }
static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32* Bt4_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
UInt32 mmm; UInt32 mmm;
UInt32 h2, h3, d2, d3, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen; unsigned maxLen;
@ -1267,10 +1285,12 @@ static UInt32* Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
} }
static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32* Bt5_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
UInt32 mmm; UInt32 mmm;
UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen;
UInt32 *hash; UInt32 *hash;
GET_MATCHES_HEADER(5) GET_MATCHES_HEADER(5)
@ -1339,8 +1359,9 @@ static UInt32* Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
} }
static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32* Hc4_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
UInt32 mmm; UInt32 mmm;
UInt32 h2, h3, d2, d3, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen; unsigned maxLen;
@ -1407,10 +1428,12 @@ static UInt32* Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
} }
static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) static UInt32 * Hc5_MatchFinder_GetMatches(void *_p, UInt32 *distances)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
UInt32 mmm; UInt32 mmm;
UInt32 h2, h3, d2, d3, maxLen, pos; UInt32 h2, h3, d2, d3, pos;
unsigned maxLen;
UInt32 *hash; UInt32 *hash;
GET_MATCHES_HEADER(5) GET_MATCHES_HEADER(5)
@ -1466,7 +1489,7 @@ static UInt32 * Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (*(cur - d2 + 3) != cur[3]) if (*(cur - d2 + 3) != cur[3])
break; break;
UPDATE_maxLen UPDATE_maxLen
distances[-2] = maxLen; distances[-2] = (UInt32)maxLen;
if (maxLen == lenLimit) if (maxLen == lenLimit)
{ {
p->son[p->cyclicBufferPos] = curMatch; p->son[p->cyclicBufferPos] = curMatch;
@ -1489,8 +1512,9 @@ UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
} }
static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Bt2_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
SKIP_HEADER(2) SKIP_HEADER(2)
{ {
HASH2_CALC HASH2_CALC
@ -1511,8 +1535,9 @@ void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_FOOTER SKIP_FOOTER
} }
static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Bt3_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
SKIP_HEADER(3) SKIP_HEADER(3)
{ {
UInt32 h2; UInt32 h2;
@ -1526,8 +1551,9 @@ static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_FOOTER SKIP_FOOTER
} }
static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Bt4_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
SKIP_HEADER(4) SKIP_HEADER(4)
{ {
UInt32 h2, h3; UInt32 h2, h3;
@ -1542,8 +1568,9 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
SKIP_FOOTER SKIP_FOOTER
} }
static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Bt5_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
SKIP_HEADER(5) SKIP_HEADER(5)
{ {
UInt32 h2, h3; UInt32 h2, h3;
@ -1589,8 +1616,9 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
}} while(num); \ }} while(num); \
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Hc4_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
HC_SKIP_HEADER(4) HC_SKIP_HEADER(4)
UInt32 h2, h3; UInt32 h2, h3;
@ -1604,8 +1632,9 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
} }
static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) static void Hc5_MatchFinder_Skip(void *_p, UInt32 num)
{ {
CMatchFinder *p = (CMatchFinder *)_p;
HC_SKIP_HEADER(5) HC_SKIP_HEADER(5)
UInt32 h2, h3; UInt32 h2, h3;
@ -1634,41 +1663,41 @@ void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable) void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinder_Init; vTable->Init = MatchFinder_Init;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; vTable->GetNumAvailableBytes = MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = MatchFinder_GetPointerToCurrentPos;
if (!p->btMode) if (!p->btMode)
{ {
if (p->numHashBytes <= 4) if (p->numHashBytes <= 4)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; vTable->GetMatches = Hc4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; vTable->Skip = Hc4_MatchFinder_Skip;
} }
else else
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; vTable->GetMatches = Hc5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; vTable->Skip = Hc5_MatchFinder_Skip;
} }
} }
else if (p->numHashBytes == 2) else if (p->numHashBytes == 2)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; vTable->GetMatches = Bt2_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; vTable->Skip = Bt2_MatchFinder_Skip;
} }
else if (p->numHashBytes == 3) else if (p->numHashBytes == 3)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; vTable->GetMatches = Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; vTable->Skip = Bt3_MatchFinder_Skip;
} }
else if (p->numHashBytes == 4) else if (p->numHashBytes == 4)
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; vTable->GetMatches = Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; vTable->Skip = Bt4_MatchFinder_Skip;
} }
else else
{ {
vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; vTable->GetMatches = Bt5_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; vTable->Skip = Bt5_MatchFinder_Skip;
} }
} }

View file

@ -1,5 +1,5 @@
/* LzFind.h -- Match finder for LZ algorithms /* LzFind.h -- Match finder for LZ algorithms
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZ_FIND_H #ifndef ZIP7_INC_LZ_FIND_H
#define ZIP7_INC_LZ_FIND_H #define ZIP7_INC_LZ_FIND_H
@ -144,7 +144,8 @@ void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable);
void MatchFinder_Init_LowHash(CMatchFinder *p); void MatchFinder_Init_LowHash(CMatchFinder *p);
void MatchFinder_Init_HighHash(CMatchFinder *p); void MatchFinder_Init_HighHash(CMatchFinder *p);
void MatchFinder_Init_4(CMatchFinder *p); void MatchFinder_Init_4(CMatchFinder *p);
void MatchFinder_Init(CMatchFinder *p); // void MatchFinder_Init(CMatchFinder *p);
void MatchFinder_Init(void *p);
UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); UInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);

View file

@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms /* LzFindMt.c -- multithreaded Match finder for LZ algorithms
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -94,7 +94,7 @@ static void MtSync_Construct(CMtSync *p)
} }
#define DEBUG_BUFFER_LOCK // define it to debug lock state // #define DEBUG_BUFFER_LOCK // define it to debug lock state
#ifdef DEBUG_BUFFER_LOCK #ifdef DEBUG_BUFFER_LOCK
#include <stdlib.h> #include <stdlib.h>
@ -877,8 +877,9 @@ SRes MatchFinderMt_InitMt(CMatchFinderMt *p)
} }
static void MatchFinderMt_Init(CMatchFinderMt *p) static void MatchFinderMt_Init(void *_p)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
CMatchFinder *mf = MF(p); CMatchFinder *mf = MF(p);
p->btBufPos = p->btBufPos =
@ -981,8 +982,9 @@ static UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)
static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) static const Byte * MatchFinderMt_GetPointerToCurrentPos(void *_p)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
return p->pointerToCurPos; return p->pointerToCurPos;
} }
@ -990,8 +992,9 @@ static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p)
#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); #define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);
static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) static UInt32 MatchFinderMt_GetNumAvailableBytes(void *_p)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
if (p->btBufPos != p->btBufPosLimit) if (p->btBufPos != p->btBufPosLimit)
return p->btNumAvailBytes; return p->btNumAvailBytes;
return MatchFinderMt_GetNextBlock_Bt(p); return MatchFinderMt_GetNextBlock_Bt(p);
@ -1243,8 +1246,9 @@ static UInt32 * MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d)
} }
static UInt32 * MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d) static UInt32 * MatchFinderMt2_GetMatches(void *_p, UInt32 *d)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
const UInt32 *bt = p->btBufPos; const UInt32 *bt = p->btBufPos;
const UInt32 len = *bt++; const UInt32 len = *bt++;
const UInt32 *btLim = bt + len; const UInt32 *btLim = bt + len;
@ -1267,8 +1271,9 @@ static UInt32 * MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *d)
static UInt32 * MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d) static UInt32 * MatchFinderMt_GetMatches(void *_p, UInt32 *d)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
const UInt32 *bt = p->btBufPos; const UInt32 *bt = p->btBufPos;
UInt32 len = *bt++; UInt32 len = *bt++;
const UInt32 avail = p->btNumAvailBytes - 1; const UInt32 avail = p->btNumAvailBytes - 1;
@ -1315,14 +1320,16 @@ static UInt32 * MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *d)
#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; #define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;
#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0); #define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0);
static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt0_Skip(void *_p, UInt32 num)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
SKIP_HEADER2_MT { p->btNumAvailBytes--; SKIP_HEADER2_MT { p->btNumAvailBytes--;
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt2_Skip(void *_p, UInt32 num)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
SKIP_HEADER_MT(2) SKIP_HEADER_MT(2)
UInt32 h2; UInt32 h2;
MT_HASH2_CALC MT_HASH2_CALC
@ -1330,8 +1337,9 @@ static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num)
SKIP_FOOTER_MT SKIP_FOOTER_MT
} }
static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) static void MatchFinderMt3_Skip(void *_p, UInt32 num)
{ {
CMatchFinderMt *p = (CMatchFinderMt *)_p;
SKIP_HEADER_MT(3) SKIP_HEADER_MT(3)
UInt32 h2, h3; UInt32 h2, h3;
MT_HASH3_CALC MT_HASH3_CALC
@ -1361,39 +1369,39 @@ static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable) void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable)
{ {
vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; vTable->Init = MatchFinderMt_Init;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; vTable->GetNumAvailableBytes = MatchFinderMt_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; vTable->GetPointerToCurrentPos = MatchFinderMt_GetPointerToCurrentPos;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; vTable->GetMatches = MatchFinderMt_GetMatches;
switch (MF(p)->numHashBytes) switch (MF(p)->numHashBytes)
{ {
case 2: case 2:
p->GetHeadsFunc = GetHeads2; p->GetHeadsFunc = GetHeads2;
p->MixMatchesFunc = (Mf_Mix_Matches)NULL; p->MixMatchesFunc = NULL;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; vTable->Skip = MatchFinderMt0_Skip;
vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; vTable->GetMatches = MatchFinderMt2_GetMatches;
break; break;
case 3: case 3:
p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3; p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3;
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; p->MixMatchesFunc = MixMatches2;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; vTable->Skip = MatchFinderMt2_Skip;
break; break;
case 4: case 4:
p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4; p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4;
// it's fast inline version of GetMatches() // it's fast inline version of GetMatches()
// vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches_Bt4; // vTable->GetMatches = MatchFinderMt_GetMatches_Bt4;
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; p->MixMatchesFunc = MixMatches3;
vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; vTable->Skip = MatchFinderMt3_Skip;
break; break;
default: default:
p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5; p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5;
p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; p->MixMatchesFunc = MixMatches4;
vTable->Skip = vTable->Skip =
(Mf_Skip_Func)MatchFinderMt3_Skip; MatchFinderMt3_Skip;
// (Mf_Skip_Func)MatchFinderMt4_Skip; // MatchFinderMt4_Skip;
break; break;
} }
} }

View file

@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms /* LzFindMt.h -- multithreaded Match finder for LZ algorithms
2023-03-05 : Igor Pavlov : Public domain */ 2024-01-22 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_LZ_FIND_MT_H #ifndef ZIP7_INC_LZ_FIND_MT_H
#define ZIP7_INC_LZ_FIND_MT_H #define ZIP7_INC_LZ_FIND_MT_H
@ -31,7 +31,10 @@ typedef struct
// UInt32 numBlocks_Sent; // UInt32 numBlocks_Sent;
} CMtSync; } CMtSync;
typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances);
struct CMatchFinderMt_;
typedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances);
/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ /* kMtCacheLineDummy must be >= size_of_CPU_cache_line */
#define kMtCacheLineDummy 128 #define kMtCacheLineDummy 128
@ -39,7 +42,7 @@ typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distance
typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,
UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);
typedef struct typedef struct CMatchFinderMt_
{ {
/* LZ */ /* LZ */
const Byte *pointerToCurPos; const Byte *pointerToCurPos;

View file

@ -1,5 +1,5 @@
/* Lzma2Dec.c -- LZMA2 Decoder /* Lzma2Dec.c -- LZMA2 Decoder
2023-03-03 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
/* #define SHOW_DEBUG_INFO */ /* #define SHOW_DEBUG_INFO */
@ -157,8 +157,10 @@ static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
p->decoder.prop.lp = (Byte)lp; p->decoder.prop.lp = (Byte)lp;
return LZMA2_STATE_DATA; return LZMA2_STATE_DATA;
} }
default:
return LZMA2_STATE_ERROR;
} }
return LZMA2_STATE_ERROR;
} }
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)

View file

@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder /* LzmaEnc.c -- LZMA Encoder
2023-04-13: Igor Pavlov : Public domain */ 2024-01-24: Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -195,11 +195,11 @@ unsigned GetPosSlot1(UInt32 pos);
unsigned GetPosSlot1(UInt32 pos) unsigned GetPosSlot1(UInt32 pos)
{ {
unsigned res; unsigned res;
BSR2_RET(pos, res); BSR2_RET(pos, res)
return res; return res;
} }
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } #define GetPosSlot2(pos, res) { BSR2_RET(pos, res) }
#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res) }
#else // ! LZMA_LOG_BSR #else // ! LZMA_LOG_BSR
@ -512,7 +512,7 @@ struct CLzmaEnc
COPY_ARR(d, s, posEncoders) \ COPY_ARR(d, s, posEncoders) \
(d)->lenProbs = (s)->lenProbs; \ (d)->lenProbs = (s)->lenProbs; \
(d)->repLenProbs = (s)->repLenProbs; \ (d)->repLenProbs = (s)->repLenProbs; \
memcpy((d)->litProbs, (s)->litProbs, ((UInt32)0x300 << (p)->lclp) * sizeof(CLzmaProb)); memcpy((d)->litProbs, (s)->litProbs, ((size_t)0x300 * sizeof(CLzmaProb)) << (p)->lclp);
void LzmaEnc_SaveState(CLzmaEncHandle p) void LzmaEnc_SaveState(CLzmaEncHandle p)
{ {
@ -1040,14 +1040,14 @@ Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(
UInt32 price = b; UInt32 price = b;
do do
{ {
unsigned bit = sym & 1; const unsigned bit = sym & 1;
sym >>= 1; sym >>= 1;
price += GET_PRICEa(probs[sym], bit); price += GET_PRICEa(probs[sym], bit);
} }
while (sym >= 2); while (sym >= 2);
{ {
unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))]; const unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob); prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob);
prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob); prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
} }
@ -1056,7 +1056,7 @@ Z7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(
{ {
unsigned posState; unsigned posState;
size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]); const size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
for (posState = 1; posState < numPosStates; posState++) for (posState = 1; posState < numPosStates; posState++)
memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num); memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
} }
@ -2696,12 +2696,12 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc,
#endif #endif
{ {
unsigned lclp = p->lc + p->lp; const unsigned lclp = p->lc + p->lp;
if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);
p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);
if (!p->litProbs || !p->saveState.litProbs) if (!p->litProbs || !p->saveState.litProbs)
{ {
LzmaEnc_FreeLits(p, alloc); LzmaEnc_FreeLits(p, alloc);
@ -2802,8 +2802,8 @@ static void LzmaEnc_Init(CLzmaEnc *p)
} }
{ {
UInt32 num = (UInt32)0x300 << (p->lp + p->lc); const size_t num = (size_t)0x300 << (p->lp + p->lc);
UInt32 k; size_t k;
CLzmaProb *probs = p->litProbs; CLzmaProb *probs = p->litProbs;
for (k = 0; k < num; k++) for (k = 0; k < num; k++)
probs[k] = kProbInitValue; probs[k] = kProbInitValue;

View file

@ -1,5 +1,5 @@
/* MtCoder.c -- Multi-thread Coder /* MtCoder.c -- Multi-thread Coder
2023-04-13 : Igor Pavlov : Public domain */ 2023-09-07 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -430,7 +430,7 @@ SRes MtCoder_Code(CMtCoder *p)
SRes res = SZ_OK; SRes res = SZ_OK;
if (numThreads > MTCODER_THREADS_MAX) if (numThreads > MTCODER_THREADS_MAX)
numThreads = MTCODER_THREADS_MAX; numThreads = MTCODER_THREADS_MAX;
numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads); numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);
if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++; if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;
@ -438,7 +438,7 @@ SRes MtCoder_Code(CMtCoder *p)
if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++; if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;
if (numBlocksMax > MTCODER_BLOCKS_MAX) if (numBlocksMax > MTCODER_BLOCKS_MAX)
numBlocksMax = MTCODER_BLOCKS_MAX; numBlocksMax = MTCODER_BLOCKS_MAX;
if (p->blockSize != p->allocatedBufsSize) if (p->blockSize != p->allocatedBufsSize)
{ {
@ -469,7 +469,7 @@ SRes MtCoder_Code(CMtCoder *p)
{ {
RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent)) RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent))
RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, numBlocksMax, numBlocksMax)) RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax))
} }
for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++) for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++)

View file

@ -1,5 +1,5 @@
/* MtDec.c -- Multi-thread Decoder /* MtDec.c -- Multi-thread Decoder
2023-04-02 : Igor Pavlov : Public domain */ 2024-02-20 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -809,6 +809,16 @@ static WRes MtDec_ThreadFunc2(CMtDecThread *t)
#endif #endif
typedef
#ifdef _WIN32
UINT_PTR
#elif 1
uintptr_t
#else
ptrdiff_t
#endif
MY_uintptr_t;
static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp) static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
{ {
WRes res; WRes res;
@ -821,7 +831,7 @@ static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
res = MtDec_ThreadFunc2(t); res = MtDec_ThreadFunc2(t);
p = t->mtDec; p = t->mtDec;
if (res == 0) if (res == 0)
return (THREAD_FUNC_RET_TYPE)(UINT_PTR)p->exitThreadWRes; return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes;
{ {
// it's unexpected situation for some threading function error // it's unexpected situation for some threading function error
if (p->exitThreadWRes == 0) if (p->exitThreadWRes == 0)
@ -832,7 +842,7 @@ static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
Event_Set(&p->threads[0].canWrite); Event_Set(&p->threads[0].canWrite);
MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));
} }
return (THREAD_FUNC_RET_TYPE)(UINT_PTR)res; return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res;
} }
static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp) static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp)
@ -1072,7 +1082,7 @@ SRes MtDec_Code(CMtDec *p)
if (wres == 0) { wres = Event_Set(&nextThread->canWrite); if (wres == 0) { wres = Event_Set(&nextThread->canWrite);
if (wres == 0) { wres = Event_Set(&nextThread->canRead); if (wres == 0) { wres = Event_Set(&nextThread->canRead);
if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread); if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread);
wres = (WRes)(UINT_PTR)res; wres = (WRes)(MY_uintptr_t)res;
if (wres != 0) if (wres != 0)
{ {
p->needContinue = False; p->needContinue = False;

View file

@ -1,5 +1,5 @@
/* Ppmd7.c -- PPMdH codec /* Ppmd7.c -- PPMdH codec
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -302,8 +302,17 @@ static void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx)
#define MEM_12_CPY(dest, src, num) \ #define MEM_12_CPY(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)(dest); \
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } const UInt32 *z = (const UInt32 *)(src); \
unsigned n = (num); \
do { \
d[0] = z[0]; \
d[1] = z[1]; \
d[2] = z[2]; \
z += 3; \
d += 3; \
} while (--n); \
}
/* /*
@ -711,8 +720,8 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
if ((ns1 & 1) == 0) if ((ns1 & 1) == 0)
{ {
/* Expand for one UNIT */ /* Expand for one UNIT */
unsigned oldNU = ns1 >> 1; const unsigned oldNU = ns1 >> 1;
unsigned i = U2I(oldNU); const unsigned i = U2I(oldNU);
if (i != U2I((size_t)oldNU + 1)) if (i != U2I((size_t)oldNU + 1))
{ {
void *ptr = Ppmd7_AllocUnits(p, i + 1); void *ptr = Ppmd7_AllocUnits(p, i + 1);
@ -731,7 +740,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
sum = c->Union2.SummFreq; sum = c->Union2.SummFreq;
/* max increase of Escape_Freq is 3 here. /* max increase of Escape_Freq is 3 here.
total increase of Union2.SummFreq for all symbols is less than 256 here */ total increase of Union2.SummFreq for all symbols is less than 256 here */
sum += (UInt32)(2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)); sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)));
/* original PPMdH uses 16-bit variable for (sum) here. /* original PPMdH uses 16-bit variable for (sum) here.
But (sum < 0x9000). So we don't truncate (sum) to 16-bit */ But (sum < 0x9000). So we don't truncate (sum) to 16-bit */
// sum = (UInt16)sum; // sum = (UInt16)sum;
@ -761,7 +770,7 @@ void Ppmd7_UpdateModel(CPpmd7 *p)
// (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context
s->Freq = (Byte)freq; s->Freq = (Byte)freq;
// max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here
sum = freq + p->InitEsc + (ns > 3); sum = (UInt32)(freq + p->InitEsc + (ns > 3));
} }
} }
@ -933,10 +942,10 @@ CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)
p->HiBitsFlag; p->HiBitsFlag;
{ {
// if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
unsigned summ = (UInt16)see->Summ; // & 0xFFFF const unsigned summ = (UInt16)see->Summ; // & 0xFFFF
unsigned r = (summ >> see->Shift); const unsigned r = (summ >> see->Shift);
see->Summ = (UInt16)(summ - r); see->Summ = (UInt16)(summ - r);
*escFreq = r + (r == 0); *escFreq = (UInt32)(r + (r == 0));
} }
} }
else else
@ -981,9 +990,9 @@ void Ppmd7_Update1_0(CPpmd7 *p)
CPpmd_State *s = p->FoundState; CPpmd_State *s = p->FoundState;
CPpmd7_Context *mc = p->MinContext; CPpmd7_Context *mc = p->MinContext;
unsigned freq = s->Freq; unsigned freq = s->Freq;
unsigned summFreq = mc->Union2.SummFreq; const unsigned summFreq = mc->Union2.SummFreq;
p->PrevSuccess = (2 * freq > summFreq); p->PrevSuccess = (2 * freq > summFreq);
p->RunLength += (int)p->PrevSuccess; p->RunLength += (Int32)p->PrevSuccess;
mc->Union2.SummFreq = (UInt16)(summFreq + 4); mc->Union2.SummFreq = (UInt16)(summFreq + 4);
freq += 4; freq += 4;
s->Freq = (Byte)freq; s->Freq = (Byte)freq;

View file

@ -1,5 +1,5 @@
/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder /* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.H (2001): Dmitry Shkarin : Public domain */ PPMd var.H (2001): Dmitry Shkarin : Public domain */
@ -58,7 +58,7 @@ static void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
void Ppmd7_UpdateModel(CPpmd7 *p); void Ppmd7_UpdateModel(CPpmd7 *p);
#define MASK(sym) ((unsigned char *)charMask)[sym] #define MASK(sym) ((Byte *)charMask)[sym]
// Z7_FORCE_INLINE // Z7_FORCE_INLINE
// static // static
int Ppmd7z_DecodeSymbol(CPpmd7 *p) int Ppmd7z_DecodeSymbol(CPpmd7 *p)
@ -120,8 +120,8 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
MASK(s->Symbol) = 0; MASK(s->Symbol) = 0;
do do
{ {
unsigned sym0 = s2[0].Symbol; const unsigned sym0 = s2[0].Symbol;
unsigned sym1 = s2[1].Symbol; const unsigned sym1 = s2[1].Symbol;
s2 += 2; s2 += 2;
MASK(sym0) = 0; MASK(sym0) = 0;
MASK(sym1) = 0; MASK(sym1) = 0;
@ -209,17 +209,17 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
unsigned num2 = num / 2; unsigned num2 = num / 2;
num &= 1; num &= 1;
hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
s += num; s += num;
p->MinContext = mc; p->MinContext = mc;
do do
{ {
unsigned sym0 = s[0].Symbol; const unsigned sym0 = s[0].Symbol;
unsigned sym1 = s[1].Symbol; const unsigned sym1 = s[1].Symbol;
s += 2; s += 2;
hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
} }
while (--num2); while (--num2);
} }
@ -238,13 +238,13 @@ int Ppmd7z_DecodeSymbol(CPpmd7 *p)
s = Ppmd7_GetStats(p, p->MinContext); s = Ppmd7_GetStats(p, p->MinContext);
hiCnt = count; hiCnt = count;
// count -= s->Freq & (unsigned)(MASK(s->Symbol)); // count -= s->Freq & (UInt32)(MASK(s->Symbol));
// if ((Int32)count >= 0) // if ((Int32)count >= 0)
{ {
for (;;) for (;;)
{ {
count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
// count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
} }
} }
s--; s--;

View file

@ -1,5 +1,5 @@
/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder /* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.H (2001): Dmitry Shkarin : Public domain */ PPMd var.H (2001): Dmitry Shkarin : Public domain */
@ -82,7 +82,7 @@ void Ppmd7z_Flush_RangeEnc(CPpmd7 *p)
void Ppmd7_UpdateModel(CPpmd7 *p); void Ppmd7_UpdateModel(CPpmd7 *p);
#define MASK(sym) ((unsigned char *)charMask)[sym] #define MASK(sym) ((Byte *)charMask)[sym]
Z7_FORCE_INLINE Z7_FORCE_INLINE
static static
@ -139,8 +139,8 @@ void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol)
MASK(s->Symbol) = 0; MASK(s->Symbol) = 0;
do do
{ {
unsigned sym0 = s2[0].Symbol; const unsigned sym0 = s2[0].Symbol;
unsigned sym1 = s2[1].Symbol; const unsigned sym1 = s2[1].Symbol;
s2 += 2; s2 += 2;
MASK(sym0) = 0; MASK(sym0) = 0;
MASK(sym1) = 0; MASK(sym1) = 0;
@ -265,16 +265,15 @@ void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol)
if (num2 != 0) if (num2 != 0)
{ {
s += i; s += i;
for (;;) do
{ {
unsigned sym0 = s[0].Symbol; const unsigned sym0 = s[0].Symbol;
unsigned sym1 = s[1].Symbol; const unsigned sym1 = s[1].Symbol;
s += 2; s += 2;
sum += (s[-2].Freq & (unsigned)(MASK(sym0))); sum += (s[-2].Freq & (unsigned)(MASK(sym0)));
sum += (s[-1].Freq & (unsigned)(MASK(sym1))); sum += (s[-1].Freq & (unsigned)(MASK(sym1)));
if (--num2 == 0)
break;
} }
while (--num2);
} }

View file

@ -1,5 +1,5 @@
/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder /* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.H (2001): Dmitry Shkarin : Public domain PPMd var.H (2001): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@ -58,7 +58,7 @@ typedef CPpmd7_Context * CTX_PTR;
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
void Ppmd7_UpdateModel(CPpmd7 *p); void Ppmd7_UpdateModel(CPpmd7 *p);
#define MASK(sym) ((unsigned char *)charMask)[sym] #define MASK(sym) ((Byte *)charMask)[sym]
int Ppmd7a_DecodeSymbol(CPpmd7 *p) int Ppmd7a_DecodeSymbol(CPpmd7 *p)
@ -120,8 +120,8 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
MASK(s->Symbol) = 0; MASK(s->Symbol) = 0;
do do
{ {
unsigned sym0 = s2[0].Symbol; const unsigned sym0 = s2[0].Symbol;
unsigned sym1 = s2[1].Symbol; const unsigned sym1 = s2[1].Symbol;
s2 += 2; s2 += 2;
MASK(sym0) = 0; MASK(sym0) = 0;
MASK(sym1) = 0; MASK(sym1) = 0;
@ -209,17 +209,17 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
unsigned num2 = num / 2; unsigned num2 = num / 2;
num &= 1; num &= 1;
hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
s += num; s += num;
p->MinContext = mc; p->MinContext = mc;
do do
{ {
unsigned sym0 = s[0].Symbol; const unsigned sym0 = s[0].Symbol;
unsigned sym1 = s[1].Symbol; const unsigned sym1 = s[1].Symbol;
s += 2; s += 2;
hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
} }
while (--num2); while (--num2);
} }
@ -238,13 +238,13 @@ int Ppmd7a_DecodeSymbol(CPpmd7 *p)
s = Ppmd7_GetStats(p, p->MinContext); s = Ppmd7_GetStats(p, p->MinContext);
hiCnt = count; hiCnt = count;
// count -= s->Freq & (unsigned)(MASK(s->Symbol)); // count -= s->Freq & (UInt32)(MASK(s->Symbol));
// if ((Int32)count >= 0) // if ((Int32)count >= 0)
{ {
for (;;) for (;;)
{ {
count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
// count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
} }
} }
s--; s--;

View file

@ -1,5 +1,5 @@
/* Ppmd8.c -- PPMdI codec /* Ppmd8.c -- PPMdI codec
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */ This code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -302,8 +302,17 @@ static void *Ppmd8_AllocUnits(CPpmd8 *p, unsigned indx)
#define MEM_12_CPY(dest, src, num) \ #define MEM_12_CPY(dest, src, num) \
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \ { UInt32 *d = (UInt32 *)(dest); \
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); } const UInt32 *z = (const UInt32 *)(src); \
unsigned n = (num); \
do { \
d[0] = z[0]; \
d[1] = z[1]; \
d[2] = z[2]; \
z += 3; \
d += 3; \
} while (--n); \
}
@ -1215,8 +1224,8 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
if ((ns1 & 1) != 0) if ((ns1 & 1) != 0)
{ {
/* Expand for one UNIT */ /* Expand for one UNIT */
unsigned oldNU = (ns1 + 1) >> 1; const unsigned oldNU = (ns1 + 1) >> 1;
unsigned i = U2I(oldNU); const unsigned i = U2I(oldNU);
if (i != U2I((size_t)oldNU + 1)) if (i != U2I((size_t)oldNU + 1))
{ {
void *ptr = Ppmd8_AllocUnits(p, i + 1); void *ptr = Ppmd8_AllocUnits(p, i + 1);
@ -1235,7 +1244,7 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
sum = c->Union2.SummFreq; sum = c->Union2.SummFreq;
/* max increase of Escape_Freq is 1 here. /* max increase of Escape_Freq is 1 here.
an average increase is 1/3 per symbol */ an average increase is 1/3 per symbol */
sum += (3 * ns1 + 1 < ns); sum += (UInt32)(unsigned)(3 * ns1 + 1 < ns);
/* original PPMdH uses 16-bit variable for (sum) here. /* original PPMdH uses 16-bit variable for (sum) here.
But (sum < ???). Do we need to truncate (sum) to 16-bit */ But (sum < ???). Do we need to truncate (sum) to 16-bit */
// sum = (UInt16)sum; // sum = (UInt16)sum;
@ -1265,7 +1274,7 @@ void Ppmd8_UpdateModel(CPpmd8 *p)
s->Freq = (Byte)freq; s->Freq = (Byte)freq;
sum = freq + p->InitEsc + (ns > 2); // Ppmd8 (> 2) sum = (UInt32)(freq + p->InitEsc + (ns > 2)); // Ppmd8 (> 2)
} }
} }
@ -1437,10 +1446,10 @@ CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)
{ {
// if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ
unsigned summ = (UInt16)see->Summ; // & 0xFFFF const unsigned summ = (UInt16)see->Summ; // & 0xFFFF
unsigned r = (summ >> see->Shift); const unsigned r = (summ >> see->Shift);
see->Summ = (UInt16)(summ - r); see->Summ = (UInt16)(summ - r);
*escFreq = r + (r == 0); *escFreq = (UInt32)(r + (r == 0));
} }
} }
else else
@ -1485,9 +1494,9 @@ void Ppmd8_Update1_0(CPpmd8 *p)
CPpmd_State *s = p->FoundState; CPpmd_State *s = p->FoundState;
CPpmd8_Context *mc = p->MinContext; CPpmd8_Context *mc = p->MinContext;
unsigned freq = s->Freq; unsigned freq = s->Freq;
unsigned summFreq = mc->Union2.SummFreq; const unsigned summFreq = mc->Union2.SummFreq;
p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=) p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=)
p->RunLength += (int)p->PrevSuccess; p->RunLength += (Int32)p->PrevSuccess;
mc->Union2.SummFreq = (UInt16)(summFreq + 4); mc->Union2.SummFreq = (UInt16)(summFreq + 4);
freq += 4; freq += 4;
s->Freq = (Byte)freq; s->Freq = (Byte)freq;

View file

@ -1,5 +1,5 @@
/* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder /* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@ -58,7 +58,7 @@ static void Ppmd8_RD_Decode(CPpmd8 *p, UInt32 start, UInt32 size)
#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p) #define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)
void Ppmd8_UpdateModel(CPpmd8 *p); void Ppmd8_UpdateModel(CPpmd8 *p);
#define MASK(sym) ((unsigned char *)charMask)[sym] #define MASK(sym) ((Byte *)charMask)[sym]
int Ppmd8_DecodeSymbol(CPpmd8 *p) int Ppmd8_DecodeSymbol(CPpmd8 *p)
@ -120,8 +120,8 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
MASK(s->Symbol) = 0; MASK(s->Symbol) = 0;
do do
{ {
unsigned sym0 = s2[0].Symbol; const unsigned sym0 = s2[0].Symbol;
unsigned sym1 = s2[1].Symbol; const unsigned sym1 = s2[1].Symbol;
s2 += 2; s2 += 2;
MASK(sym0) = 0; MASK(sym0) = 0;
MASK(sym1) = 0; MASK(sym1) = 0;
@ -209,17 +209,17 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
unsigned num2 = num / 2; unsigned num2 = num / 2;
num &= 1; num &= 1;
hiCnt = (s->Freq & (unsigned)(MASK(s->Symbol))) & (0 - (UInt32)num); hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);
s += num; s += num;
p->MinContext = mc; p->MinContext = mc;
do do
{ {
unsigned sym0 = s[0].Symbol; const unsigned sym0 = s[0].Symbol;
unsigned sym1 = s[1].Symbol; const unsigned sym1 = s[1].Symbol;
s += 2; s += 2;
hiCnt += (s[-2].Freq & (unsigned)(MASK(sym0))); hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));
hiCnt += (s[-1].Freq & (unsigned)(MASK(sym1))); hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));
} }
while (--num2); while (--num2);
} }
@ -243,8 +243,8 @@ int Ppmd8_DecodeSymbol(CPpmd8 *p)
{ {
for (;;) for (;;)
{ {
count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
// count -= s->Freq & (unsigned)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break; // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;
} }
} }
s--; s--;

View file

@ -1,5 +1,5 @@
/* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder /* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder
2023-04-02 : Igor Pavlov : Public domain 2023-09-07 : Igor Pavlov : Public domain
This code is based on: This code is based on:
PPMd var.I (2002): Dmitry Shkarin : Public domain PPMd var.I (2002): Dmitry Shkarin : Public domain
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */ Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
@ -82,7 +82,7 @@ static void Ppmd8_RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 t
void Ppmd8_UpdateModel(CPpmd8 *p); void Ppmd8_UpdateModel(CPpmd8 *p);
#define MASK(sym) ((unsigned char *)charMask)[sym] #define MASK(sym) ((Byte *)charMask)[sym]
// Z7_FORCE_INLINE // Z7_FORCE_INLINE
// static // static
@ -139,8 +139,8 @@ void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
MASK(s->Symbol) = 0; MASK(s->Symbol) = 0;
do do
{ {
unsigned sym0 = s2[0].Symbol; const unsigned sym0 = s2[0].Symbol;
unsigned sym1 = s2[1].Symbol; const unsigned sym1 = s2[1].Symbol;
s2 += 2; s2 += 2;
MASK(sym0) = 0; MASK(sym0) = 0;
MASK(sym1) = 0; MASK(sym1) = 0;
@ -265,16 +265,15 @@ void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)
if (num2 != 0) if (num2 != 0)
{ {
s += i; s += i;
for (;;) do
{ {
unsigned sym0 = s[0].Symbol; const unsigned sym0 = s[0].Symbol;
unsigned sym1 = s[1].Symbol; const unsigned sym1 = s[1].Symbol;
s += 2; s += 2;
sum += (s[-2].Freq & (unsigned)(MASK(sym0))); sum += (s[-2].Freq & (unsigned)(MASK(sym0)));
sum += (s[-1].Freq & (unsigned)(MASK(sym1))); sum += (s[-1].Freq & (unsigned)(MASK(sym1)));
if (--num2 == 0)
break;
} }
while (--num2);
} }
PPMD8_CORRECT_SUM_RANGE(p, sum) PPMD8_CORRECT_SUM_RANGE(p, sum)

View file

@ -1,10 +1,127 @@
/* Precomp.h -- StdAfx /* Precomp.h -- precompilation file
2023-04-02 : Igor Pavlov : Public domain */ 2024-01-25 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H #ifndef ZIP7_INC_PRECOMP_H
#define ZIP7_INC_PRECOMP_H #define ZIP7_INC_PRECOMP_H
/*
this file must be included before another *.h files and before <windows.h>.
this file is included from the following files:
C\*.c
C\Util\*\Precomp.h <- C\Util\*\*.c
CPP\Common\Common.h <- *\StdAfx.h <- *\*.cpp
this file can set the following macros:
Z7_LARGE_PAGES 1
Z7_LONG_PATH 1
Z7_WIN32_WINNT_MIN 0x0500 (or higher) : we require at least win2000+ for 7-Zip
_WIN32_WINNT 0x0500 (or higher)
WINVER _WIN32_WINNT
UNICODE 1
_UNICODE 1
*/
#include "Compiler.h" #include "Compiler.h"
/* #include "7zTypes.h" */
#ifdef _MSC_VER
// #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty
#if _MSC_VER >= 1912
// #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
#endif
#endif
/*
// for debug:
#define UNICODE 1
#define _UNICODE 1
#define _WIN32_WINNT 0x0500 // win2000
#ifndef WINVER
#define WINVER _WIN32_WINNT
#endif
*/
#ifdef _WIN32
/*
this "Precomp.h" file must be included before <windows.h>,
if we want to define _WIN32_WINNT before <windows.h>.
*/
#ifndef Z7_LARGE_PAGES
#ifndef Z7_NO_LARGE_PAGES
#define Z7_LARGE_PAGES 1
#endif
#endif
#ifndef Z7_LONG_PATH
#ifndef Z7_NO_LONG_PATH
#define Z7_LONG_PATH 1
#endif
#endif
#ifndef Z7_DEVICE_FILE
#ifndef Z7_NO_DEVICE_FILE
// #define Z7_DEVICE_FILE 1
#endif
#endif
// we don't change macros if included after <windows.h>
#ifndef _WINDOWS_
#ifndef Z7_WIN32_WINNT_MIN
#if defined(_M_ARM64) || defined(__aarch64__)
// #define Z7_WIN32_WINNT_MIN 0x0a00 // win10
#define Z7_WIN32_WINNT_MIN 0x0600 // vista
#elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT)
// #define Z7_WIN32_WINNT_MIN 0x0602 // win8
#define Z7_WIN32_WINNT_MIN 0x0600 // vista
#elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64)
#define Z7_WIN32_WINNT_MIN 0x0503 // win2003
// #elif defined(_M_IX86) || defined(__i386__)
// #define Z7_WIN32_WINNT_MIN 0x0500 // win2000
#else // x86 and another(old) systems
#define Z7_WIN32_WINNT_MIN 0x0500 // win2000
// #define Z7_WIN32_WINNT_MIN 0x0502 // win2003 // for debug
#endif
#endif // Z7_WIN32_WINNT_MIN
#ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT
#ifdef _WIN32_WINNT
// #error Stop_Compiling_Bad_WIN32_WINNT
#else
#ifndef Z7_NO_DEFINE_WIN32_WINNT
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define _WIN32_WINNT Z7_WIN32_WINNT_MIN
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // _WIN32_WINNT
#ifndef WINVER
#define WINVER _WIN32_WINNT
#endif
#endif // Z7_DO_NOT_DEFINE_WIN32_WINNT
#ifndef _MBCS
#ifndef Z7_NO_UNICODE
// UNICODE and _UNICODE are used by <windows.h> and by 7-zip code.
#ifndef UNICODE
#define UNICODE 1
#endif
#ifndef _UNICODE
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define _UNICODE 1
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // Z7_NO_UNICODE
#endif // _MBCS
#endif // _WINDOWS_
// #include "7zWindows.h"
#endif // _WIN32
#endif #endif

View file

@ -1,5 +1,5 @@
/* Sha1.c -- SHA-1 Hash /* Sha1.c -- SHA-1 Hash
2023-04-02 : Igor Pavlov : Public domain 2024-03-01 : Igor Pavlov : Public domain
This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */ This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ library. */
#include "Precomp.h" #include "Precomp.h"
@ -15,35 +15,35 @@ This code is based on public domain code of Steve Reid from Wei Dai's Crypto++ l
#endif #endif
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#ifdef _MSC_VER #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
#if _MSC_VER >= 1200 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \
|| defined(_MSC_VER) && (_MSC_VER >= 1200)
#define Z7_COMPILER_SHA1_SUPPORTED #define Z7_COMPILER_SHA1_SUPPORTED
#endif
#elif defined(__clang__)
#if (__clang_major__ >= 8) // fix that check
#define Z7_COMPILER_SHA1_SUPPORTED
#endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 8) // fix that check
#define Z7_COMPILER_SHA1_SUPPORTED
#endif
#elif defined(__INTEL_COMPILER)
#if (__INTEL_COMPILER >= 1800) // fix that check
#define Z7_COMPILER_SHA1_SUPPORTED
#endif
#endif #endif
#elif defined(MY_CPU_ARM_OR_ARM64) #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) \
#ifdef _MSC_VER && (!defined(Z7_MSC_VER_ORIGINAL) || (_MSC_VER >= 1929) && (_MSC_FULL_VER >= 192930037))
#if _MSC_VER >= 1910 && _MSC_VER >= 1929 && _MSC_FULL_VER >= 192930037 #if defined(__ARM_FEATURE_SHA2) \
|| defined(__ARM_FEATURE_CRYPTO)
#define Z7_COMPILER_SHA1_SUPPORTED
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define Z7_COMPILER_SHA1_SUPPORTED #define Z7_COMPILER_SHA1_SUPPORTED
#endif #endif
#elif defined(__clang__)
#if (__clang_major__ >= 8) // fix that check
#define Z7_COMPILER_SHA1_SUPPORTED
#endif #endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define Z7_COMPILER_SHA1_SUPPORTED
#endif #endif
#endif #endif
#endif #endif
@ -436,7 +436,7 @@ void Sha1Prepare(void)
#endif #endif
{ {
// printf("\n========== HW SHA1 ======== \n"); // printf("\n========== HW SHA1 ======== \n");
#if defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER) #if 0 && defined(MY_CPU_ARM_OR_ARM64) && defined(_MSC_VER)
/* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037). /* there was bug in MSVC compiler for ARM64 -O2 before version VS2019 16.10 (19.29.30037).
It generated incorrect SHA-1 code. It generated incorrect SHA-1 code.
21.03 : we test sha1-hardware code at runtime initialization */ 21.03 : we test sha1-hardware code at runtime initialization */

View file

@ -1,5 +1,5 @@
/* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions /* Sha1Opt.c -- SHA-1 optimized code for SHA-1 hardware instructions
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "Compiler.h" #include "Compiler.h"
@ -11,6 +11,8 @@
#endif #endif
#endif #endif
// #define Z7_USE_HW_SHA_STUB // for debug
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
#define USE_HW_SHA #define USE_HW_SHA
@ -32,9 +34,14 @@
#endif #endif
#if (_MSC_VER >= USE_VER_MIN) #if (_MSC_VER >= USE_VER_MIN)
#define USE_HW_SHA #define USE_HW_SHA
#else
#define Z7_USE_HW_SHA_STUB
#endif #endif
#endif #endif
// #endif // MY_CPU_X86_OR_AMD64 // #endif // MY_CPU_X86_OR_AMD64
#ifndef USE_HW_SHA
// #define Z7_USE_HW_SHA_STUB // for debug
#endif
#ifdef USE_HW_SHA #ifdef USE_HW_SHA
@ -202,46 +209,124 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
#endif // USE_HW_SHA #endif // USE_HW_SHA
#elif defined(MY_CPU_ARM_OR_ARM64) #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE) \
&& (!defined(Z7_MSC_VER_ORIGINAL) || (_MSC_VER >= 1929) && (_MSC_FULL_VER >= 192930037))
#if defined(__clang__) #if defined(__ARM_FEATURE_SHA2) \
#if (__clang_major__ >= 8) // fix that check || defined(__ARM_FEATURE_CRYPTO)
#define USE_HW_SHA
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define USE_HW_SHA #define USE_HW_SHA
#endif #endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define USE_HW_SHA
#endif #endif
#elif defined(_MSC_VER)
#if _MSC_VER >= 1910
#define USE_HW_SHA
#endif #endif
#endif #endif
#ifdef USE_HW_SHA #ifdef USE_HW_SHA
// #pragma message("=== Sha1 HW === ") // #pragma message("=== Sha1 HW === ")
// __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_SHA2
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
#if defined(__clang__)
#define ATTRIB_SHA __attribute__((__target__("crypto")))
#else
#define ATTRIB_SHA __attribute__((__target__("+crypto"))) #define ATTRIB_SHA __attribute__((__target__("+crypto")))
#endif
#else #else
#if defined(__clang__) && (__clang_major__ >= 1)
#define ATTRIB_SHA __attribute__((__target__("armv8-a,sha2")))
#else
#define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
#endif
#endif #endif
#endif
#else #else
// _MSC_VER // _MSC_VER
// for arm32 // for arm32
#define _ARM_USE_NEW_NEON_INTRINSICS #define _ARM_USE_NEW_NEON_INTRINSICS
#endif #endif
#if defined(_MSC_VER) && defined(MY_CPU_ARM64)
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
#include <arm_neon.h>
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
// #if defined(__clang__) && __clang_major__ < 13
#define __ARM_FEATURE_CRYPTO 1
// #else
#define __ARM_FEATURE_SHA2 1
// #endif
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif #endif
#endif // clang
#if defined(__clang__)
#if defined(__ARM_ARCH) && __ARM_ARCH < 8
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
// #pragma message("#define __ARM_ARCH 8")
#undef __ARM_ARCH
#define __ARM_ARCH 8
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // clang
#include <arm_neon.h>
#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
defined(__ARM_FEATURE_CRYPTO) && \
defined(__ARM_FEATURE_SHA2)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#undef __ARM_FEATURE_CRYPTO
#undef __ARM_FEATURE_SHA2
#undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
#endif
#endif // Z7_MSC_VER_ORIGINAL
typedef uint32x4_t v128; typedef uint32x4_t v128;
// typedef __n128 v128; // MSVC // typedef __n128 v128; // MSVC
// the bug in clang 3.8.1:
// __builtin_neon_vgetq_lane_i32((int8x16_t)__s0, __p1);
#if defined(__clang__) && (__clang_major__ <= 9)
#pragma GCC diagnostic ignored "-Wvector-conversion"
#endif
#ifdef MY_CPU_BE #ifdef MY_CPU_BE
#define MY_rev32_for_LE(x) #define MY_rev32_for_LE(x)
@ -256,11 +341,11 @@ typedef uint32x4_t v128;
m = LOAD_128((data + (k) * 16)); \ m = LOAD_128((data + (k) * 16)); \
MY_rev32_for_LE(m); \ MY_rev32_for_LE(m); \
#define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3); #define SU0(dest, src2, src3) dest = vsha1su0q_u32(dest, src2, src3)
#define SU1(dest, src) dest = vsha1su1q_u32(dest, src); #define SU1(dest, src) dest = vsha1su1q_u32(dest, src)
#define C(e) abcd = vsha1cq_u32(abcd, e, t); #define C(e) abcd = vsha1cq_u32(abcd, e, t)
#define P(e) abcd = vsha1pq_u32(abcd, e, t); #define P(e) abcd = vsha1pq_u32(abcd, e, t)
#define M(e) abcd = vsha1mq_u32(abcd, e, t); #define M(e) abcd = vsha1mq_u32(abcd, e, t)
#define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0)) #define H(e) e = vsha1h_u32(vgetq_lane_u32(abcd, 0))
#define T(m, c) t = vaddq_u32(m, c) #define T(m, c) t = vaddq_u32(m, c)
@ -337,16 +422,17 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t
#endif // MY_CPU_ARM_OR_ARM64 #endif // MY_CPU_ARM_OR_ARM64
#ifndef USE_HW_SHA #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
// #error Stop_Compiling_UNSUPPORTED_SHA // #error Stop_Compiling_UNSUPPORTED_SHA
// #include <stdlib.h> // #include <stdlib.h>
// #include "Sha1.h" // #include "Sha1.h"
void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks); // #if defined(_MSC_VER)
#pragma message("Sha1 HW-SW stub was used") #pragma message("Sha1 HW-SW stub was used")
// #endif
void Z7_FASTCALL Sha1_UpdateBlocks (UInt32 state[5], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks); void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks) void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t numBlocks)
{ {
@ -359,7 +445,6 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
return; return;
*/ */
} }
#endif #endif
#undef SU0 #undef SU0
@ -384,3 +469,4 @@ void Z7_FASTCALL Sha1_UpdateBlocks_HW(UInt32 state[5], const Byte *data, size_t
#undef USE_HW_SHA #undef USE_HW_SHA
#undef ATTRIB_SHA #undef ATTRIB_SHA
#undef USE_VER_MIN #undef USE_VER_MIN
#undef Z7_USE_HW_SHA_STUB

View file

@ -1,5 +1,5 @@
/* Sha256.c -- SHA-256 Hash /* Sha256.c -- SHA-256 Hash
2023-04-02 : Igor Pavlov : Public domain 2024-03-01 : Igor Pavlov : Public domain
This code is based on public domain code from Wei Dai's Crypto++ library. */ This code is based on public domain code from Wei Dai's Crypto++ library. */
#include "Precomp.h" #include "Precomp.h"
@ -15,35 +15,35 @@ This code is based on public domain code from Wei Dai's Crypto++ library. */
#endif #endif
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#ifdef _MSC_VER #if defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30800) \
#if _MSC_VER >= 1200 || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 50100) \
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \
|| defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) \
|| defined(_MSC_VER) && (_MSC_VER >= 1200)
#define Z7_COMPILER_SHA256_SUPPORTED #define Z7_COMPILER_SHA256_SUPPORTED
#endif
#elif defined(__clang__)
#if (__clang_major__ >= 8) // fix that check
#define Z7_COMPILER_SHA256_SUPPORTED
#endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 8) // fix that check
#define Z7_COMPILER_SHA256_SUPPORTED
#endif
#elif defined(__INTEL_COMPILER)
#if (__INTEL_COMPILER >= 1800) // fix that check
#define Z7_COMPILER_SHA256_SUPPORTED
#endif
#endif #endif
#elif defined(MY_CPU_ARM_OR_ARM64) #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
#ifdef _MSC_VER
#if _MSC_VER >= 1910 #if defined(__ARM_FEATURE_SHA2) \
|| defined(__ARM_FEATURE_CRYPTO)
#define Z7_COMPILER_SHA256_SUPPORTED
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define Z7_COMPILER_SHA256_SUPPORTED #define Z7_COMPILER_SHA256_SUPPORTED
#endif #endif
#elif defined(__clang__)
#if (__clang_major__ >= 8) // fix that check
#define Z7_COMPILER_SHA256_SUPPORTED
#endif #endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define Z7_COMPILER_SHA256_SUPPORTED
#endif #endif
#endif #endif
#endif #endif
@ -224,8 +224,6 @@ void Sha256_Init(CSha256 *p)
#endif #endif
void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks);
// static // static
extern MY_ALIGN(64) extern MY_ALIGN(64)
const UInt32 SHA256_K_ARRAY[64]; const UInt32 SHA256_K_ARRAY[64];

View file

@ -1,5 +1,5 @@
/* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions /* Sha256Opt.c -- SHA-256 optimized code for SHA-256 hardware instructions
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "Compiler.h" #include "Compiler.h"
@ -11,6 +11,8 @@
#endif #endif
#endif #endif
// #define Z7_USE_HW_SHA_STUB // for debug
#ifdef MY_CPU_X86_OR_AMD64 #ifdef MY_CPU_X86_OR_AMD64
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1600) // fix that check
#define USE_HW_SHA #define USE_HW_SHA
@ -32,9 +34,14 @@
#endif #endif
#if (_MSC_VER >= USE_VER_MIN) #if (_MSC_VER >= USE_VER_MIN)
#define USE_HW_SHA #define USE_HW_SHA
#else
#define Z7_USE_HW_SHA_STUB
#endif #endif
#endif #endif
// #endif // MY_CPU_X86_OR_AMD64 // #endif // MY_CPU_X86_OR_AMD64
#ifndef USE_HW_SHA
// #define Z7_USE_HW_SHA_STUB // for debug
#endif
#ifdef USE_HW_SHA #ifdef USE_HW_SHA
@ -202,19 +209,28 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#endif // USE_HW_SHA #endif // USE_HW_SHA
#elif defined(MY_CPU_ARM_OR_ARM64) #elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
#if defined(__clang__) #if defined(__ARM_FEATURE_SHA2) \
#if (__clang_major__ >= 8) // fix that check || defined(__ARM_FEATURE_CRYPTO)
#define USE_HW_SHA
#else
#if defined(MY_CPU_ARM64) \
|| defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \
|| defined(Z7_MSC_VER_ORIGINAL)
#if defined(__ARM_FP) && \
( defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \
|| defined(__GNUC__) && (__GNUC__ >= 6) \
) \
|| defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON) && \
(Z7_CLANG_VERSION < 170000 || \
Z7_CLANG_VERSION > 170001)
#define USE_HW_SHA #define USE_HW_SHA
#endif #endif
#elif defined(__GNUC__)
#if (__GNUC__ >= 6) // fix that check
#define USE_HW_SHA
#endif #endif
#elif defined(_MSC_VER)
#if _MSC_VER >= 1910
#define USE_HW_SHA
#endif #endif
#endif #endif
@ -222,23 +238,87 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
// #pragma message("=== Sha256 HW === ") // #pragma message("=== Sha256 HW === ")
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
#if defined(__clang__)
#define ATTRIB_SHA __attribute__((__target__("crypto")))
#else
#define ATTRIB_SHA __attribute__((__target__("+crypto"))) #define ATTRIB_SHA __attribute__((__target__("+crypto")))
#endif
#else #else
#if defined(__clang__) && (__clang_major__ >= 1)
#define ATTRIB_SHA __attribute__((__target__("armv8-a,sha2")))
#else
#define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #define ATTRIB_SHA __attribute__((__target__("fpu=crypto-neon-fp-armv8")))
#endif
#endif #endif
#endif
#else #else
// _MSC_VER // _MSC_VER
// for arm32 // for arm32
#define _ARM_USE_NEW_NEON_INTRINSICS #define _ARM_USE_NEW_NEON_INTRINSICS
#endif #endif
#if defined(_MSC_VER) && defined(MY_CPU_ARM64)
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
#include <arm_neon.h>
#if defined(__clang__) && __clang_major__ < 16
#if !defined(__ARM_FEATURE_SHA2) && \
!defined(__ARM_FEATURE_CRYPTO)
// #pragma message("=== we set __ARM_FEATURE_CRYPTO 1 === ")
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1
// #if defined(__clang__) && __clang_major__ < 13
#define __ARM_FEATURE_CRYPTO 1
// #else
#define __ARM_FEATURE_SHA2 1
// #endif
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif #endif
#endif // clang
#if defined(__clang__)
#if defined(__ARM_ARCH) && __ARM_ARCH < 8
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
// #pragma message("#define __ARM_ARCH 8")
#undef __ARM_ARCH
#define __ARM_ARCH 8
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif // clang
#include <arm_neon.h>
#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \
defined(__ARM_FEATURE_CRYPTO) && \
defined(__ARM_FEATURE_SHA2)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#undef __ARM_FEATURE_CRYPTO
#undef __ARM_FEATURE_SHA2
#undef Z7_ARM_FEATURE_CRYPTO_WAS_SET
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
// #pragma message("=== we undefine __ARM_FEATURE_CRYPTO === ")
#endif
#endif // Z7_MSC_VER_ORIGINAL
typedef uint32x4_t v128; typedef uint32x4_t v128;
// typedef __n128 v128; // MSVC // typedef __n128 v128; // MSVC
@ -316,10 +396,10 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
LOAD_SHUFFLE (m2, 2) LOAD_SHUFFLE (m2, 2)
LOAD_SHUFFLE (m3, 3) LOAD_SHUFFLE (m3, 3)
R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 ); R16 ( 0, NNN, NNN, SM1, NNN, SM1, SM2, SM1, SM2 )
R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); R16 ( 1, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 ); R16 ( 2, SM1, SM2, SM1, SM2, SM1, SM2, SM1, SM2 )
R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN ); R16 ( 3, SM1, SM2, NNN, SM2, NNN, NNN, NNN, NNN )
state0 = vaddq_u32(state0, state0_save); state0 = vaddq_u32(state0, state0_save);
state1 = vaddq_u32(state1, state1_save); state1 = vaddq_u32(state1, state1_save);
@ -337,16 +417,17 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#endif // MY_CPU_ARM_OR_ARM64 #endif // MY_CPU_ARM_OR_ARM64
#ifndef USE_HW_SHA #if !defined(USE_HW_SHA) && defined(Z7_USE_HW_SHA_STUB)
// #error Stop_Compiling_UNSUPPORTED_SHA // #error Stop_Compiling_UNSUPPORTED_SHA
// #include <stdlib.h> // #include <stdlib.h>
// We can compile this file with another C compiler,
// or we can compile asm version.
// So we can generate real code instead of this stub function.
// #include "Sha256.h" // #include "Sha256.h"
void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks); // #if defined(_MSC_VER)
#pragma message("Sha256 HW-SW stub was used") #pragma message("Sha256 HW-SW stub was used")
// #endif
void Z7_FASTCALL Sha256_UpdateBlocks (UInt32 state[8], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks); void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks);
void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks) void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_t numBlocks)
{ {
@ -359,7 +440,6 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
return; return;
*/ */
} }
#endif #endif
@ -384,3 +464,4 @@ void Z7_FASTCALL Sha256_UpdateBlocks_HW(UInt32 state[8], const Byte *data, size_
#undef USE_HW_SHA #undef USE_HW_SHA
#undef ATTRIB_SHA #undef ATTRIB_SHA
#undef USE_VER_MIN #undef USE_VER_MIN
#undef Z7_USE_HW_SHA_STUB

View file

@ -1,5 +1,5 @@
/* SwapBytes.c -- Byte Swap conversion filter /* SwapBytes.c -- Byte Swap conversion filter
2023-04-07 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -305,11 +305,12 @@ ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr)
msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want
*/ */
// _mm256_broadcastsi128_si256(*mask128_ptr); // _mm256_broadcastsi128_si256(*mask128_ptr);
/* #if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000)
#define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1) #define MY_mm256_set_m128i(hi, lo) _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)
MY_mm256_set_m128i #else
*/ #define MY_mm256_set_m128i _mm256_set_m128i
_mm256_set_m128i( #endif
MY_mm256_set_m128i(
*(const __m128i *)mask128_ptr, *(const __m128i *)mask128_ptr,
*(const __m128i *)mask128_ptr); *(const __m128i *)mask128_ptr);
#endif #endif
@ -330,32 +331,59 @@ ShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr)
// compile message "NEON intrinsics not available with the soft-float ABI" // compile message "NEON intrinsics not available with the soft-float ABI"
#elif defined(MY_CPU_ARM_OR_ARM64) || \ #elif defined(MY_CPU_ARM_OR_ARM64) \
(defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) && defined(MY_CPU_LE) \
// #elif defined(MY_CPU_ARM64) && !defined(Z7_DISABLE_ARM_NEON)
#if defined(__clang__) && (__clang_major__ >= 8) \ #if defined(__clang__) && (__clang_major__ >= 8) \
|| defined(__GNUC__) && (__GNUC__ >= 8) || defined(__GNUC__) && (__GNUC__ >= 6)
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \ #if defined(__ARM_FP)
#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 4)) \
|| defined(MY_CPU_ARM64) || defined(MY_CPU_ARM64)
#if defined(MY_CPU_ARM64) \
|| !defined(Z7_CLANG_VERSION) \
|| defined(__ARM_NEON)
#define USE_SWAP_128 #define USE_SWAP_128
#endif
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
// #define SWAP_ATTRIB_NEON __attribute__((__target__(""))) // #define SWAP_ATTRIB_NEON __attribute__((__target__("")))
#else #else
// #define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=crypto-neon-fp-armv8"))) #if defined(Z7_CLANG_VERSION)
#endif // #define SWAP_ATTRIB_NEON __attribute__((__target__("neon")))
#else
// #pragma message("SWAP_ATTRIB_NEON __attribute__((__target__(fpu=neon))")
#define SWAP_ATTRIB_NEON __attribute__((__target__("fpu=neon")))
#endif
#endif // MY_CPU_ARM64
#endif // __ARM_NEON
#endif // __ARM_ARCH
#endif // __ARM_FP
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#if (_MSC_VER >= 1910) #if (_MSC_VER >= 1910)
#define USE_SWAP_128 #define USE_SWAP_128
#endif #endif
#endif #endif
#if defined(_MSC_VER) && defined(MY_CPU_ARM64) #ifdef USE_SWAP_128
#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)
#include <arm64_neon.h> #include <arm64_neon.h>
#else #else
/*
#if !defined(__ARM_NEON)
#if defined(Z7_GCC_VERSION) && (__GNUC__ < 5) \
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 90201) \
|| defined(Z7_GCC_VERSION) && (__GNUC__ == 5) && (Z7_GCC_VERSION < 100100)
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#pragma message("#define __ARM_NEON 1")
// #define __ARM_NEON 1
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif
*/
#include <arm_neon.h> #include <arm_neon.h>
#endif #endif
#endif
#ifndef USE_SWAP_128 #ifndef USE_SWAP_128
#define FORCE_SWAP_MODE #define FORCE_SWAP_MODE
@ -464,6 +492,13 @@ Z7_ATTRIB_NO_VECTOR \
void Z7_FASTCALL void Z7_FASTCALL
#if defined(MY_CPU_ARM_OR_ARM64)
#if defined(__clang__)
#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
#endif
#endif
#ifdef MY_CPU_64BIT #ifdef MY_CPU_64BIT
#if defined(MY_CPU_ARM64) \ #if defined(MY_CPU_ARM64) \

View file

@ -1,5 +1,5 @@
/* Threads.c -- multithreading library /* Threads.c -- multithreading library
2023-03-04 : Igor Pavlov : Public domain */ 2024-03-28 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -195,20 +195,19 @@ WRes CriticalSection_Init(CCriticalSection *p)
// ---------- POSIX ---------- // ---------- POSIX ----------
#ifndef __APPLE__ #if defined(__linux__) && !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
#ifndef Z7_AFFINITY_DISABLE #ifndef Z7_AFFINITY_DISABLE
// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET // _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET
// clang < 3.6 : unknown warning group '-Wreserved-id-macro' // clang < 3.6 : unknown warning group '-Wreserved-id-macro'
// clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier" // clang 3.6 - 12.01 : gives warning "macro name is a reserved identifier"
// clang >= 13 : do not give warning // clang >= 13 : do not give warning
#if !defined(_GNU_SOURCE) #if !defined(_GNU_SOURCE)
#if defined(__clang__) && (__clang_major__ >= 4) && (__clang_major__ <= 12) Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#pragma GCC diagnostic ignored "-Wreserved-id-macro" // #define _GNU_SOURCE
#endif Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#define _GNU_SOURCE
#endif // !defined(_GNU_SOURCE) #endif // !defined(_GNU_SOURCE)
#endif // Z7_AFFINITY_DISABLE #endif // Z7_AFFINITY_DISABLE
#endif // __APPLE__ #endif // __linux__
#include "Threads.h" #include "Threads.h"
@ -244,8 +243,9 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param,
{ {
if (cpuSet) if (cpuSet)
{ {
#ifdef Z7_AFFINITY_SUPPORTED // pthread_attr_setaffinity_np() is not supported for MUSL compile.
// so we check for __GLIBC__ here
#if defined(Z7_AFFINITY_SUPPORTED) && defined( __GLIBC__)
/* /*
printf("\n affinity :"); printf("\n affinity :");
unsigned i; unsigned i;
@ -267,7 +267,7 @@ WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param,
// ret2 = // ret2 =
pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet); pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet);
// if (ret2) ret = ret2; // if (ret2) ret = ret2;
#endif #endif
} }
ret = pthread_create(&p->_tid, &attr, func, param); ret = pthread_create(&p->_tid, &attr, func, param);
@ -369,13 +369,20 @@ WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
{ return AutoResetEvent_Create(p, 0); } { return AutoResetEvent_Create(p, 0); }
#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13)
// freebsd:
#pragma GCC diagnostic ignored "-Wthread-safety-analysis"
#endif
WRes Event_Set(CEvent *p) WRes Event_Set(CEvent *p)
{ {
RINOK(pthread_mutex_lock(&p->_mutex)) RINOK(pthread_mutex_lock(&p->_mutex))
p->_state = True; p->_state = True;
int res1 = pthread_cond_broadcast(&p->_cond); {
int res2 = pthread_mutex_unlock(&p->_mutex); const int res1 = pthread_cond_broadcast(&p->_cond);
return (res2 ? res2 : res1); const int res2 = pthread_mutex_unlock(&p->_mutex);
return (res2 ? res2 : res1);
}
} }
WRes Event_Reset(CEvent *p) WRes Event_Reset(CEvent *p)
@ -408,8 +415,8 @@ WRes Event_Close(CEvent *p)
return 0; return 0;
p->_created = 0; p->_created = 0;
{ {
int res1 = pthread_mutex_destroy(&p->_mutex); const int res1 = pthread_mutex_destroy(&p->_mutex);
int res2 = pthread_cond_destroy(&p->_cond); const int res2 = pthread_cond_destroy(&p->_cond);
return (res1 ? res1 : res2); return (res1 ? res1 : res2);
} }
} }
@ -487,8 +494,8 @@ WRes Semaphore_Close(CSemaphore *p)
return 0; return 0;
p->_created = 0; p->_created = 0;
{ {
int res1 = pthread_mutex_destroy(&p->_mutex); const int res1 = pthread_mutex_destroy(&p->_mutex);
int res2 = pthread_cond_destroy(&p->_cond); const int res2 = pthread_cond_destroy(&p->_cond);
return (res1 ? res1 : res2); return (res1 ? res1 : res2);
} }
} }
@ -549,6 +556,18 @@ LONG InterlockedIncrement(LONG volatile *addend)
#endif #endif
} }
LONG InterlockedDecrement(LONG volatile *addend)
{
// Print("InterlockedDecrement")
#ifdef USE_HACK_UNSAFE_ATOMIC
LONG val = *addend - 1;
*addend = val;
return val;
#else
return __sync_sub_and_fetch(addend, 1);
#endif
}
#endif // _WIN32 #endif // _WIN32
WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p) WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)

View file

@ -1,5 +1,5 @@
/* Threads.h -- multithreading library /* Threads.h -- multithreading library
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-28 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_THREADS_H #ifndef ZIP7_INC_THREADS_H
#define ZIP7_INC_THREADS_H #define ZIP7_INC_THREADS_H
@ -9,12 +9,21 @@
#else #else
#include "Compiler.h"
// #define Z7_AFFINITY_DISABLE
#if defined(__linux__) #if defined(__linux__)
#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
#ifndef Z7_AFFINITY_DISABLE #ifndef Z7_AFFINITY_DISABLE
#define Z7_AFFINITY_SUPPORTED #define Z7_AFFINITY_SUPPORTED
// #pragma message(" ==== Z7_AFFINITY_SUPPORTED") // #pragma message(" ==== Z7_AFFINITY_SUPPORTED")
// #define _GNU_SOURCE #if !defined(_GNU_SOURCE)
// #pragma message(" ==== _GNU_SOURCE set")
// we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL
Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
#define _GNU_SOURCE
Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
#endif
#endif #endif
#endif #endif
#endif #endif
@ -173,7 +182,7 @@ WRes CriticalSection_Init(CCriticalSection *p);
#else // _WIN32 #else // _WIN32
typedef struct _CEvent typedef struct
{ {
int _created; int _created;
int _manual_reset; int _manual_reset;
@ -199,7 +208,7 @@ WRes Event_Wait(CEvent *p);
WRes Event_Close(CEvent *p); WRes Event_Close(CEvent *p);
typedef struct _CSemaphore typedef struct
{ {
int _created; int _created;
UInt32 _count; UInt32 _count;
@ -219,7 +228,7 @@ WRes Semaphore_Wait(CSemaphore *p);
WRes Semaphore_Close(CSemaphore *p); WRes Semaphore_Close(CSemaphore *p);
typedef struct _CCriticalSection typedef struct
{ {
pthread_mutex_t _mutex; pthread_mutex_t _mutex;
} CCriticalSection; } CCriticalSection;
@ -230,6 +239,7 @@ void CriticalSection_Enter(CCriticalSection *cs);
void CriticalSection_Leave(CCriticalSection *cs); void CriticalSection_Leave(CCriticalSection *cs);
LONG InterlockedIncrement(LONG volatile *addend); LONG InterlockedIncrement(LONG volatile *addend);
LONG InterlockedDecrement(LONG volatile *addend);
#endif // _WIN32 #endif // _WIN32

View file

@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /FAcs /Yu"Precomp.h" /FD /c # ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /FAcs /Yu"Precomp.h" /FD /c
# ADD BASE RSC /l 0x419 /d "NDEBUG" # ADD BASE RSC /l 0x419 /d "NDEBUG"
# ADD RSC /l 0x419 /d "NDEBUG" # ADD RSC /l 0x419 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@ -67,7 +67,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /Yu"Precomp.h" /FD /GZ /c # ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /D "Z7_PPMD_SUPPORT" /D "Z7_EXTRACT_ONLY" /Yu"Precomp.h" /FD /GZ /c
# ADD BASE RSC /l 0x419 /d "_DEBUG" # ADD BASE RSC /l 0x419 /d "_DEBUG"
# ADD RSC /l 0x419 /d "_DEBUG" # ADD RSC /l 0x419 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@ -234,6 +234,10 @@ SOURCE=.\Precomp.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\Precomp.h
# End Source File
# Begin Source File
SOURCE=.\Precomp.h SOURCE=.\Precomp.h
# End Source File # End Source File
# End Group # End Group

View file

@ -1,20 +1,11 @@
/* 7zMain.c - Test application for 7z Decoder /* 7zMain.c - Test application for 7z Decoder
2023-04-04 : Igor Pavlov : Public domain */ 2024-02-28 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "../../CpuArch.h"
#include "../../7z.h"
#include "../../7zAlloc.h"
#include "../../7zBuf.h"
#include "../../7zCrc.h"
#include "../../7zFile.h"
#include "../../7zVersion.h"
#ifndef USE_WINDOWS_FILE #ifndef USE_WINDOWS_FILE
/* for mkdir */ /* for mkdir */
#ifdef _WIN32 #ifdef _WIN32
@ -32,6 +23,15 @@
#endif #endif
#endif #endif
#include "../../7zFile.h"
#include "../../7z.h"
#include "../../7zAlloc.h"
#include "../../7zBuf.h"
#include "../../7zCrc.h"
#include "../../7zVersion.h"
#include "../../CpuArch.h"
#define kInputBufSize ((size_t)1 << 18) #define kInputBufSize ((size_t)1 << 18)
static const ISzAlloc g_Alloc = { SzAlloc, SzFree }; static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
@ -168,12 +168,12 @@ static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s
#endif #endif
) )
{ {
unsigned len = 0; size_t len = 0;
for (len = 0; s[len] != 0; len++) {} for (len = 0; s[len] != 0; len++) {}
#ifndef MY_USE_UTF8 #ifndef MY_USE_UTF8
{ {
const unsigned size = len * 3 + 100; const size_t size = len * 3 + 100;
if (!Buf_EnsureSize(buf, size)) if (!Buf_EnsureSize(buf, size))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
{ {
@ -320,21 +320,20 @@ static void UIntToStr_2(char *s, unsigned value)
// typedef long BOOL; // typedef long BOOL;
typedef int BOOL; typedef int BOOL;
typedef struct _FILETIME typedef struct
{ {
DWORD dwLowDateTime; DWORD dwLowDateTime;
DWORD dwHighDateTime; DWORD dwHighDateTime;
} FILETIME; } FILETIME;
static LONG TIME_GetBias() static LONG TIME_GetBias(void)
{ {
const time_t utc = time(NULL); const time_t utc = time(NULL);
struct tm *ptm = localtime(&utc); struct tm *ptm = localtime(&utc);
const int localdaylight = ptm->tm_isdst; /* daylight for local timezone */ const int localdaylight = ptm->tm_isdst; /* daylight for local timezone */
ptm = gmtime(&utc); ptm = gmtime(&utc);
ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */ ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */
const LONG bias = (int)(mktime(ptm) - utc); return (int)(mktime(ptm) - utc);
return bias;
} }
#define TICKS_PER_SEC 10000000 #define TICKS_PER_SEC 10000000
@ -359,11 +358,11 @@ static BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *l
static const UInt32 kNumTimeQuantumsInSecond = 10000000; static const UInt32 kNumTimeQuantumsInSecond = 10000000;
static const UInt32 kFileTimeStartYear = 1601; static const UInt32 kFileTimeStartYear = 1601;
static const UInt32 kUnixTimeStartYear = 1970; static const UInt32 kUnixTimeStartYear = 1970;
static const UInt64 kUnixTimeOffset =
(UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft) static Int64 Time_FileTimeToUnixTime64(const FILETIME *ft)
{ {
const UInt64 kUnixTimeOffset =
(UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear));
const UInt64 winTime = GET_TIME_64(ft); const UInt64 winTime = GET_TIME_64(ft);
return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;
} }
@ -384,8 +383,10 @@ static void FILETIME_To_timespec(const FILETIME *ft, struct MY_ST_TIMESPEC *ts)
if (sec2 == sec) if (sec2 == sec)
{ {
ts->tv_sec = sec2; ts->tv_sec = sec2;
const UInt64 winTime = GET_TIME_64(ft); {
ts->tv_nsec = (long)((winTime % 10000000) * 100); const UInt64 winTime = GET_TIME_64(ft);
ts->tv_nsec = (long)((winTime % 10000000) * 100);
}
return; return;
} }
} }
@ -429,7 +430,7 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s)
{ {
unsigned year, mon, hour, min, sec; unsigned year, mon, hour, min, sec;
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned t; UInt32 t;
UInt32 v; UInt32 v;
// UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); // UInt64 v64 = nt->Low | ((UInt64)nt->High << 32);
UInt64 v64; UInt64 v64;
@ -461,7 +462,7 @@ static void ConvertFileTimeToString(const CNtfsFileTime *nTime, char *s)
ms[1] = 29; ms[1] = 29;
for (mon = 0;; mon++) for (mon = 0;; mon++)
{ {
const unsigned d = ms[mon]; const UInt32 d = ms[mon];
if (v < d) if (v < d)
break; break;
v -= d; v -= d;

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -5,8 +5,6 @@ PROG = 7zDec.exe
C_OBJS = \ C_OBJS = \
$O\7zAlloc.obj \ $O\7zAlloc.obj \
$O\7zBuf.obj \ $O\7zBuf.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \ $O\7zFile.obj \
$O\7zDec.obj \ $O\7zDec.obj \
$O\7zArcIn.obj \ $O\7zArcIn.obj \
@ -25,10 +23,14 @@ C_OBJS = \
7Z_OBJS = \ 7Z_OBJS = \
$O\7zMain.obj \ $O\7zMain.obj \
!include "../../../CPP/7zip/Crc.mak"
!include "../../../CPP/7zip/LzmaDec.mak"
OBJS = \ OBJS = \
$O\Precomp.obj \ $O\Precomp.obj \
$(7Z_OBJS) \ $(7Z_OBJS) \
$(C_OBJS) \ $(C_OBJS) \
$(ASM_OBJS) \
!include "../../../CPP/Build.mak" !include "../../../CPP/Build.mak"
@ -38,3 +40,5 @@ $(C_OBJS): ../../$(*B).c
$(CCOMPL_USE) $(CCOMPL_USE)
$O\Precomp.obj: Precomp.c $O\Precomp.obj: Precomp.c
$(CCOMPL_PCH) $(CCOMPL_PCH)
!include "../../Asm_c.mak"

View file

@ -1,5 +1,5 @@
/* 7zipInstall.c - 7-Zip Installer /* 7zipInstall.c - 7-Zip Installer
2023-04-04 : Igor Pavlov : Public domain */ 2024-04-05 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -11,6 +11,8 @@
#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
#endif #endif
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
#ifdef Z7_OLD_WIN_SDK #ifdef Z7_OLD_WIN_SDK
struct IShellView; struct IShellView;
#define SHFOLDERAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE #define SHFOLDERAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
@ -41,16 +43,6 @@ typedef enum {
// #pragma GCC diagnostic ignored "-Wcast-function-type" // #pragma GCC diagnostic ignored "-Wcast-function-type"
#endif #endif
#if defined(__clang__) || defined(__GNUC__)
typedef void (*Z7_voidFunction)(void);
#define MY_CAST_FUNC (Z7_voidFunction)
#elif defined(_MSC_VER) && _MSC_VER > 1920
#define MY_CAST_FUNC (void *)
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
#else
#define MY_CAST_FUNC
#endif
#define LLL_(quote) L##quote #define LLL_(quote) L##quote
#define LLL(quote) LLL_(quote) #define LLL(quote) LLL_(quote)
@ -118,11 +110,13 @@ static LPCWSTR const k_Reg_Path32 = L"Path"
#define k_Reg_WOW_Flag 0 #define k_Reg_WOW_Flag 0
#endif #endif
#ifdef USE_7ZIP_32_DLL
#ifdef _WIN64 #ifdef _WIN64
#define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
#else #else
#define k_Reg_WOW_Flag_32 0 #define k_Reg_WOW_Flag_32 0
#endif #endif
#endif
#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}" #define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
@ -219,11 +213,11 @@ static DWORD GetFileVersion(LPCWSTR s)
return 0; return 0;
} }
my_GetFileVersionInfoSizeW = (Func_GetFileVersionInfoSizeW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, my_GetFileVersionInfoSizeW = (Func_GetFileVersionInfoSizeW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
"GetFileVersionInfoSizeW"); "GetFileVersionInfoSizeW");
my_GetFileVersionInfoW = (Func_GetFileVersionInfoW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, my_GetFileVersionInfoW = (Func_GetFileVersionInfoW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
"GetFileVersionInfoW"); "GetFileVersionInfoW");
my_VerQueryValueW = (Func_VerQueryValueW) MY_CAST_FUNC GetProcAddress(g_version_dll_hModule, my_VerQueryValueW = (Func_VerQueryValueW) Z7_CAST_FUNC_C GetProcAddress(g_version_dll_hModule,
"VerQueryValueW"); "VerQueryValueW");
if (!my_GetFileVersionInfoSizeW if (!my_GetFileVersionInfoSizeW
@ -1102,7 +1096,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{ {
BOOL isWow64 = FALSE; BOOL isWow64 = FALSE;
const Func_IsWow64Process func_IsWow64Process = (Func_IsWow64Process) const Func_IsWow64Process func_IsWow64Process = (Func_IsWow64Process)
MY_CAST_FUNC GetProcAddress(GetModuleHandleW(L"kernel32.dll"), Z7_CAST_FUNC_C GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
"IsWow64Process"); "IsWow64Process");
if (func_IsWow64Process) if (func_IsWow64Process)
@ -1111,7 +1105,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (!isWow64) if (!isWow64)
{ {
if (!g_SilentMode) if (!g_SilentMode)
PrintErrorMessage("This installation requires Windows " MY_CPU_NAME, NULL); PrintErrorMessage("This installation requires Windows "
#ifdef MY_CPU_X86_OR_AMD64
"x64"
#else
"64-bit"
#endif
, NULL);
return 1; return 1;
} }
} }

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -19,9 +19,6 @@ C_OBJS = \
$O\7zAlloc.obj \ $O\7zAlloc.obj \
$O\7zArcIn.obj \ $O\7zArcIn.obj \
$O\7zBuf.obj \ $O\7zBuf.obj \
$O\7zBuf2.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \ $O\7zFile.obj \
$O\7zDec.obj \ $O\7zDec.obj \
$O\7zStream.obj \ $O\7zStream.obj \
@ -34,11 +31,17 @@ C_OBJS = \
OBJS = \ OBJS = \
$(MAIN_OBJS) \ $(MAIN_OBJS) \
$(C_OBJS) \ $(C_OBJS) \
$(ASM_OBJS) \
$O\resource.res $O\resource.res
!include "../../../CPP/7zip/Crc.mak"
# !include "../../../CPP/7zip/LzmaDec.mak"
!include "../../../CPP/Build.mak" !include "../../../CPP/Build.mak"
$(MAIN_OBJS): $(*B).c $(MAIN_OBJS): $(*B).c
$(COMPL_O1) $(COMPL_O1)
$(C_OBJS): ../../$(*B).c $(C_OBJS): ../../$(*B).c
$(COMPL_O1) $(COMPL_O1)
!include "../../Asm_c.mak"

View file

@ -1,5 +1,6 @@
#include <winnt.h> #include <windows.h>
#include <WinUser.h> // #include <winnt.h>
// #include <WinUser.h>
#include <CommCtrl.h> #include <CommCtrl.h>
#define USE_COPYRIGHT_CR #define USE_COPYRIGHT_CR

View file

@ -1,10 +1,11 @@
/* 7zipUninstall.c - 7-Zip Uninstaller /* 7zipUninstall.c - 7-Zip Uninstaller
2022-07-15 : Igor Pavlov : Public domain */ 2024-03-21 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
// #define SZ_ERROR_ABORT 100 // #define SZ_ERROR_ABORT 100
#include "../../7zTypes.h"
#include "../../7zWindows.h" #include "../../7zWindows.h"
#if defined(_MSC_VER) && _MSC_VER < 1600 #if defined(_MSC_VER) && _MSC_VER < 1600
@ -31,16 +32,7 @@ typedef enum {
#include "resource.h" #include "resource.h"
#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)
// #pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
#if defined(_MSC_VER) && _MSC_VER > 1920
#define MY_CAST_FUNC (void *)
// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'
#else
#define MY_CAST_FUNC
#endif
#define LLL_(quote) L##quote #define LLL_(quote) L##quote
@ -101,11 +93,13 @@ static LPCWSTR const k_Reg_Path32 = L"Path"
#define k_Reg_WOW_Flag 0 #define k_Reg_WOW_Flag 0
#endif #endif
#ifdef USE_7ZIP_32_DLL
#ifdef _WIN64 #ifdef _WIN64
#define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY #define k_Reg_WOW_Flag_32 KEY_WOW64_32KEY
#else #else
#define k_Reg_WOW_Flag_32 0 #define k_Reg_WOW_Flag_32 0
#endif #endif
#endif
#define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}" #define k_7zip_CLSID L"{23170F69-40C1-278A-1000-000100020000}"
@ -124,9 +118,19 @@ static HWND g_Path_HWND;
static HWND g_InfoLine_HWND; static HWND g_InfoLine_HWND;
static HWND g_Progress_HWND; static HWND g_Progress_HWND;
// WINADVAPI // RegDeleteKeyExW is supported starting from win2003sp1/xp-pro-x64
// Z7_WIN32_WINNT_MIN < 0x0600 // Vista
#if !defined(Z7_WIN32_WINNT_MIN) \
|| Z7_WIN32_WINNT_MIN < 0x0502 /* < win2003 */ \
|| Z7_WIN32_WINNT_MIN == 0x0502 && !defined(_M_AMD64)
#define Z7_USE_DYN_RegDeleteKeyExW
#endif
#ifdef Z7_USE_DYN_RegDeleteKeyExW
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
typedef LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); typedef LONG (APIENTRY *Func_RegDeleteKeyExW)(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
static Func_RegDeleteKeyExW func_RegDeleteKeyExW; static Func_RegDeleteKeyExW func_RegDeleteKeyExW;
#endif
static WCHAR cmd[MAX_PATH + 4]; static WCHAR cmd[MAX_PATH + 4];
static WCHAR cmdError[MAX_PATH + 4]; static WCHAR cmdError[MAX_PATH + 4];
@ -247,13 +251,18 @@ static LONG MyRegistry_OpenKey_ReadWrite(HKEY parentKey, LPCWSTR name, HKEY *des
static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCWSTR name) static LONG MyRegistry_DeleteKey(HKEY parentKey, LPCWSTR name)
{ {
#if k_Reg_WOW_Flag != 0 #if k_Reg_WOW_Flag != 0
if (func_RegDeleteKeyExW) #ifdef Z7_USE_DYN_RegDeleteKeyExW
return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag, 0); if (!func_RegDeleteKeyExW)
return E_FAIL; return E_FAIL;
#else return func_RegDeleteKeyExW
#else
return RegDeleteKeyExW
#endif
(parentKey, name, k_Reg_WOW_Flag, 0);
#else
return RegDeleteKeyW(parentKey, name); return RegDeleteKeyW(parentKey, name);
#endif #endif
} }
#ifdef USE_7ZIP_32_DLL #ifdef USE_7ZIP_32_DLL
@ -278,13 +287,18 @@ static LONG MyRegistry_OpenKey_ReadWrite_32(HKEY parentKey, LPCWSTR name, HKEY *
static LONG MyRegistry_DeleteKey_32(HKEY parentKey, LPCWSTR name) static LONG MyRegistry_DeleteKey_32(HKEY parentKey, LPCWSTR name)
{ {
#if k_Reg_WOW_Flag_32 != 0 #if k_Reg_WOW_Flag_32 != 0
if (func_RegDeleteKeyExW) #ifdef Z7_USE_DYN_RegDeleteKeyExW
return func_RegDeleteKeyExW(parentKey, name, k_Reg_WOW_Flag_32, 0); if (!func_RegDeleteKeyExW)
return E_FAIL; return E_FAIL;
#else return func_RegDeleteKeyExW
#else
return RegDeleteKeyExW
#endif
(parentKey, name, k_Reg_WOW_Flag_32, 0);
#else
return RegDeleteKeyW(parentKey, name); return RegDeleteKeyW(parentKey, name);
#endif #endif
} }
#endif #endif
@ -930,14 +944,17 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
UNUSED_VAR(lpCmdLine) UNUSED_VAR(lpCmdLine)
UNUSED_VAR(nCmdShow) UNUSED_VAR(nCmdShow)
#ifndef UNDER_CE #ifndef UNDER_CE
CoInitialize(NULL); CoInitialize(NULL);
#endif #endif
#ifndef UNDER_CE #ifndef UNDER_CE
func_RegDeleteKeyExW = (Func_RegDeleteKeyExW) MY_CAST_FUNC #ifdef Z7_USE_DYN_RegDeleteKeyExW
GetProcAddress(GetModuleHandleW(L"advapi32.dll"), "RegDeleteKeyExW"); func_RegDeleteKeyExW =
#endif (Func_RegDeleteKeyExW) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandleW(L"advapi32.dll"),
"RegDeleteKeyExW");
#endif
#endif
{ {
const wchar_t *s = GetCommandLineW(); const wchar_t *s = GetCommandLineW();

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -1,5 +1,6 @@
#include <winnt.h> #include <windows.h>
#include <WinUser.h> // #include <winnt.h>
// #include <WinUser.h>
#include <CommCtrl.h> #include <CommCtrl.h>
#define USE_COPYRIGHT_CR #define USE_COPYRIGHT_CR

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -14,16 +14,19 @@ C_OBJS = \
$O\CpuArch.obj \ $O\CpuArch.obj \
$O\LzFind.obj \ $O\LzFind.obj \
$O\LzFindMt.obj \ $O\LzFindMt.obj \
$O\LzFindOpt.obj \
$O\LzmaDec.obj \ $O\LzmaDec.obj \
$O\LzmaEnc.obj \ $O\LzmaEnc.obj \
$O\LzmaLib.obj \ $O\LzmaLib.obj \
$O\Threads.obj \ $O\Threads.obj \
!include "../../../CPP/7zip/LzFindOpt.mak"
!include "../../../CPP/7zip/LzmaDec.mak"
OBJS = \ OBJS = \
$O\Precomp.obj \ $O\Precomp.obj \
$(LIB_OBJS) \ $(LIB_OBJS) \
$(C_OBJS) \ $(C_OBJS) \
$(ASM_OBJS) \
$O\resource.res $O\resource.res
!include "../../../CPP/Build.mak" !include "../../../CPP/Build.mak"
@ -52,3 +55,5 @@ $(C_OBJS): ../../$(*B).c
$(CCOMPLB_USE) $(CCOMPLB_USE)
!ENDIF !ENDIF
!include "../../Asm_c.mak"

View file

@ -1,14 +1,13 @@
/* Precomp.h -- StdAfx /* Precomp.h -- Precomp
2023-03-04 : Igor Pavlov : Public domain */ 2024-01-23 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_PRECOMP_H // #ifndef ZIP7_INC_PRECOMP_LOC_H
#define ZIP7_INC_PRECOMP_H // #define ZIP7_INC_PRECOMP_LOC_H
#if defined(_MSC_VER) && _MSC_VER >= 1800 #if defined(_MSC_VER) && _MSC_VER >= 1800
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "../../Compiler.h" #include "../../Precomp.h"
#include "../../7zTypes.h"
#endif // #endif

View file

@ -1,5 +1,5 @@
/* SfxSetup.c - 7z SFX Setup /* SfxSetup.c - 7z SFX Setup
2019-02-02 : Igor Pavlov : Public domain */ 2024-01-24 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -278,10 +278,10 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#ifdef _CONSOLE #ifdef _CONSOLE
SetConsoleCtrlHandler(HandlerRoutine, TRUE); SetConsoleCtrlHandler(HandlerRoutine, TRUE);
#else #else
UNUSED_VAR(hInstance); UNUSED_VAR(hInstance)
UNUSED_VAR(hPrevInstance); UNUSED_VAR(hPrevInstance)
UNUSED_VAR(lpCmdLine); UNUSED_VAR(lpCmdLine)
UNUSED_VAR(nCmdShow); UNUSED_VAR(nCmdShow)
#endif #endif
CrcGenerateTable(); CrcGenerateTable();
@ -516,12 +516,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#endif #endif
{ {
const SRes res2 = File_Close(&outFile); const WRes res2 = File_Close(&outFile);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
if (res2 != SZ_OK) if (res2 != 0)
{ {
res = res2; errorMessage = "Can't close output file";
res = SZ_ERROR_FAIL;
break; break;
} }
} }

View file

@ -9,8 +9,6 @@ C_OBJS = \
$O\7zArcIn.obj \ $O\7zArcIn.obj \
$O\7zBuf.obj \ $O\7zBuf.obj \
$O\7zBuf2.obj \ $O\7zBuf2.obj \
$O\7zCrc.obj \
$O\7zCrcOpt.obj \
$O\7zFile.obj \ $O\7zFile.obj \
$O\7zDec.obj \ $O\7zDec.obj \
$O\7zStream.obj \ $O\7zStream.obj \
@ -27,9 +25,13 @@ C_OBJS = \
7Z_OBJS = \ 7Z_OBJS = \
$O\SfxSetup.obj \ $O\SfxSetup.obj \
!include "../../../CPP/7zip/Crc.mak"
# !include "../../../CPP/7zip/LzmaDec.mak"
OBJS = \ OBJS = \
$(7Z_OBJS) \ $(7Z_OBJS) \
$(C_OBJS) \ $(C_OBJS) \
$(ASM_OBJS) \
$O\resource.res $O\resource.res
!include "../../../CPP/Build.mak" !include "../../../CPP/Build.mak"
@ -38,3 +40,5 @@ $(7Z_OBJS): $(*B).c
$(COMPL_O1) $(COMPL_O1)
$(C_OBJS): ../../$(*B).c $(C_OBJS): ../../$(*B).c
$(COMPL_O1) $(COMPL_O1)
!include "../../Asm_c.mak"

327
C/Xxh64.c Normal file
View file

@ -0,0 +1,327 @@
/* Xxh64.c -- XXH64 hash calculation
original code: Copyright (c) Yann Collet.
2023-08-18 : modified by Igor Pavlov.
This source code is licensed under BSD 2-Clause License.
*/
#include "Precomp.h"
#include "CpuArch.h"
#include "RotateDefs.h"
#include "Xxh64.h"
#define Z7_XXH_PRIME64_1 UINT64_CONST(0x9E3779B185EBCA87)
#define Z7_XXH_PRIME64_2 UINT64_CONST(0xC2B2AE3D27D4EB4F)
#define Z7_XXH_PRIME64_3 UINT64_CONST(0x165667B19E3779F9)
#define Z7_XXH_PRIME64_4 UINT64_CONST(0x85EBCA77C2B2AE63)
#define Z7_XXH_PRIME64_5 UINT64_CONST(0x27D4EB2F165667C5)
void Xxh64State_Init(CXxh64State *p)
{
const UInt64 seed = 0;
p->v[0] = seed + Z7_XXH_PRIME64_1 + Z7_XXH_PRIME64_2;
p->v[1] = seed + Z7_XXH_PRIME64_2;
p->v[2] = seed;
p->v[3] = seed - Z7_XXH_PRIME64_1;
}
#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) && defined(_MSC_VER)
#define Z7_XXH64_USE_ASM
#endif
#if !defined(MY_CPU_64BIT) && defined(MY_CPU_X86) \
&& defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL > 1200
/* we try to avoid __allmul calls in MSVC for 64-bit multiply.
But MSVC6 still uses __allmul for our code.
So for MSVC6 we use default 64-bit multiply without our optimization.
*/
#define LOW32(b) ((UInt32)(b & 0xffffffff))
/* MSVC compiler (MSVC > 1200) can use "mul" instruction
without __allmul for our MY_emulu MACRO.
MY_emulu is similar to __emulu(a, b) MACRO */
#define MY_emulu(a, b) ((UInt64)(a) * (b))
#define MY_SET_HIGH32(a) ((UInt64)(a) << 32)
#define MY_MUL32_SET_HIGH32(a, b) MY_SET_HIGH32((UInt32)(a) * (UInt32)(b))
// /*
#define MY_MUL64(a, b) \
( MY_emulu((UInt32)(a), LOW32(b)) + \
MY_SET_HIGH32( \
(UInt32)((a) >> 32) * LOW32(b) + \
(UInt32)(a) * (UInt32)((b) >> 32) \
))
// */
/*
#define MY_MUL64(a, b) \
( MY_emulu((UInt32)(a), LOW32(b)) \
+ MY_MUL32_SET_HIGH32((a) >> 32, LOW32(b)) + \
+ MY_MUL32_SET_HIGH32(a, (b) >> 32) \
)
*/
#define MY_MUL_32_64(a32, b) \
( MY_emulu((UInt32)(a32), LOW32(b)) \
+ MY_MUL32_SET_HIGH32(a32, (b) >> 32) \
)
#else
#define MY_MUL64(a, b) ((a) * (b))
#define MY_MUL_32_64(a32, b) ((a32) * (UInt64)(b))
#endif
static
Z7_FORCE_INLINE
UInt64 Xxh64_Round(UInt64 acc, UInt64 input)
{
acc += MY_MUL64(input, Z7_XXH_PRIME64_2);
acc = Z7_ROTL64(acc, 31);
return MY_MUL64(acc, Z7_XXH_PRIME64_1);
}
static UInt64 Xxh64_Merge(UInt64 acc, UInt64 val)
{
acc ^= Xxh64_Round(0, val);
return MY_MUL64(acc, Z7_XXH_PRIME64_1) + Z7_XXH_PRIME64_4;
}
#ifdef Z7_XXH64_USE_ASM
#define Z7_XXH_PRIME64_1_HIGH 0x9E3779B1
#define Z7_XXH_PRIME64_1_LOW 0x85EBCA87
#define Z7_XXH_PRIME64_2_HIGH 0xC2B2AE3D
#define Z7_XXH_PRIME64_2_LOW 0x27D4EB4F
void
Z7_NO_INLINE
__declspec(naked)
Z7_FASTCALL
Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end)
{
#if !defined(__clang__)
UNUSED_VAR(p)
UNUSED_VAR(data)
UNUSED_VAR(end)
#endif
__asm push ebx
__asm push ebp
__asm push esi
__asm push edi
#define STACK_OFFSET 4 * 8
__asm sub esp, STACK_OFFSET
#define COPY_1(n) \
__asm mov eax, [ecx + n * 4] \
__asm mov [esp + n * 4], eax \
#define COPY_2(n) \
__asm mov eax, [esp + n * 4] \
__asm mov [ecx + n * 4], eax \
COPY_1(0)
__asm mov edi, [ecx + 1 * 4] \
COPY_1(2)
COPY_1(3)
COPY_1(4)
COPY_1(5)
COPY_1(6)
COPY_1(7)
__asm mov esi, edx \
__asm mov [esp + 0 * 8 + 4], ecx
__asm mov ecx, Z7_XXH_PRIME64_2_LOW \
__asm mov ebp, Z7_XXH_PRIME64_1_LOW \
#define R(n, state1, state1_reg) \
__asm mov eax, [esi + n * 8] \
__asm imul ebx, eax, Z7_XXH_PRIME64_2_HIGH \
__asm add ebx, state1 \
__asm mul ecx \
__asm add edx, ebx \
__asm mov ebx, [esi + n * 8 + 4] \
__asm imul ebx, ecx \
__asm add eax, [esp + n * 8] \
__asm adc edx, ebx \
__asm mov ebx, eax \
__asm shld eax, edx, 31 \
__asm shld edx, ebx, 31 \
__asm imul state1_reg, eax, Z7_XXH_PRIME64_1_HIGH \
__asm imul edx, ebp \
__asm add state1_reg, edx \
__asm mul ebp \
__asm add state1_reg, edx \
__asm mov [esp + n * 8], eax \
#define R2(n) \
R(n, [esp + n * 8 + 4], ebx) \
__asm mov [esp + n * 8 + 4], ebx \
__asm align 16
__asm main_loop:
R(0, edi, edi)
R2(1)
R2(2)
R2(3)
__asm add esi, 32
__asm cmp esi, [esp + STACK_OFFSET + 4 * 4 + 4]
__asm jne main_loop
__asm mov ecx, [esp + 0 * 8 + 4]
COPY_2(0)
__asm mov [ecx + 1 * 4], edi
COPY_2(2)
COPY_2(3)
COPY_2(4)
COPY_2(5)
COPY_2(6)
COPY_2(7)
__asm add esp, STACK_OFFSET
__asm pop edi
__asm pop esi
__asm pop ebp
__asm pop ebx
__asm ret 4
}
#else
void
Z7_NO_INLINE
Z7_FASTCALL
Xxh64State_UpdateBlocks(CXxh64State *p, const void *_data, const void *end)
{
const Byte *data = (const Byte *)_data;
UInt64 v[4];
v[0] = p->v[0];
v[1] = p->v[1];
v[2] = p->v[2];
v[3] = p->v[3];
do
{
v[0] = Xxh64_Round(v[0], GetUi64(data)); data += 8;
v[1] = Xxh64_Round(v[1], GetUi64(data)); data += 8;
v[2] = Xxh64_Round(v[2], GetUi64(data)); data += 8;
v[3] = Xxh64_Round(v[3], GetUi64(data)); data += 8;
}
while (data != end);
p->v[0] = v[0];
p->v[1] = v[1];
p->v[2] = v[2];
p->v[3] = v[3];
}
#endif
UInt64 Xxh64State_Digest(const CXxh64State *p, const void *_data, UInt64 count)
{
UInt64 h = p->v[2];
if (count >= 32)
{
h = Z7_ROTL64(p->v[0], 1) +
Z7_ROTL64(p->v[1], 7) +
Z7_ROTL64(h, 12) +
Z7_ROTL64(p->v[3], 18);
h = Xxh64_Merge(h, p->v[0]);
h = Xxh64_Merge(h, p->v[1]);
h = Xxh64_Merge(h, p->v[2]);
h = Xxh64_Merge(h, p->v[3]);
}
else
h += Z7_XXH_PRIME64_5;
h += count;
// XXH64_finalize():
{
unsigned cnt = (unsigned)count & 31;
const Byte *data = (const Byte *)_data;
while (cnt >= 8)
{
h ^= Xxh64_Round(0, GetUi64(data));
data += 8;
h = Z7_ROTL64(h, 27);
h = MY_MUL64(h, Z7_XXH_PRIME64_1) + Z7_XXH_PRIME64_4;
cnt -= 8;
}
if (cnt >= 4)
{
const UInt32 v = GetUi32(data);
data += 4;
h ^= MY_MUL_32_64(v, Z7_XXH_PRIME64_1);
h = Z7_ROTL64(h, 23);
h = MY_MUL64(h, Z7_XXH_PRIME64_2) + Z7_XXH_PRIME64_3;
cnt -= 4;
}
while (cnt)
{
const UInt32 v = *data++;
h ^= MY_MUL_32_64(v, Z7_XXH_PRIME64_5);
h = Z7_ROTL64(h, 11);
h = MY_MUL64(h, Z7_XXH_PRIME64_1);
cnt--;
}
// XXH64_avalanche(h):
h ^= h >> 33; h = MY_MUL64(h, Z7_XXH_PRIME64_2);
h ^= h >> 29; h = MY_MUL64(h, Z7_XXH_PRIME64_3);
h ^= h >> 32;
return h;
}
}
void Xxh64_Init(CXxh64 *p)
{
Xxh64State_Init(&p->state);
p->count = 0;
p->buf64[0] = 0;
p->buf64[1] = 0;
p->buf64[2] = 0;
p->buf64[3] = 0;
}
void Xxh64_Update(CXxh64 *p, const void *_data, size_t size)
{
const Byte *data = (const Byte *)_data;
unsigned cnt;
if (size == 0)
return;
cnt = (unsigned)p->count;
p->count += size;
if (cnt &= 31)
{
unsigned rem = 32 - cnt;
Byte *dest = (Byte *)p->buf64 + cnt;
if (rem > size)
rem = (unsigned)size;
size -= rem;
cnt += rem;
// memcpy((Byte *)p->buf64 + cnt, data, rem);
do
*dest++ = *data++;
while (--rem);
if (cnt != 32)
return;
Xxh64State_UpdateBlocks(&p->state, p->buf64, &p->buf64[4]);
}
if (size &= ~(size_t)31)
{
Xxh64State_UpdateBlocks(&p->state, data, data + size);
data += size;
}
cnt = (unsigned)p->count & 31;
if (cnt)
{
// memcpy(p->buf64, data, cnt);
Byte *dest = (Byte *)p->buf64;
do
*dest++ = *data++;
while (--cnt);
}
}

50
C/Xxh64.h Normal file
View file

@ -0,0 +1,50 @@
/* Xxh64.h -- XXH64 hash calculation interfaces
2023-08-18 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XXH64_H
#define ZIP7_INC_XXH64_H
#include "7zTypes.h"
EXTERN_C_BEGIN
#define Z7_XXH64_BLOCK_SIZE (4 * 8)
typedef struct
{
UInt64 v[4];
} CXxh64State;
void Xxh64State_Init(CXxh64State *p);
// end != data && end == data + Z7_XXH64_BLOCK_SIZE * numBlocks
void Z7_FASTCALL Xxh64State_UpdateBlocks(CXxh64State *p, const void *data, const void *end);
/*
Xxh64State_Digest():
data:
the function processes only
(totalCount & (Z7_XXH64_BLOCK_SIZE - 1)) bytes in (data): (smaller than 32 bytes).
totalCount: total size of hashed stream:
it includes total size of data processed by previous Xxh64State_UpdateBlocks() calls,
and it also includes current processed size in (data).
*/
UInt64 Xxh64State_Digest(const CXxh64State *p, const void *data, UInt64 totalCount);
typedef struct
{
CXxh64State state;
UInt64 count;
UInt64 buf64[4];
} CXxh64;
void Xxh64_Init(CXxh64 *p);
void Xxh64_Update(CXxh64 *p, const void *data, size_t size);
#define Xxh64_Digest(p) \
Xxh64State_Digest(&(p)->state, (p)->buf64, (p)->count)
EXTERN_C_END
#endif

4
C/Xz.c
View file

@ -1,5 +1,5 @@
/* Xz.c - Xz /* Xz.c - Xz
2023-04-02 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -52,6 +52,7 @@ void XzCheck_Init(CXzCheck *p, unsigned mode)
case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;
case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;
case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;
default: break;
} }
} }
@ -62,6 +63,7 @@ void XzCheck_Update(CXzCheck *p, const void *data, size_t size)
case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;
case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;
case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;
default: break;
} }
} }

7
C/Xz.h
View file

@ -1,5 +1,5 @@
/* Xz.h - Xz interface /* Xz.h - Xz interface
2023-04-13 : Igor Pavlov : Public domain */ 2024-01-26 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XZ_H #ifndef ZIP7_INC_XZ_H
#define ZIP7_INC_XZ_H #define ZIP7_INC_XZ_H
@ -18,6 +18,7 @@ EXTERN_C_BEGIN
#define XZ_ID_ARMT 8 #define XZ_ID_ARMT 8
#define XZ_ID_SPARC 9 #define XZ_ID_SPARC 9
#define XZ_ID_ARM64 0xa #define XZ_ID_ARM64 0xa
#define XZ_ID_RISCV 0xb
#define XZ_ID_LZMA2 0x21 #define XZ_ID_LZMA2 0x21
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
@ -233,13 +234,13 @@ typedef enum
typedef struct typedef struct
{ {
EXzState state; EXzState state;
UInt32 pos; unsigned pos;
unsigned alignPos; unsigned alignPos;
unsigned indexPreSize; unsigned indexPreSize;
CXzStreamFlags streamFlags; CXzStreamFlags streamFlags;
UInt32 blockHeaderSize; unsigned blockHeaderSize;
UInt64 packSize; UInt64 packSize;
UInt64 unpackSize; UInt64 unpackSize;

View file

@ -1,5 +1,5 @@
/* XzCrc64.c -- CRC64 calculation /* XzCrc64.c -- CRC64 calculation
2023-04-02 : Igor Pavlov : Public domain */ 2023-12-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -8,36 +8,76 @@
#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) #define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)
#ifdef MY_CPU_LE // for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu
#define CRC64_NUM_TABLES 4 // #define Z7_CRC64_DEBUG_BE
#else #ifdef Z7_CRC64_DEBUG_BE
#define CRC64_NUM_TABLES 5 #undef MY_CPU_LE
#define MY_CPU_BE
UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif #endif
#ifdef Z7_CRC64_NUM_TABLES
#define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES
#else
#define Z7_CRC64_NUM_TABLES_USE 12
#endif
#if Z7_CRC64_NUM_TABLES_USE < 1
#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
#endif
#if Z7_CRC64_NUM_TABLES_USE != 1
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); #define FUNC_NAME_LE_2(s) XzCrc64UpdateT ## s
#define FUNC_NAME_LE_1(s) FUNC_NAME_LE_2(s)
#define FUNC_NAME_LE FUNC_NAME_LE_1(Z7_CRC64_NUM_TABLES_USE)
UInt64 Z7_FASTCALL FUNC_NAME_LE (UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif
#ifndef MY_CPU_LE
#define FUNC_NAME_BE_2(s) XzCrc64UpdateBeT ## s
#define FUNC_NAME_BE_1(s) FUNC_NAME_BE_2(s)
#define FUNC_NAME_BE FUNC_NAME_BE_1(Z7_CRC64_NUM_TABLES_USE)
UInt64 Z7_FASTCALL FUNC_NAME_BE (UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif #endif
typedef UInt64 (Z7_FASTCALL *CRC64_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); #if defined(MY_CPU_LE)
#define FUNC_REF FUNC_NAME_LE
#elif defined(MY_CPU_BE)
#define FUNC_REF FUNC_NAME_BE
#else
#define FUNC_REF g_Crc64Update
static UInt64 (Z7_FASTCALL *FUNC_REF)(UInt64 v, const void *data, size_t size, const UInt64 *table);
#endif
#endif
MY_ALIGN(64)
static UInt64 g_Crc64Table[256 * Z7_CRC64_NUM_TABLES_USE];
static CRC64_FUNC g_Crc64Update;
UInt64 g_Crc64Table[256 * CRC64_NUM_TABLES];
UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size) UInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size)
{ {
return g_Crc64Update(v, data, size, g_Crc64Table); #if Z7_CRC64_NUM_TABLES_USE == 1
#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
const UInt64 *table = g_Crc64Table;
const Byte *p = (const Byte *)data;
const Byte *lim = p + size;
for (; p != lim; p++)
v = CRC64_UPDATE_BYTE_2(v, *p);
return v;
#undef CRC64_UPDATE_BYTE_2
#else
return FUNC_REF (v, data, size, g_Crc64Table);
#endif
} }
UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size)
{
return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL;
}
Z7_NO_INLINE
void Z7_FASTCALL Crc64GenerateTable(void) void Z7_FASTCALL Crc64GenerateTable(void)
{ {
UInt32 i; unsigned i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt64 r = i; UInt64 r = i;
@ -46,35 +86,55 @@ void Z7_FASTCALL Crc64GenerateTable(void)
r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1))); r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1)));
g_Crc64Table[i] = r; g_Crc64Table[i] = r;
} }
for (i = 256; i < 256 * CRC64_NUM_TABLES; i++)
#if Z7_CRC64_NUM_TABLES_USE != 1
#if 1 || 1 && defined(MY_CPU_X86) // low register count
for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i++)
{ {
const UInt64 r = g_Crc64Table[(size_t)i - 256]; const UInt64 r0 = g_Crc64Table[(size_t)i];
g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); g_Crc64Table[(size_t)i + 256] = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);
} }
#else
#ifdef MY_CPU_LE for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i += 2)
g_Crc64Update = XzCrc64UpdateT4;
#else
{ {
#ifndef MY_CPU_BE UInt64 r0 = g_Crc64Table[(size_t)(i) ];
UInt64 r1 = g_Crc64Table[(size_t)(i) + 1];
r0 = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);
r1 = g_Crc64Table[(Byte)r1] ^ (r1 >> 8);
g_Crc64Table[(size_t)i + 256 ] = r0;
g_Crc64Table[(size_t)i + 256 + 1] = r1;
}
#endif
#ifndef MY_CPU_LE
{
#ifndef MY_CPU_BE
UInt32 k = 1; UInt32 k = 1;
if (*(const Byte *)&k == 1) if (*(const Byte *)&k == 1)
g_Crc64Update = XzCrc64UpdateT4; FUNC_REF = FUNC_NAME_LE;
else else
#endif #endif
{ {
for (i = 256 * CRC64_NUM_TABLES - 1; i >= 256; i--) #ifndef MY_CPU_BE
FUNC_REF = FUNC_NAME_BE;
#endif
for (i = 0; i < 256 * Z7_CRC64_NUM_TABLES_USE; i++)
{ {
const UInt64 x = g_Crc64Table[(size_t)i - 256]; const UInt64 x = g_Crc64Table[i];
g_Crc64Table[i] = Z7_BSWAP64(x); g_Crc64Table[i] = Z7_BSWAP64(x);
} }
g_Crc64Update = XzCrc64UpdateT1_BeT4;
} }
} }
#endif #endif // ndef MY_CPU_LE
#endif // Z7_CRC64_NUM_TABLES_USE != 1
} }
#undef kCrc64Poly #undef kCrc64Poly
#undef CRC64_NUM_TABLES #undef Z7_CRC64_NUM_TABLES_USE
#undef FUNC_REF
#undef FUNC_NAME_LE_2
#undef FUNC_NAME_LE_1
#undef FUNC_NAME_LE
#undef FUNC_NAME_BE_2
#undef FUNC_NAME_BE_1
#undef FUNC_NAME_BE

View file

@ -1,5 +1,5 @@
/* XzCrc64.h -- CRC64 calculation /* XzCrc64.h -- CRC64 calculation
2023-04-02 : Igor Pavlov : Public domain */ 2023-12-08 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_XZ_CRC64_H #ifndef ZIP7_INC_XZ_CRC64_H
#define ZIP7_INC_XZ_CRC64_H #define ZIP7_INC_XZ_CRC64_H
@ -10,16 +10,16 @@
EXTERN_C_BEGIN EXTERN_C_BEGIN
extern UInt64 g_Crc64Table[]; // extern UInt64 g_Crc64Table[];
void Z7_FASTCALL Crc64GenerateTable(void); void Z7_FASTCALL Crc64GenerateTable(void);
#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) #define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)
#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) #define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)
#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) // #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size); UInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size);
UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size); // UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size);
EXTERN_C_END EXTERN_C_END

View file

@ -1,61 +1,261 @@
/* XzCrc64Opt.c -- CRC64 calculation /* XzCrc64Opt.c -- CRC64 calculation (optimized functions)
2023-04-02 : Igor Pavlov : Public domain */ 2023-12-08 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
#include "CpuArch.h" #include "CpuArch.h"
#if !defined(Z7_CRC64_NUM_TABLES) || Z7_CRC64_NUM_TABLES > 1
// for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu
// #define Z7_CRC64_DEBUG_BE
#ifdef Z7_CRC64_DEBUG_BE
#undef MY_CPU_LE
#define MY_CPU_BE
#endif
#if defined(MY_CPU_64BIT)
#define Z7_CRC64_USE_64BIT
#endif
// the value Z7_CRC64_NUM_TABLES_USE must be defined to same value as in XzCrc64.c
#ifdef Z7_CRC64_NUM_TABLES
#define Z7_CRC64_NUM_TABLES_USE Z7_CRC64_NUM_TABLES
#else
#define Z7_CRC64_NUM_TABLES_USE 12
#endif
#if Z7_CRC64_NUM_TABLES_USE % 4 || \
Z7_CRC64_NUM_TABLES_USE < 4 || \
Z7_CRC64_NUM_TABLES_USE > 4 * 4
#error Stop_Compiling_Bad_CRC64_NUM_TABLES
#endif
#ifndef MY_CPU_BE #ifndef MY_CPU_BE
#define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC64_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); #if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)
UInt64 Z7_FASTCALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
#define Q64LE(n, d) \
( (table + ((n) * 8 + 7) * 0x100)[((d) ) & 0xFF] \
^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 3 * 8) & 0xFF] \
^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 4 * 8) & 0xFF] \
^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 5 * 8) & 0xFF] \
^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 6 * 8) & 0xFF] \
^ (table + ((n) * 8 + 0) * 0x100)[((d) >> 7 * 8)] )
#define R64(a) *((const UInt64 *)(const void *)p + (a))
#else
#define Q32LE(n, d) \
( (table + ((n) * 4 + 3) * 0x100)[((d) ) & 0xFF] \
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
#define R32(a) *((const UInt32 *)(const void *)p + (a))
#endif
#define CRC64_FUNC_PRE_LE2(step) \
UInt64 Z7_FASTCALL XzCrc64UpdateT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)
#define CRC64_FUNC_PRE_LE(step) \
CRC64_FUNC_PRE_LE2(step); \
CRC64_FUNC_PRE_LE2(step)
CRC64_FUNC_PRE_LE(Z7_CRC64_NUM_TABLES_USE)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) const Byte *lim;
for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)
v = CRC64_UPDATE_BYTE_2(v, *p); v = CRC64_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4) lim = p + size;
if (size >= Z7_CRC64_NUM_TABLES_USE)
{ {
const UInt32 d = (UInt32)v ^ *(const UInt32 *)(const void *)p; lim -= Z7_CRC64_NUM_TABLES_USE;
v = (v >> 32) do
^ (table + 0x300)[((d ) & 0xFF)] {
^ (table + 0x200)[((d >> 8) & 0xFF)] #if Z7_CRC64_NUM_TABLES_USE == 4
^ (table + 0x100)[((d >> 16) & 0xFF)] const UInt32 d = (UInt32)v ^ R32(0);
^ (table + 0x000)[((d >> 24))]; v = (v >> 32) ^ Q32LE(0, d);
#elif Z7_CRC64_NUM_TABLES_USE == 8
#ifdef Z7_CRC64_USE_64BIT
v ^= R64(0);
v = Q64LE(0, v);
#else
UInt32 v0, v1;
v0 = (UInt32)v ^ R32(0);
v1 = (UInt32)(v >> 32) ^ R32(1);
v = Q32LE(1, v0) ^ Q32LE(0, v1);
#endif
#elif Z7_CRC64_NUM_TABLES_USE == 12
UInt32 w;
UInt32 v0, v1;
v0 = (UInt32)v ^ R32(0);
v1 = (UInt32)(v >> 32) ^ R32(1);
w = R32(2);
v = Q32LE(0, w);
v ^= Q32LE(2, v0) ^ Q32LE(1, v1);
#elif Z7_CRC64_NUM_TABLES_USE == 16
#ifdef Z7_CRC64_USE_64BIT
UInt64 w;
UInt64 x;
w = R64(1); x = Q64LE(0, w);
v ^= R64(0); v = x ^ Q64LE(1, v);
#else
UInt32 v0, v1;
UInt32 r0, r1;
v0 = (UInt32)v ^ R32(0);
v1 = (UInt32)(v >> 32) ^ R32(1);
r0 = R32(2);
r1 = R32(3);
v = Q32LE(1, r0) ^ Q32LE(0, r1);
v ^= Q32LE(3, v0) ^ Q32LE(2, v1);
#endif
#else
#error Stop_Compiling_Bad_CRC64_NUM_TABLES
#endif
p += Z7_CRC64_NUM_TABLES_USE;
}
while (p <= lim);
lim += Z7_CRC64_NUM_TABLES_USE;
} }
for (; size > 0; size--, p++) for (; p < lim; p++)
v = CRC64_UPDATE_BYTE_2(v, *p); v = CRC64_UPDATE_BYTE_2(v, *p);
return v; return v;
} }
#undef CRC64_UPDATE_BYTE_2
#undef R32
#undef R64
#undef Q32LE
#undef Q64LE
#undef CRC64_FUNC_PRE_LE
#undef CRC64_FUNC_PRE_LE2
#endif #endif
#ifndef MY_CPU_LE #ifndef MY_CPU_LE
#define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[(Byte)((crc) >> 56) ^ (b)] ^ ((crc) << 8)) #define CRC64_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 56) ^ (b)] ^ ((crc) << 8))
UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); #if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)
UInt64 Z7_FASTCALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table)
#define Q64BE(n, d) \
( (table + ((n) * 8 + 0) * 0x100)[(Byte)(d)] \
^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 3 * 8) & 0xFF] \
^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 4 * 8) & 0xFF] \
^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 5 * 8) & 0xFF] \
^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 6 * 8) & 0xFF] \
^ (table + ((n) * 8 + 7) * 0x100)[((d) >> 7 * 8)] )
#ifdef Z7_CRC64_DEBUG_BE
#define R64BE(a) GetBe64a((const UInt64 *)(const void *)p + (a))
#else
#define R64BE(a) *((const UInt64 *)(const void *)p + (a))
#endif
#else
#define Q32BE(n, d) \
( (table + ((n) * 4 + 0) * 0x100)[(Byte)(d)] \
^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
#ifdef Z7_CRC64_DEBUG_BE
#define R32BE(a) GetBe32a((const UInt32 *)(const void *)p + (a))
#else
#define R32BE(a) *((const UInt32 *)(const void *)p + (a))
#endif
#endif
#define CRC64_FUNC_PRE_BE2(step) \
UInt64 Z7_FASTCALL XzCrc64UpdateBeT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)
#define CRC64_FUNC_PRE_BE(step) \
CRC64_FUNC_PRE_BE2(step); \
CRC64_FUNC_PRE_BE2(step)
CRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE)
{ {
const Byte *p = (const Byte *)data; const Byte *p = (const Byte *)data;
table += 0x100; const Byte *lim;
v = Z7_BSWAP64(v); v = Z7_BSWAP64(v);
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)
v = CRC64_UPDATE_BYTE_2_BE(v, *p); v = CRC64_UPDATE_BYTE_2_BE(v, *p);
for (; size >= 4; size -= 4, p += 4) lim = p + size;
if (size >= Z7_CRC64_NUM_TABLES_USE)
{ {
const UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)(const void *)p; lim -= Z7_CRC64_NUM_TABLES_USE;
v = (v << 32) do
^ (table + 0x000)[((d ) & 0xFF)] {
^ (table + 0x100)[((d >> 8) & 0xFF)] #if Z7_CRC64_NUM_TABLES_USE == 4
^ (table + 0x200)[((d >> 16) & 0xFF)] const UInt32 d = (UInt32)(v >> 32) ^ R32BE(0);
^ (table + 0x300)[((d >> 24))]; v = (v << 32) ^ Q32BE(0, d);
#elif Z7_CRC64_NUM_TABLES_USE == 12
const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
const UInt32 w = R32BE(2);
v = Q32BE(0, w);
v ^= Q32BE(2, d1) ^ Q32BE(1, d0);
#elif Z7_CRC64_NUM_TABLES_USE == 8
#ifdef Z7_CRC64_USE_64BIT
v ^= R64BE(0);
v = Q64BE(0, v);
#else
const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
v = Q32BE(1, d1) ^ Q32BE(0, d0);
#endif
#elif Z7_CRC64_NUM_TABLES_USE == 16
#ifdef Z7_CRC64_USE_64BIT
const UInt64 w = R64BE(1);
v ^= R64BE(0);
v = Q64BE(0, w) ^ Q64BE(1, v);
#else
const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);
const UInt32 d0 = (UInt32)(v ) ^ R32BE(1);
const UInt32 w1 = R32BE(2);
const UInt32 w0 = R32BE(3);
v = Q32BE(1, w1) ^ Q32BE(0, w0);
v ^= Q32BE(3, d1) ^ Q32BE(2, d0);
#endif
#elif
#error Stop_Compiling_Bad_CRC64_NUM_TABLES
#endif
p += Z7_CRC64_NUM_TABLES_USE;
}
while (p <= lim);
lim += Z7_CRC64_NUM_TABLES_USE;
} }
for (; size > 0; size--, p++) for (; p < lim; p++)
v = CRC64_UPDATE_BYTE_2_BE(v, *p); v = CRC64_UPDATE_BYTE_2_BE(v, *p);
return Z7_BSWAP64(v); return Z7_BSWAP64(v);
} }
#undef CRC64_UPDATE_BYTE_2_BE
#undef R32BE
#undef R64BE
#undef Q32BE
#undef Q64BE
#undef CRC64_FUNC_PRE_BE
#undef CRC64_FUNC_PRE_BE2
#endif
#undef Z7_CRC64_NUM_TABLES_USE
#endif #endif

View file

@ -1,5 +1,5 @@
/* XzDec.c -- Xz Decode /* XzDec.c -- Xz Decode
2023-04-13 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -105,30 +105,32 @@ static SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSiz
{ {
if (propSize != 1) if (propSize != 1)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
p->delta = (unsigned)props[0] + 1; p->delta = (UInt32)props[0] + 1;
} }
else else
{ {
if (propSize == 4) if (propSize == 4)
{ {
UInt32 v = GetUi32(props); const UInt32 v = GetUi32(props);
switch (p->methodId) switch (p->methodId)
{ {
case XZ_ID_PPC: case XZ_ID_PPC:
case XZ_ID_ARM: case XZ_ID_ARM:
case XZ_ID_SPARC: case XZ_ID_SPARC:
case XZ_ID_ARM64: case XZ_ID_ARM64:
if ((v & 3) != 0) if (v & 3)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
break; break;
case XZ_ID_ARMT: case XZ_ID_ARMT:
if ((v & 1) != 0) case XZ_ID_RISCV:
if (v & 1)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
break; break;
case XZ_ID_IA64: case XZ_ID_IA64:
if ((v & 0xF) != 0) if (v & 0xf)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
break; break;
default: break;
} }
p->ip = v; p->ip = v;
} }
@ -151,12 +153,13 @@ static void XzBcFilterState_Init(void *pp)
static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] = static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] =
{ {
Z7_BRANCH_CONV_DEC(PPC), Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC),
Z7_BRANCH_CONV_DEC(IA64), Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64),
Z7_BRANCH_CONV_DEC(ARM), Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM),
Z7_BRANCH_CONV_DEC(ARMT), Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT),
Z7_BRANCH_CONV_DEC(SPARC), Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC),
Z7_BRANCH_CONV_DEC(ARM64) Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64),
Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV)
}; };
static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size) static SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size)
@ -262,7 +265,7 @@ static SRes XzBcFilterState_Code2(void *pp,
#define XZ_IS_SUPPORTED_FILTER_ID(id) \ #define XZ_IS_SUPPORTED_FILTER_ID(id) \
((id) >= XZ_ID_Delta && (id) <= XZ_ID_ARM64) ((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV)
SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc) Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc)
@ -541,13 +544,12 @@ static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 met
{ {
IStateCoder *sc = &p->coders[coderIndex]; IStateCoder *sc = &p->coders[coderIndex];
p->ids[coderIndex] = methodId; p->ids[coderIndex] = methodId;
switch (methodId) if (methodId == XZ_ID_LZMA2)
{ return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); #ifdef USE_SUBBLOCK
#ifdef USE_SUBBLOCK if (methodId == XZ_ID_Subblock)
case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); return SbState_SetFromMethod(sc, p->alloc);
#endif #endif
}
if (coderIndex == 0) if (coderIndex == 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId, return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId,
@ -558,10 +560,8 @@ static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 met
static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
{ {
IStateCoder *sc = &p->coders[coderIndex]; IStateCoder *sc = &p->coders[coderIndex];
switch (methodId) if (methodId == XZ_ID_LZMA2)
{ return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
}
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
@ -804,7 +804,7 @@ static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte
} }
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
if (s == 0) return SZ_ERROR_ARCHIVE; \ if (s == 0) return SZ_ERROR_ARCHIVE; \
pos += s; } pos += s; }
@ -1034,7 +1034,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
SRes res; SRes res;
ECoderFinishMode finishMode2 = finishMode; ECoderFinishMode finishMode2 = finishMode;
BoolInt srcFinished2 = srcFinished; BoolInt srcFinished2 = (BoolInt)srcFinished;
BoolInt destFinish = False; BoolInt destFinish = False;
if (p->block.packSize != (UInt64)(Int64)-1) if (p->block.packSize != (UInt64)(Int64)-1)
@ -1127,7 +1127,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
return SZ_OK; return SZ_OK;
} }
switch (p->state) switch ((int)p->state)
{ {
case XZ_STATE_STREAM_HEADER: case XZ_STATE_STREAM_HEADER:
{ {
@ -1172,15 +1172,15 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
p->state = XZ_STATE_STREAM_INDEX; p->state = XZ_STATE_STREAM_INDEX;
break; break;
} }
p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4;
break; break;
} }
if (p->pos != p->blockHeaderSize) if (p->pos != p->blockHeaderSize)
{ {
UInt32 cur = p->blockHeaderSize - p->pos; unsigned cur = p->blockHeaderSize - p->pos;
if (cur > srcRem) if (cur > srcRem)
cur = (UInt32)srcRem; cur = (unsigned)srcRem;
memcpy(p->buf + p->pos, src, cur); memcpy(p->buf + p->pos, src, cur);
p->pos += cur; p->pos += cur;
(*srcLen) += cur; (*srcLen) += cur;
@ -1222,8 +1222,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
} }
else else
{ {
UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags);
UInt32 cur = checkSize - p->pos; unsigned cur = checkSize - p->pos;
if (cur != 0) if (cur != 0)
{ {
if (srcRem == 0) if (srcRem == 0)
@ -1232,7 +1232,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
return SZ_OK; return SZ_OK;
} }
if (cur > srcRem) if (cur > srcRem)
cur = (UInt32)srcRem; cur = (unsigned)srcRem;
memcpy(p->buf + p->pos, src, cur); memcpy(p->buf + p->pos, src, cur);
p->pos += cur; p->pos += cur;
(*srcLen) += cur; (*srcLen) += cur;
@ -1321,9 +1321,9 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
case XZ_STATE_STREAM_FOOTER: case XZ_STATE_STREAM_FOOTER:
{ {
UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos;
if (cur > srcRem) if (cur > srcRem)
cur = (UInt32)srcRem; cur = (unsigned)srcRem;
memcpy(p->buf + p->pos, src, cur); memcpy(p->buf + p->pos, src, cur);
p->pos += cur; p->pos += cur;
(*srcLen) += cur; (*srcLen) += cur;
@ -1358,6 +1358,8 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
} }
case XZ_STATE_BLOCK: break; /* to disable GCC warning */ case XZ_STATE_BLOCK: break; /* to disable GCC warning */
default: return SZ_ERROR_FAIL;
} }
} }
/* /*
@ -1773,10 +1775,10 @@ static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbac
} }
} }
{ {
UInt64 packSize = block->packSize; const UInt64 packSize = block->packSize;
UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
// if (blockPackSum <= me->props.inBlockMax) // if (blockPackSum <= me->props.inBlockMax)
// unpackBlockMaxSize // unpackBlockMaxSize
{ {
@ -2381,7 +2383,7 @@ static SRes XzDecMt_Decode_ST(CXzDecMt *p
if (tMode) if (tMode)
{ {
XzDecMt_FreeOutBufs(p); XzDecMt_FreeOutBufs(p);
tMode = MtDec_PrepareRead(&p->mtc); tMode = (BoolInt)MtDec_PrepareRead(&p->mtc);
} }
#endif #endif
@ -2644,7 +2646,7 @@ SRes XzDecMt_Decode(CXzDecMtHandle p,
p->outSize = *outDataSize; p->outSize = *outDataSize;
} }
p->finishMode = finishMode; p->finishMode = (BoolInt)finishMode;
// p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test

View file

@ -1,5 +1,5 @@
/* XzEnc.c -- Xz Encode /* XzEnc.c -- Xz Encode
2023-04-13 : Igor Pavlov : Public domain */ 2024-03-01 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -29,8 +29,9 @@
#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3) #define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3)
/* max pack size for LZMA2 block + check-64bytrs: */ #define XZ_CHECK_SIZE_MAX 64
#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + 64) /* max pack size for LZMA2 block + pad4 + check_size: */
#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + XZ_CHECK_SIZE_MAX)
#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize)) #define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize))
@ -325,12 +326,13 @@ typedef struct
static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] = static const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] =
{ {
Z7_BRANCH_CONV_ENC(PPC), Z7_BRANCH_CONV_ENC_2 (BranchConv_PPC),
Z7_BRANCH_CONV_ENC(IA64), Z7_BRANCH_CONV_ENC_2 (BranchConv_IA64),
Z7_BRANCH_CONV_ENC(ARM), Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM),
Z7_BRANCH_CONV_ENC(ARMT), Z7_BRANCH_CONV_ENC_2 (BranchConv_ARMT),
Z7_BRANCH_CONV_ENC(SPARC), Z7_BRANCH_CONV_ENC_2 (BranchConv_SPARC),
Z7_BRANCH_CONV_ENC(ARM64) Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM64),
Z7_BRANCH_CONV_ENC_2 (BranchConv_RISCV)
}; };
static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size) static SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size)
@ -888,9 +890,9 @@ static SRes Xz_CompressBlock(
blockSizes->unpackSize = checkInStream.processed; blockSizes->unpackSize = checkInStream.processed;
} }
{ {
Byte buf[4 + 64]; Byte buf[4 + XZ_CHECK_SIZE_MAX];
unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed); const unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed);
UInt64 packSize = seqSizeOutStream.processed; const UInt64 packSize = seqSizeOutStream.processed;
buf[0] = 0; buf[0] = 0;
buf[1] = 0; buf[1] = 0;
@ -898,7 +900,8 @@ static SRes Xz_CompressBlock(
buf[3] = 0; buf[3] = 0;
SeqCheckInStream_GetDigest(&checkInStream, buf + 4); SeqCheckInStream_GetDigest(&checkInStream, buf + 4);
RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize), padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId))) RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize),
padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId)))
blockSizes->totalSize = seqSizeOutStream.processed - padSize; blockSizes->totalSize = seqSizeOutStream.processed - padSize;
@ -1083,18 +1086,19 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
CXzEnc *me = (CXzEnc *)pp; CXzEnc *me = (CXzEnc *)pp;
SRes res; SRes res;
CMtProgressThunk progressThunk; CMtProgressThunk progressThunk;
Byte *dest;
Byte *dest = me->outBufs[outBufIndex];
UNUSED_VAR(finished) UNUSED_VAR(finished)
{ {
CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
bInfo->totalSize = 0; bInfo->totalSize = 0;
bInfo->unpackSize = 0; bInfo->unpackSize = 0;
bInfo->headerSize = 0; bInfo->headerSize = 0;
// v23.02: we don't compress empty blocks
// also we must ignore that empty block in XzEnc_MtCallback_Write()
if (srcSize == 0)
return SZ_OK;
} }
dest = me->outBufs[outBufIndex];
if (!dest) if (!dest)
{ {
dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize); dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);
@ -1140,18 +1144,20 @@ static SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBuf
static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex) static SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex)
{ {
CXzEnc *me = (CXzEnc *)pp; CXzEnc *me = (CXzEnc *)pp;
const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex]; const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];
const Byte *data = me->outBufs[outBufIndex]; // v23.02: we don't write empty blocks
// note: if (bInfo->unpackSize == 0) then there is no compressed data of block
RINOK(WriteBytes(me->outStream, data, bInfo->headerSize)) if (bInfo->unpackSize == 0)
return SZ_OK;
{ {
UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize); const Byte *data = me->outBufs[outBufIndex];
RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize)) RINOK(WriteBytes(me->outStream, data, bInfo->headerSize))
{
const UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize);
RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize))
}
return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);
} }
return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);
} }
#endif #endif

View file

@ -1,5 +1,5 @@
/* XzIn.c - Xz input /* XzIn.c - Xz input
2023-04-02 : Igor Pavlov : Public domain */ 2023-09-07 : Igor Pavlov : Public domain */
#include "Precomp.h" #include "Precomp.h"
@ -27,7 +27,7 @@ SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream)
} }
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
if (s == 0) return SZ_ERROR_ARCHIVE; \ if (s == 0) return SZ_ERROR_ARCHIVE; \
pos += s; } pos += s; }
@ -37,7 +37,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
unsigned headerSize; unsigned headerSize;
*headerSizeRes = 0; *headerSizeRes = 0;
RINOK(SeqInStream_ReadByte(inStream, &header[0])) RINOK(SeqInStream_ReadByte(inStream, &header[0]))
headerSize = (unsigned)header[0]; headerSize = header[0];
if (headerSize == 0) if (headerSize == 0)
{ {
*headerSizeRes = 1; *headerSizeRes = 1;
@ -47,7 +47,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
*isIndex = False; *isIndex = False;
headerSize = (headerSize << 2) + 4; headerSize = (headerSize << 2) + 4;
*headerSizeRes = headerSize; *headerSizeRes = (UInt32)headerSize;
{ {
size_t processedSize = headerSize - 1; size_t processedSize = headerSize - 1;
RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize)) RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize))
@ -58,7 +58,7 @@ SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex,
} }
#define ADD_SIZE_CHECK(size, val) \ #define ADD_SIZE_CHECK(size, val) \
{ UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } { const UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
UInt64 Xz_GetUnpackSize(const CXzStream *p) UInt64 Xz_GetUnpackSize(const CXzStream *p)
{ {

4064
C/ZstdDec.c Normal file

File diff suppressed because it is too large Load diff

173
C/ZstdDec.h Normal file
View file

@ -0,0 +1,173 @@
/* ZstdDec.h -- Zstd Decoder interfaces
2024-01-21 : Igor Pavlov : Public domain */
#ifndef ZIP7_INC_ZSTD_DEC_H
#define ZIP7_INC_ZSTD_DEC_H
EXTERN_C_BEGIN
typedef struct CZstdDec CZstdDec;
typedef CZstdDec * CZstdDecHandle;
CZstdDecHandle ZstdDec_Create(ISzAllocPtr alloc_Small, ISzAllocPtr alloc_Big);
void ZstdDec_Destroy(CZstdDecHandle p);
typedef enum
{
ZSTD_STATUS_NOT_SPECIFIED, /* use main error code instead */
ZSTD_STATUS_FINISHED_FRAME, /* data frame or skip frame was finished */
ZSTD_STATUS_NOT_FINISHED, /* just finished non-empty block or unfinished RAW/RLE block */
ZSTD_STATUS_NEEDS_MORE_INPUT, /* the callee needs more input bytes. It has more priority over ZSTD_STATUS_NOT_FINISHED */
ZSTD_STATUS_OUT_REACHED /* is not finihed frame and ((outProcessed > outSize) || (outProcessed == outSize && unfinished RAW/RLE block) */
} enum_ZstdStatus_Dummy;
#define ZstdDecState_DOES_NEED_MORE_INPUT_OR_FINISHED_FRAME(p) \
((p)->status & ZSTD_STATUS_FINISHED_FRAME)
/*
((p)->status == ZSTD_STATUS_NEEDS_MORE_INPUT || \
(p)->status == ZSTD_STATUS_FINISHED_FRAME)
*/
typedef Byte enum_ZstdStatus;
void ZstdDec_Init(CZstdDecHandle p);
typedef struct
{
UInt64 num_Blocks;
Byte descriptor_OR;
Byte descriptor_NOT_OR;
Byte are_ContentSize_Unknown;
Byte windowDescriptor_MAX;
// Byte are_ContentSize_Known;
// Byte are_SingleSegments;
// Byte are_WindowDescriptors;
Byte checksum_Defined;
// Byte are_Checksums;
// Byte are_Non_Checksums;
// Byte are_DictionaryId;
Byte are_DictionaryId_Different;
// Byte reserved[3];
UInt32 checksum; // checksum of last data frame
/// UInt32 dictionaryId_Cur;
UInt32 dictionaryId; // if there are non-zero dictionary IDs, then it's first dictionaryId
UInt64 num_DataFrames;
UInt64 num_SkipFrames;
UInt64 skipFrames_Size;
UInt64 contentSize_Total;
UInt64 contentSize_MAX;
// UInt64 num_Checksums;
// UInt64 num_Non_Checksums; // frames without checksum
// UInt64 num_WindowDescriptors;
// UInt64 num_SingleSegments;
// UInt64 num_Frames_with_ContentSize;
// UInt64 num_Frames_without_ContentSize;
UInt64 windowSize_MAX;
UInt64 windowSize_Allocate_MAX;
// UInt64 num_DictionaryIds;
// UInt64 num_Blocks_forType[4];
// UInt64 num_BlockBytes_forType[4];
// UInt64 num_SingleSegments;
// UInt64 singleSegment_ContentSize_MAX;
} CZstdDecInfo;
#define ZstdDecInfo_CLEAR(p) { memset(p, 0, sizeof(*(p))); }
#define ZstdDecInfo_GET_NUM_FRAMES(p) ((p)->num_DataFrames + (p)->num_SkipFrames)
typedef struct CZstdDecState
{
enum_ZstdStatus status; // out
Byte disableHash;
// Byte mustBeFinished;
Byte outSize_Defined;
// Byte isAfterSizeMode;
// UInt64 inProcessed;
// SRes codeRes;
// Byte needWrite_IsStrong;
const Byte *inBuf;
size_t inPos; // in/out
size_t inLim;
const Byte *win; // out
size_t winPos; // out
size_t wrPos; // in/out
// size_t cycSize; // out : if (!outBuf_fromCaller)
size_t needWrite_Size; // out
Byte *outBuf_fromCaller;
size_t outBufSize_fromCaller;
/* (outBufSize_fromCaller >= full_uncompressed_size_of_all_frames) is required
for success decoding.
If outBufSize_fromCaller < full_uncompressed_size_of_all_frames),
decoding can give error message, because we decode per block basis.
*/
// size_t outStep;
UInt64 outSize; // total in all frames
UInt64 outProcessed; // out decoded in all frames (it can be >= outSize)
CZstdDecInfo info;
} CZstdDecState;
void ZstdDecState_Clear(CZstdDecState *p);
/*
ZstdDec_Decode()
return:
SZ_OK - no error
SZ_ERROR_DATA - Data Error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported method or method properties
SZ_ERROR_CRC - XXH hash Error
// SZ_ERROR_ARCHIVE - Headers error (not used now)
*/
SRes ZstdDec_Decode(CZstdDecHandle dec, CZstdDecState *p);
/*
ZstdDec_ReadUnusedFromInBuf():
returns: the number of bytes that were read from InBuf
(*afterDecoding_tempPos) must be set to zero before first call of ZstdDec_ReadUnusedFromInBuf()
*/
size_t ZstdDec_ReadUnusedFromInBuf(
CZstdDecHandle dec,
size_t afterDecoding_tempPos, // in/out
void *data, size_t size);
typedef struct
{
SRes decode_SRes; // error code of data decoding
Byte is_NonFinishedFrame; // there is unfinished decoding for data frame or skip frame
Byte extraSize;
} CZstdDecResInfo;
/*
#define ZstdDecResInfo_CLEAR(p) \
{ (p)->decode_SRes = 0; \
(p)->is_NonFinishedFrame; \
(p)->extraSize = 0; \
}
// memset(p, 0, sizeof(*p));
*/
/*
additional error codes for CZstdDecResInfo::decode_SRes:
SZ_ERROR_NO_ARCHIVE - is not zstd stream (no frames)
SZ_ERROR_INPUT_EOF - need more data in input stream
*/
void ZstdDec_GetResInfo(const CZstdDec *dec,
const CZstdDecState *p,
SRes res, // it's result from ZstdDec_Decode()
CZstdDecResInfo *info);
EXTERN_C_END
#endif

View file

@ -6,6 +6,7 @@ IS_ARM64=1
CROSS_COMPILE= CROSS_COMPILE=
MY_ARCH= MY_ARCH=
USE_ASM=1 USE_ASM=1
ASM_FLAGS=-Wno-unused-macros
CC=$(CROSS_COMPILE)clang CC=$(CROSS_COMPILE)clang
CXX=$(CROSS_COMPILE)clang++ CXX=$(CROSS_COMPILE)clang++
USE_CLANG=1 USE_CLANG=1

View file

@ -124,7 +124,7 @@ $(WIM_OBJS): ../../Archive/Wim/$(*B).cpp
!IFDEF ZIP_OBJS !IFDEF ZIP_OBJS
$(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp $(ZIP_OBJS): ../../Archive/Zip/$(*B).cpp
$(COMPL) $(COMPL) $(ZIP_FLAGS)
!ENDIF !ENDIF
!IFDEF COMPRESS_OBJS !IFDEF COMPRESS_OBJS
@ -149,7 +149,7 @@ $(AGENT_OBJS): ../../UI/Agent/$(*B).cpp
!IFDEF CONSOLE_OBJS !IFDEF CONSOLE_OBJS
$(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp $(CONSOLE_OBJS): ../../UI/Console/$(*B).cpp
$(COMPL) $(COMPL) $(CONSOLE_VARIANT_FLAGS)
!ENDIF !ENDIF
!IFDEF EXPLORER_OBJS !IFDEF EXPLORER_OBJS
@ -191,7 +191,7 @@ $(C_OBJS): ../../../../C/$(*B).c
{../../UI/Agent}.cpp{$O}.obj:: {../../UI/Agent}.cpp{$O}.obj::
$(COMPLB) $(COMPLB)
{../../UI/Console}.cpp{$O}.obj:: {../../UI/Console}.cpp{$O}.obj::
$(COMPLB) $(COMPLB) $(CONSOLE_VARIANT_FLAGS)
{../../UI/Explorer}.cpp{$O}.obj:: {../../UI/Explorer}.cpp{$O}.obj::
$(COMPLB) $(COMPLB)
{../../UI/FileManager}.cpp{$O}.obj:: {../../UI/FileManager}.cpp{$O}.obj::
@ -226,7 +226,7 @@ $(C_OBJS): ../../../../C/$(*B).c
{../../Archive/Wim}.cpp{$O}.obj:: {../../Archive/Wim}.cpp{$O}.obj::
$(COMPLB) $(COMPLB)
{../../Archive/Zip}.cpp{$O}.obj:: {../../Archive/Zip}.cpp{$O}.obj::
$(COMPLB) $(COMPLB) $(ZIP_FLAGS)
{../../Compress}.cpp{$O}.obj:: {../../Compress}.cpp{$O}.obj::
$(COMPLB_O2) $(COMPLB_O2)

View file

@ -30,16 +30,33 @@ endif
# for object file # for object file
# -Wa,-aln=test.s # -Wa,-aln=test.s
# -save-temps # -save-temps
FLAGS_BASE = -mbranch-protection=standard -march=armv8.5-a
FLAGS_BASE = -mbranch-protection=standard
FLAGS_BASE =
# FLAGS_BASE = -DZ7_NO_UNICODE
CFLAGS_BASE_LIST = -c CFLAGS_BASE_LIST = -c
#DEBUG_BUILD=1
ifdef DEBUG_BUILD
CFLAGS_DEBUG = -g
else
CFLAGS_DEBUG = -DNDEBUG
ifneq ($(CC), $(CROSS_COMPILE)clang)
LFLAGS_STRIP = -s
endif
endif
# CFLAGS_BASE_LIST = -S # CFLAGS_BASE_LIST = -S
CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \ CFLAGS_BASE = -O2 $(CFLAGS_BASE_LIST) $(CFLAGS_WARN_WALL) $(CFLAGS_WARN) \
-DNDEBUG -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ $(CFLAGS_DEBUG) -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
-fPIC -fPIC
FLAGS_FLTO = -ffunction-sections FLAGS_FLTO = -ffunction-sections
FLAGS_FLTO = -flto FLAGS_FLTO = -flto
FLAGS_FLTO = FLAGS_FLTO = $(FLAGS_BASE)
#
# -DZ7_AFFINITY_DISABLE # -DZ7_AFFINITY_DISABLE
@ -68,7 +85,7 @@ endif
endif endif
endif endif
LDFLAGS_STATIC = -DNDEBUG $(LDFLAGS_STATIC_2) LDFLAGS_STATIC = $(CFLAGS_DEBUG) $(LDFLAGS_STATIC_2) $(LDFLAGS_STATIC_3)
ifndef O ifndef O
ifdef IS_MINGW ifdef IS_MINGW
@ -95,6 +112,7 @@ endif
else else
LDFLAGS = $(LDFLAGS_STATIC) LDFLAGS = $(LDFLAGS_STATIC)
# -z force-bti
# -s is not required for clang, do we need it for GCC ??? # -s is not required for clang, do we need it for GCC ???
#-static -static-libgcc -static-libstdc++ #-static -static-libgcc -static-libstdc++
@ -127,7 +145,8 @@ endif
LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP) LIB2_GUI = -lOle32 -lGdi32 -lComctl32 -lComdlg32 -lShell32 $(LIB_HTMLHELP)
LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI) LIB2 = -loleaut32 -luuid -ladvapi32 -lUser32 $(LIB2_GUI)
CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE # v24.00: -DUNICODE and -D_UNICODE are defined in precompilation header files
# CXXFLAGS_EXTRA = -DUNICODE -D_UNICODE
# -Wno-delete-non-virtual-dtor # -Wno-delete-non-virtual-dtor
@ -142,6 +161,7 @@ DEL_OBJ_EXE = -$(RM) $(PROGPATH) $(PROGPATH_STATIC) $(OBJS)
# LOCAL_LIBS=-lpthread # LOCAL_LIBS=-lpthread
# LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl # LOCAL_LIBS_DLL=$(LOCAL_LIBS) -ldl
LIB2 = -lpthread
LIB2 = -lpthread -ldl LIB2 = -lpthread -ldl
@ -190,7 +210,7 @@ CXX_WARN_FLAGS =
#-Wno-invalid-offsetof #-Wno-invalid-offsetof
#-Wno-reorder #-Wno-reorder
CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(FLAGS_FLTO) $(CXXFLAGS_EXTRA) $(CC_SHARED) $(CXX_WARN_FLAGS) $(CXX_STD_FLAGS) -o $@ CXXFLAGS = $(MY_ARCH_2) $(LOCAL_FLAGS) $(CXXFLAGS_BASE2) $(CFLAGS_BASE) $(FLAGS_FLTO) $(CXXFLAGS_EXTRA) $(CC_SHARED) $(CXX_WARN_FLAGS) $(CXX_STD_FLAGS) $(CXX_INCLUDE_FLAGS) -o $@
STATIC_TARGET= STATIC_TARGET=
ifdef COMPL_STATIC ifdef COMPL_STATIC
@ -207,11 +227,28 @@ $(O):
# LDFLAGS3= -Wl,--gc-sections # LDFLAGS3= -Wl,--gc-sections
# -Wl,--print-gc-sections # -Wl,--print-gc-sections
ifneq ($(CC), $(CROSS_COMPILE)clang) ifndef IS_MINGW
LFLAGS_STRIP = -s
# LFLAGS_NOEXECSTACK=
ifdef Z7_USE_OS_UNAME_FOR_NOEXECSTACK
Z7_OS := $(shell uname)
show_os:
echo $(Z7_OS)
# ifeq ($(CXX), $(CROSS_COMPILE)g++)
ifeq ($(Z7_OS), Linux)
LFLAGS_NOEXECSTACK ?= -z noexecstack
endif endif
LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(OBJS) $(MY_LIBS) $(LIB2) else
LFLAGS_NOEXECSTACK ?= $(shell echo 'int main(){return 0;}' | $(CC) $(MY_ARCH_2) -z noexecstack -o /dev/null -x c - 2>/dev/null && echo -z noexecstack || echo)
endif
endif
LFLAGS_ALL = $(LFLAGS_STRIP) $(MY_ARCH_2) $(LDFLAGS) $(FLAGS_FLTO) $(LD_arch) $(LFLAGS_NOEXECSTACK) $(OBJS) $(MY_LIBS) $(LIB2)
# -s : GCC : Remove all symbol table and relocation information from the executable. # -s : GCC : Remove all symbol table and relocation information from the executable.
# -s : CLANG : unsupported # -s : CLANG : unsupported
@ -304,6 +341,8 @@ $O/XzCrc64Init.o: ../../../Common/XzCrc64Init.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp $O/XzCrc64Reg.o: ../../../Common/XzCrc64Reg.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/Xxh64Reg.o: ../../../Common/Xxh64Reg.cpp
$(CXX) $(CXXFLAGS) $<
@ -490,6 +529,8 @@ $O/IhexHandler.o: ../../Archive/IhexHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/LpHandler.o: ../../Archive/LpHandler.cpp $O/LpHandler.o: ../../Archive/LpHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/LvmHandler.o: ../../Archive/LvmHandler.cpp
$(CXX) $(CXXFLAGS) $<
$O/LzhHandler.o: ../../Archive/LzhHandler.cpp $O/LzhHandler.o: ../../Archive/LzhHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp $O/LzmaHandler.o: ../../Archive/LzmaHandler.cpp
@ -536,6 +577,8 @@ $O/XzHandler.o: ../../Archive/XzHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZHandler.o: ../../Archive/ZHandler.cpp $O/ZHandler.o: ../../Archive/ZHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZstdHandler.o: ../../Archive/ZstdHandler.cpp
$(CXX) $(CXXFLAGS) $<
$O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp $O/7zCompressionMode.o: ../../Archive/7z/7zCompressionMode.cpp
@ -642,7 +685,7 @@ $O/WimRegister.o: ../../Archive/Wim/WimRegister.cpp
$O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp $O/ZipAddCommon.o: ../../Archive/Zip/ZipAddCommon.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp $O/ZipHandler.o: ../../Archive/Zip/ZipHandler.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $(ZIP_FLAGS) $<
$O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp $O/ZipHandlerOut.o: ../../Archive/Zip/ZipHandlerOut.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp $O/ZipIn.o: ../../Archive/Zip/ZipIn.cpp
@ -763,6 +806,10 @@ $O/ZlibDecoder.o: ../../Compress/ZlibDecoder.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp $O/ZlibEncoder.o: ../../Compress/ZlibEncoder.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ZstdDecoder.o: ../../Compress/ZstdDecoder.cpp
$(CXX) $(CXXFLAGS) $<
$O/ZstdRegister.o: ../../Compress/ZstdRegister.cpp
$(CXX) $(CXXFLAGS) $<
$O/7zAes.o: ../../Crypto/7zAes.cpp $O/7zAes.o: ../../Crypto/7zAes.cpp
@ -953,6 +1000,8 @@ $O/App.o: ../../UI/FileManager/App.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp $O/BrowseDialog.o: ../../UI/FileManager/BrowseDialog.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/BrowseDialog2.o: ../../UI/FileManager/BrowseDialog2.cpp
$(CXX) $(CXXFLAGS) $<
$O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp $O/ClassDefs.o: ../../UI/FileManager/ClassDefs.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp $O/ComboDialog.o: ../../UI/FileManager/ComboDialog.cpp
@ -993,6 +1042,8 @@ $O/LinkDialog.o: ../../UI/FileManager/LinkDialog.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp $O/ListViewDialog.o: ../../UI/FileManager/ListViewDialog.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/MemDialog.o: ../../UI/FileManager/MemDialog.cpp
$(CXX) $(CXXFLAGS) $<
$O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp $O/MenuPage.o: ../../UI/FileManager/MenuPage.cpp
$(CXX) $(CXXFLAGS) $< $(CXX) $(CXXFLAGS) $<
$O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp $O/MessagesDialog.o: ../../UI/FileManager/MessagesDialog.cpp
@ -1179,6 +1230,8 @@ $O/Sort.o: ../../../../C/Sort.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
$O/SwapBytes.o: ../../../../C/SwapBytes.c $O/SwapBytes.o: ../../../../C/SwapBytes.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
$O/Xxh64.o: ../../../../C/Xxh64.c
$(CC) $(CFLAGS) $<
$O/Xz.o: ../../../../C/Xz.c $O/Xz.o: ../../../../C/Xz.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
$O/XzCrc64.o: ../../../../C/XzCrc64.c $O/XzCrc64.o: ../../../../C/XzCrc64.c
@ -1189,6 +1242,8 @@ $O/XzEnc.o: ../../../../C/XzEnc.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
$O/XzIn.o: ../../../../C/XzIn.c $O/XzIn.o: ../../../../C/XzIn.c
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $<
$O/ZstdDec.o: ../../../../C/ZstdDec.c
$(CC) $(CFLAGS) $<
ifdef USE_ASM ifdef USE_ASM
@ -1254,7 +1309,7 @@ endif
ifdef IS_ARM64 ifdef IS_ARM64
$O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S $O/LzmaDecOpt.o: ../../../../Asm/arm64/LzmaDecOpt.S ../../../../Asm/arm64/7zAsm.S
$(CC) $(CFLAGS) $< $(CC) $(CFLAGS) $(ASM_FLAGS) $<
endif endif
$O/LzmaDec.o: ../../../../C/LzmaDec.c $O/LzmaDec.o: ../../../../C/LzmaDec.c

View file

@ -52,31 +52,30 @@ struct CCompressionMethodMode
bool DefaultMethod_was_Inserted; bool DefaultMethod_was_Inserted;
bool Filter_was_Inserted; bool Filter_was_Inserted;
bool PasswordIsDefined;
bool MemoryUsageLimit_WasSet;
#ifndef Z7_ST #ifndef Z7_ST
UInt32 NumThreads;
bool NumThreads_WasForced; bool NumThreads_WasForced;
bool MultiThreadMixer; bool MultiThreadMixer;
UInt32 NumThreads;
#endif #endif
UInt64 MemoryUsageLimit;
bool MemoryUsageLimit_WasSet;
bool PasswordIsDefined;
UString Password; // _Wipe UString Password; // _Wipe
UInt64 MemoryUsageLimit;
bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); } bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
CCompressionMethodMode(): CCompressionMethodMode():
DefaultMethod_was_Inserted(false) DefaultMethod_was_Inserted(false)
, Filter_was_Inserted(false) , Filter_was_Inserted(false)
, PasswordIsDefined(false)
, MemoryUsageLimit_WasSet(false)
#ifndef Z7_ST #ifndef Z7_ST
, NumThreads(1)
, NumThreads_WasForced(false) , NumThreads_WasForced(false)
, MultiThreadMixer(true) , MultiThreadMixer(true)
, NumThreads(1)
#endif #endif
, MemoryUsageLimit((UInt64)1 << 30) , MemoryUsageLimit((UInt64)1 << 30)
, MemoryUsageLimit_WasSet(false)
, PasswordIsDefined(false)
{} {}
#ifdef Z7_CPP_IS_SUPPORTED_default #ifdef Z7_CPP_IS_SUPPORTED_default

View file

@ -442,9 +442,10 @@ HRESULT CDecoder::Decode(
len = password.Len(); len = password.Len();
} }
CByteBuffer_Wipe buffer(len * 2); CByteBuffer_Wipe buffer(len * 2);
const LPCOLESTR psw = passwordBSTR;
for (size_t k = 0; k < len; k++) for (size_t k = 0; k < len; k++)
{ {
const wchar_t c = passwordBSTR[k]; const wchar_t c = psw[k];
((Byte *)buffer)[k * 2] = (Byte)c; ((Byte *)buffer)[k * 2] = (Byte)c;
((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8); ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);
} }
@ -501,8 +502,7 @@ HRESULT CDecoder::Decode(
CObjectVector< CMyComPtr<ISequentialInStream> > inStreams; CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
CLockedInStream *lockedInStreamSpec = new CLockedInStream; CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;
CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
#ifdef USE_MIXER_MT #ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST #ifdef USE_MIXER_ST
@ -514,8 +514,8 @@ HRESULT CDecoder::Decode(
{ {
// lockedInStream.Pos = (UInt64)(Int64)-1; // lockedInStream.Pos = (UInt64)(Int64)-1;
// RINOK(InStream_GetPos(inStream, lockedInStream.Pos)) // RINOK(InStream_GetPos(inStream, lockedInStream.Pos))
RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStreamSpec->Pos)) RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))
lockedInStreamSpec->Stream = inStream; lockedInStream->Stream = inStream;
#ifdef USE_MIXER_MT #ifdef USE_MIXER_MT
#ifdef USE_MIXER_ST #ifdef USE_MIXER_ST
@ -551,7 +551,7 @@ HRESULT CDecoder::Decode(
{ {
CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT; CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
packStream = lockedStreamImpSpec; packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
} }
#ifdef USE_MIXER_ST #ifdef USE_MIXER_ST
else else
@ -561,7 +561,7 @@ HRESULT CDecoder::Decode(
#ifdef USE_MIXER_ST #ifdef USE_MIXER_ST
CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST; CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
packStream = lockedStreamImpSpec; packStream = lockedStreamImpSpec;
lockedStreamImpSpec->Init(lockedInStreamSpec, packPos); lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);
#endif #endif
} }
} }

View file

@ -299,10 +299,9 @@ static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
writeCoderProperties, coder) writeCoderProperties, coder)
if (writeCoderProperties) if (writeCoderProperties)
{ {
CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;
CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
outStreamSpec->Init(); outStreamSpec->Init();
RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream)) RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))
outStreamSpec->CopyToBuffer(props); outStreamSpec->CopyToBuffer(props);
} }
else else
@ -332,11 +331,8 @@ HRESULT CEncoder::Encode1(
RINOK(_mixer->ReInit2()) RINOK(_mixer->ReInit2())
CMtEncMultiProgress *mtProgressSpec = NULL; CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;
CMyComPtr<ICompressProgressInfo> mtProgress; CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;
CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
@ -454,18 +450,16 @@ HRESULT CEncoder::Encode1(
if (useMtProgress) if (useMtProgress)
{ {
mtProgressSpec = new CMtEncMultiProgress; mtProgress.SetFromCls(new CMtEncMultiProgress);
mtProgress = mtProgressSpec; mtProgress->Init(compressProgress);
mtProgressSpec->Init(compressProgress);
mtOutStreamNotifySpec = new CSequentialOutMtNotify; mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);
mtOutStreamNotify = mtOutStreamNotifySpec; mtOutStreamNotify->_stream = outStream;
mtOutStreamNotifySpec->_stream = outStream; mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();
mtOutStreamNotifySpec->_mtProgressSpec = mtProgressSpec;
FOR_VECTOR (t, tempBufferSpecs) FOR_VECTOR (t, tempBufferSpecs)
{ {
tempBufferSpecs[t]->_mtProgressSpec = mtProgressSpec; tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();
} }
} }
@ -474,7 +468,8 @@ HRESULT CEncoder::Encode1(
{ {
outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
outStreamSizeCount = outStreamSizeCountSpec; outStreamSizeCount = outStreamSizeCountSpec;
outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?
mtOutStreamNotify.Interface() : outStream);
outStreamSizeCountSpec->Init(); outStreamSizeCountSpec->Init();
outStreamPointers.Add(outStreamSizeCount); outStreamPointers.Add(outStreamSizeCount);
} }
@ -486,8 +481,9 @@ HRESULT CEncoder::Encode1(
RINOK(_mixer->Code( RINOK(_mixer->Code(
&inStreamPointer, &inStreamPointer,
&outStreamPointers.Front(), outStreamPointers.ConstData(),
mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error)) mtProgress.IsDefined() ? mtProgress.Interface() :
compressProgress, dataAfterEnd_Error))
if (_bindInfo.PackStreams.Size() != 0) if (_bindInfo.PackStreams.Size() != 0)
packSizes.Add(outStreamSizeCountSpec->GetSize()); packSizes.Add(outStreamSizeCountSpec->GetSize());

View file

@ -271,8 +271,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetTotal(importantTotalUnpacked)) RINOK(extractCallback->SetTotal(importantTotalUnpacked))
CLocalProgress *lps = new CLocalProgress; CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
CDecoder decoder( CDecoder decoder(
@ -385,7 +384,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
&curUnpacked, &curUnpacked,
outStream, outStream,
progress, lps,
NULL // *inStreamMainRes NULL // *inStreamMainRes
, dataAfterEnd_Error , dataAfterEnd_Error

View file

@ -272,6 +272,7 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
prop = true; prop = true;
break; break;
} }
default: break;
} }
return prop.Detach(value); return prop.Detach(value);
#ifndef Z7_SFX #ifndef Z7_SFX
@ -291,7 +292,7 @@ bool CHandler::IsFolderEncrypted(CNum folderIndex) const
if (folderIndex == kNumNoIndex) if (folderIndex == kNumNoIndex)
return false; return false;
const size_t startPos = _db.FoCodersDataOffset[folderIndex]; const size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData + startPos; const Byte *p = _db.CodersData.ConstData() + startPos;
const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte; CInByte2 inByte;
inByte.Init(p, size); inByte.Init(p, size);
@ -350,11 +351,11 @@ Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data
{ {
if (_db.NameOffsets && _db.NamesBuf) if (_db.NameOffsets && _db.NamesBuf)
{ {
size_t offset = _db.NameOffsets[index]; const size_t offset = _db.NameOffsets[index];
size_t size = (_db.NameOffsets[index + 1] - offset) * 2; const size_t size = (_db.NameOffsets[index + 1] - offset) * 2;
if (size < ((UInt32)1 << 31)) if (size < ((UInt32)1 << 31))
{ {
*data = (const void *)(_db.NamesBuf + offset * 2); *data = (const void *)(_db.NamesBuf.ConstData() + offset * 2);
*dataSize = (UInt32)size; *dataSize = (UInt32)size;
*propType = NPropDataType::kUtf16z; *propType = NPropDataType::kUtf16z;
} }
@ -395,7 +396,7 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
temp[--pos] = 0; temp[--pos] = 0;
const size_t startPos = _db.FoCodersDataOffset[folderIndex]; const size_t startPos = _db.FoCodersDataOffset[folderIndex];
const Byte *p = _db.CodersData + startPos; const Byte *p = _db.CodersData.ConstData() + startPos;
const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos; const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;
CInByte2 inByte; CInByte2 inByte;
inByte.Init(p, size); inByte.Init(p, size);
@ -482,9 +483,9 @@ HRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const
if (propsSize == 1) if (propsSize == 1)
ConvertUInt32ToString((UInt32)props[0] + 1, s); ConvertUInt32ToString((UInt32)props[0] + 1, s);
} }
else if (id == k_ARM64) else if (id == k_ARM64 || id == k_RISCV)
{ {
name = "ARM64"; name = id == k_ARM64 ? "ARM64" : "RISCV";
if (propsSize == 4) if (propsSize == 4)
ConvertUInt32ToString(GetUi32(props), s); ConvertUInt32ToString(GetUi32(props), s);
/* /*
@ -666,6 +667,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif #endif
#endif #endif
default: break;
} }
// return prop.Detach(value); // return prop.Detach(value);
return S_OK; return S_OK;

View file

@ -54,11 +54,13 @@ public:
CBoolPair Write_Attrib; CBoolPair Write_Attrib;
bool _useMultiThreadMixer; bool _useMultiThreadMixer;
bool _removeSfxBlock; bool _removeSfxBlock;
// bool _volumeMode; // bool _volumeMode;
UInt32 _decoderCompatibilityVersion;
CUIntVector _enabledFilters;
CUIntVector _disabledFilters;
void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); } void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }
void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); } void InitSolidSize() { _numSolidBytes = (UInt64)(Int64)(-1); }
void InitSolid() void InitSolid()

View file

@ -20,6 +20,9 @@ using namespace NWindows;
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
static const UInt32 k_decoderCompatibilityVersion = 2301;
// 7-Zip version 2301 supports ARM64 filter
#define k_LZMA_Name "LZMA" #define k_LZMA_Name "LZMA"
#define kDefaultMethodName "LZMA2" #define kDefaultMethodName "LZMA2"
#define k_Copy_Name "Copy" #define k_Copy_Name "Copy"
@ -774,6 +777,11 @@ Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
options.MaxFilter = (level >= 8); options.MaxFilter = (level >= 8);
options.AnalysisLevel = GetAnalysisLevel(); options.AnalysisLevel = GetAnalysisLevel();
options.SetFilterSupporting_ver_enabled_disabled(
_decoderCompatibilityVersion,
_enabledFilters,
_disabledFilters);
options.HeaderOptions.CompressMainHeader = compressMainHeader; options.HeaderOptions.CompressMainHeader = compressMainHeader;
/* /*
options.HeaderOptions.WriteCTime = Write_CTime; options.HeaderOptions.WriteCTime = Write_CTime;
@ -858,6 +866,10 @@ void COutHandler::InitProps7z()
InitSolid(); InitSolid();
_useTypeSorting = false; _useTypeSorting = false;
_decoderCompatibilityVersion = k_decoderCompatibilityVersion;
_enabledFilters.Clear();
_disabledFilters.Clear();
} }
void COutHandler::InitProps() void COutHandler::InitProps()
@ -944,6 +956,29 @@ static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
return S_OK; return S_OK;
} }
struct C_Id_Name_pair
{
UInt32 Id;
const char *Name;
};
static const C_Id_Name_pair g_filter_pairs[] =
{
{ k_Delta, "Delta" },
{ k_ARM64, "ARM64" },
{ k_RISCV, "RISCV" },
{ k_SWAP2, "SWAP2" },
{ k_SWAP4, "SWAP4" },
{ k_BCJ, "BCJ" },
{ k_BCJ2 , "BCJ2" },
{ k_PPC, "PPC" },
{ k_IA64, "IA64" },
{ k_ARM, "ARM" },
{ k_ARMT, "ARMT" },
{ k_SPARC, "SPARC" }
};
HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value) HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
{ {
UString name = nameSpec; UString name = nameSpec;
@ -1004,6 +1039,43 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting); if (name.IsEqualTo("qs")) return PROPVARIANT_to_bool(value, _useTypeSorting);
if (name.IsPrefixedBy_Ascii_NoCase("yv"))
{
name.Delete(0, 2);
UInt32 v = 1 << 16; // if no number is noit specified, we use big value
RINOK(ParsePropToUInt32(name, value, v))
_decoderCompatibilityVersion = v;
// if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion;
return S_OK;
}
if (name.IsPrefixedBy_Ascii_NoCase("yf"))
{
name.Delete(0, 2);
CUIntVector *vec;
if (name.IsEqualTo_Ascii_NoCase("a")) vec = &_enabledFilters;
else if (name.IsEqualTo_Ascii_NoCase("d")) vec = &_disabledFilters;
else return E_INVALIDARG;
if (value.vt != VT_BSTR)
return E_INVALIDARG;
for (unsigned k = 0;; k++)
{
if (k == Z7_ARRAY_SIZE(g_filter_pairs))
{
// maybe we can ignore unsupported filter names here?
return E_INVALIDARG;
}
const C_Id_Name_pair &pair = g_filter_pairs[k];
if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name))
{
vec->AddToUniqueSorted(pair.Id);
break;
}
}
return S_OK;
}
// if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode); // if (name.IsEqualTo("v")) return PROPVARIANT_to_bool(value, _volumeMode);
} }
return CMultiMethodProps::SetProperty(name, value); return CMultiMethodProps::SetProperty(name, value);

View file

@ -100,6 +100,7 @@ namespace NID
const UInt32 k_Copy = 0; const UInt32 k_Copy = 0;
const UInt32 k_Delta = 3; const UInt32 k_Delta = 3;
const UInt32 k_ARM64 = 0xa; const UInt32 k_ARM64 = 0xa;
const UInt32 k_RISCV = 0xb;
const UInt32 k_LZMA2 = 0x21; const UInt32 k_LZMA2 = 0x21;
@ -126,7 +127,7 @@ const UInt32 k_AES = 0x6F10701;
// const UInt32 k_ZSTD = 0x4015D; // winzip zstd // const UInt32 k_ZSTD = 0x4015D; // winzip zstd
// 0x4F71101, 7z-zstd // 0x4F71101, 7z-zstd
static inline bool IsFilterMethod(UInt64 m) inline bool IsFilterMethod(UInt64 m)
{ {
if (m > (UInt32)0xFFFFFFFF) if (m > (UInt32)0xFFFFFFFF)
return false; return false;
@ -134,6 +135,7 @@ static inline bool IsFilterMethod(UInt64 m)
{ {
case k_Delta: case k_Delta:
case k_ARM64: case k_ARM64:
case k_RISCV:
case k_BCJ: case k_BCJ:
case k_BCJ2: case k_BCJ2:
case k_PPC: case k_PPC:
@ -144,6 +146,7 @@ static inline bool IsFilterMethod(UInt64 m)
case k_SWAP2: case k_SWAP2:
case k_SWAP4: case k_SWAP4:
return true; return true;
default: break;
} }
return false; return false;
} }

View file

@ -32,37 +32,45 @@
using namespace NWindows; using namespace NWindows;
using namespace NCOM; using namespace NCOM;
namespace NArchive {
namespace N7z {
#define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
unsigned BoolVector_CountSum(const CBoolVector &v); unsigned BoolVector_CountSum(const CBoolVector &v);
Z7_NO_INLINE
unsigned BoolVector_CountSum(const CBoolVector &v) unsigned BoolVector_CountSum(const CBoolVector &v)
{ {
unsigned sum = 0; unsigned sum = 0;
const unsigned size = v.Size(); const unsigned size = v.Size();
for (unsigned i = 0; i < size; i++) if (size)
if (v[i]) {
sum++; const bool *p = v.ConstData();
const bool * const lim = p + size;
do
if (*p)
sum++;
while (++p != lim);
}
return sum; return sum;
} }
static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i) static inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)
{ {
return (i < v.Size() ? v[i] : false); return i < v.Size() ? v[i] : false;
} }
Z7_NO_INLINE
static void BoolVector_Fill_False(CBoolVector &v, unsigned size) static void BoolVector_Fill_False(CBoolVector &v, unsigned size)
{ {
v.ClearAndSetSize(size); v.ClearAndSetSize(size);
bool *p = &v[0]; bool *p = v.NonConstData();
for (unsigned i = 0; i < size; i++) for (unsigned i = 0; i < size; i++)
p[i] = false; p[i] = false;
} }
namespace NArchive {
namespace N7z {
#define k_Scan_NumCoders_MAX 64
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
class CInArchiveException {}; class CInArchiveException {};
class CUnsupportedFeatureException: public CInArchiveException {}; class CUnsupportedFeatureException: public CInArchiveException {};
@ -510,7 +518,7 @@ void CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const
{ {
const size_t startPos = FoCodersDataOffset[folderIndex]; const size_t startPos = FoCodersDataOffset[folderIndex];
CInByte2 inByte; CInByte2 inByte;
inByte.Init(CodersData + startPos, FoCodersDataOffset[folderIndex + 1] - startPos); inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);
inByte.ParseFolder(folder); inByte.ParseFolder(folder);
if (inByte.GetRem() != 0) if (inByte.GetRem() != 0)
throw 20120424; throw 20120424;
@ -1177,8 +1185,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
ThrowUnsupported(); ThrowUnsupported();
data.Alloc(unpackSize); data.Alloc(unpackSize);
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream; CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamSpec;
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
outStreamSpec->Init(data, unpackSize); outStreamSpec->Init(data, unpackSize);
bool dataAfterEnd_Error = false; bool dataAfterEnd_Error = false;
@ -1189,7 +1196,7 @@ HRESULT CInArchive::ReadAndDecodePackedStreams(
folders, i, folders, i,
NULL, // &unpackSize64 NULL, // &unpackSize64
outStream, outStreamSpec,
NULL, // *compressProgress NULL, // *compressProgress
NULL // **inStreamMainRes NULL // **inStreamMainRes
@ -1280,7 +1287,7 @@ HRESULT CInArchive::ReadHeader(
CBoolVector emptyStreamVector; CBoolVector emptyStreamVector;
CBoolVector emptyFileVector; CBoolVector emptyFileVector;
CBoolVector antiFileVector; CBoolVector antiFileVector;
CNum numEmptyStreams = 0; unsigned numEmptyStreams = 0;
for (;;) for (;;)
{ {
@ -1311,7 +1318,7 @@ HRESULT CInArchive::ReadHeader(
for (i = 0; i < numFiles; i++) for (i = 0; i < numFiles; i++)
{ {
const size_t curRem = (rem - pos) / 2; const size_t curRem = (rem - pos) / 2;
const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf + pos); const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos);
size_t j; size_t j;
for (j = 0; j < curRem && buf[j] != 0; j++); for (j = 0; j < curRem && buf[j] != 0; j++);
if (j == curRem) if (j == curRem)
@ -1457,7 +1464,7 @@ HRESULT CInArchive::ReadHeader(
CNum emptyFileIndex = 0; CNum emptyFileIndex = 0;
CNum sizeIndex = 0; CNum sizeIndex = 0;
const CNum numAntiItems = BoolVector_CountSum(antiFileVector); const unsigned numAntiItems = BoolVector_CountSum(antiFileVector);
if (numAntiItems != 0) if (numAntiItems != 0)
db.IsAnti.ClearAndSetSize(numFiles); db.IsAnti.ClearAndSetSize(numFiles);
@ -1649,7 +1656,7 @@ HRESULT CInArchive::ReadDatabase2(
if (nextHeaderSize == 0) if (nextHeaderSize == 0)
{ {
if (nextHeaderOffset != 0) if (nextHeaderOffset != 0 || nextHeaderCRC != 0)
return S_FALSE; return S_FALSE;
db.IsArc = true; db.IsArc = true;
db.HeadersSize = HeadersSize; db.HeadersSize = HeadersSize;

View file

@ -273,33 +273,36 @@ struct CDbEx: public CDatabase
void FillLinks(); void FillLinks();
UInt64 GetFolderStreamPos(CNum folderIndex, unsigned indexInFolder) const UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const
{ {
return ArcInfo.DataStartPosition + return ArcInfo.DataStartPosition + PackPositions.ConstData()
PackPositions[FoStartPackStreamIndex[folderIndex] + indexInFolder]; [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder];
} }
UInt64 GetFolderFullPackSize(CNum folderIndex) const UInt64 GetFolderFullPackSize(size_t folderIndex) const
{ {
return return
PackPositions[FoStartPackStreamIndex[folderIndex + 1]] - PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] -
PackPositions[FoStartPackStreamIndex[folderIndex]]; PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]];
} }
UInt64 GetFolderPackStreamSize(CNum folderIndex, unsigned streamIndex) const UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const
{ {
size_t i = FoStartPackStreamIndex[folderIndex] + streamIndex; const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex;
return PackPositions[i + 1] - PackPositions[i]; return PackPositions.ConstData()[i + 1] -
PackPositions.ConstData()[i];
} }
UInt64 GetFilePackSize(CNum fileIndex) const /*
UInt64 GetFilePackSize(size_t fileIndex) const
{ {
CNum folderIndex = FileIndexToFolderIndexMap[fileIndex]; const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
if (folderIndex != kNumNoIndex) if (folderIndex != kNumNoIndex)
if (FolderStartFileIndex[folderIndex] == fileIndex) if (FolderStartFileIndex[folderIndex] == fileIndex)
return GetFolderFullPackSize(folderIndex); return GetFolderFullPackSize(folderIndex);
return 0; return 0;
} }
*/
}; };
const unsigned kNumBufLevelsMax = 4; const unsigned kNumBufLevelsMax = 4;

View file

@ -129,7 +129,7 @@ struct CUInt32DefVector
bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; } bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }
void SetItem(unsigned index, bool defined, UInt32 value); void SetItem(unsigned index, bool defined, UInt32 value);
void if_NonEmpty_FillResedue_with_false(unsigned numItems) void if_NonEmpty_FillResidue_with_false(unsigned numItems)
{ {
if (Defs.Size() != 0 && Defs.Size() < numItems) if (Defs.Size() != 0 && Defs.Size() < numItems)
SetItem(numItems - 1, false, 0); SetItem(numItems - 1, false, 0);

View file

@ -3,14 +3,34 @@
#include "StdAfx.h" #include "StdAfx.h"
#include "../../../../C/7zCrc.h" #include "../../../../C/7zCrc.h"
#include "../../../../C/CpuArch.h"
#include "../../../Common/AutoPtr.h" #include "../../../Common/AutoPtr.h"
// #include "../../../Common/UTFConvert.h" // #include "../../../Common/UTFConvert.h"
#include "../../Common/StreamObjects.h" #include "../../Common/StreamObjects.h"
#include "../Common/OutStreamWithCRC.h"
#include "7zOut.h" #include "7zOut.h"
unsigned BoolVector_CountSum(const CBoolVector &v);
static UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v)
{
UInt64 sum = 0;
const unsigned size = v.Size();
if (size)
{
const UInt64 *p = v.ConstData();
const UInt64 * const lim = p + size;
do
sum += *p++;
while (p != lim);
}
return sum;
}
namespace NArchive { namespace NArchive {
namespace N7z { namespace N7z {
@ -133,7 +153,7 @@ void COutArchive::WriteBytes(const void *data, size_t size)
else if (_writeToStream) else if (_writeToStream)
{ {
_outByte.WriteBytes(data, size); _outByte.WriteBytes(data, size);
_crc = CrcUpdate(_crc, data, size); // _crc = CrcUpdate(_crc, data, size);
} }
else else
_outByte2.WriteBytes(data, size); _outByte2.WriteBytes(data, size);
@ -144,14 +164,12 @@ void COutArchive::WriteByte(Byte b)
if (_countMode) if (_countMode)
_countSize++; _countSize++;
else if (_writeToStream) else if (_writeToStream)
{ WriteByte_ToStream(b);
_outByte.WriteByte(b);
_crc = CRC_UPDATE_BYTE(_crc, b);
}
else else
_outByte2.WriteByte(b); _outByte2.WriteByte(b);
} }
/*
void COutArchive::WriteUInt32(UInt32 value) void COutArchive::WriteUInt32(UInt32 value)
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -169,6 +187,7 @@ void COutArchive::WriteUInt64(UInt64 value)
value >>= 8; value >>= 8;
} }
} }
*/
void COutArchive::WriteNumber(UInt64 value) void COutArchive::WriteNumber(UInt64 value)
{ {
@ -288,7 +307,7 @@ void COutArchive::WriteFolder(const CFolder &folder)
WriteNumber(folder.PackStreams[i]); WriteNumber(folder.PackStreams[i]);
} }
void COutArchive::WriteBoolVector(const CBoolVector &boolVector) void COutArchive::Write_BoolVector(const CBoolVector &boolVector)
{ {
Byte b = 0; Byte b = 0;
Byte mask = 0x80; Byte mask = 0x80;
@ -314,31 +333,32 @@ void COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)
{ {
WriteByte(id); WriteByte(id);
WriteNumber(Bv_GetSizeInBytes(boolVector)); WriteNumber(Bv_GetSizeInBytes(boolVector));
WriteBoolVector(boolVector); Write_BoolVector(boolVector);
}
void COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined)
{
if (numDefined == boolVector.Size())
WriteByte(1);
else
{
WriteByte(0);
Write_BoolVector(boolVector);
}
} }
unsigned BoolVector_CountSum(const CBoolVector &v);
void COutArchive::WriteHashDigests(const CUInt32DefVector &digests) void COutArchive::WriteHashDigests(const CUInt32DefVector &digests)
{ {
const unsigned numDefined = BoolVector_CountSum(digests.Defs); const unsigned numDefined = BoolVector_CountSum(digests.Defs);
if (numDefined == 0) if (numDefined == 0)
return; return;
WriteByte(NID::kCRC); WriteByte(NID::kCRC);
if (numDefined == digests.Defs.Size()) Write_BoolVector_numDefined(digests.Defs, numDefined);
WriteByte(1); Write_UInt32DefVector_numDefined(digests, numDefined);
else
{
WriteByte(0);
WriteBoolVector(digests.Defs);
}
for (unsigned i = 0; i < digests.Defs.Size(); i++)
if (digests.Defs[i])
WriteUInt32(digests.Vals[i]);
} }
void COutArchive::WritePackInfo( void COutArchive::WritePackInfo(
UInt64 dataOffset, UInt64 dataOffset,
const CRecordVector<UInt64> &packSizes, const CRecordVector<UInt64> &packSizes,
@ -467,17 +487,42 @@ void COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, B
WriteByte(type); WriteByte(type);
WriteNumber(dataSize); WriteNumber(dataSize);
if (numDefined == v.Size()) Write_BoolVector_numDefined(v, numDefined);
WriteByte(1);
else
{
WriteByte(0);
WriteBoolVector(v);
}
WriteByte(0); // 0 means no switching to external stream WriteByte(0); // 0 means no switching to external stream
} }
void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
void COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined)
{
if (_countMode)
{
_countSize += (size_t)numDefined * 4;
return;
}
const bool * const defs = v.Defs.ConstData();
const UInt32 * const vals = v.Vals.ConstData();
const size_t num = v.Defs.Size();
for (size_t i = 0; i < num; i++)
if (defs[i])
{
UInt32 value = vals[i];
for (int k = 0; k < 4; k++)
{
if (_writeToStream)
WriteByte_ToStream((Byte)value);
else
_outByte2.WriteByte((Byte)value);
// WriteByte((Byte)value);
value >>= 8;
}
// WriteUInt32(v.Vals[i]);
}
}
void COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type)
{ {
const unsigned numDefined = BoolVector_CountSum(v.Defs); const unsigned numDefined = BoolVector_CountSum(v.Defs);
if (numDefined == 0) if (numDefined == 0)
@ -485,18 +530,40 @@ void COutArchive::WriteUInt64DefVector(const CUInt64DefVector &v, Byte type)
WriteAlignedBools(v.Defs, numDefined, type, 3); WriteAlignedBools(v.Defs, numDefined, type, 3);
for (unsigned i = 0; i < v.Defs.Size(); i++) if (_countMode)
if (v.Defs[i]) {
WriteUInt64(v.Vals[i]); _countSize += (size_t)numDefined * 8;
return;
}
const bool * const defs = v.Defs.ConstData();
const UInt64 * const vals = v.Vals.ConstData();
const size_t num = v.Defs.Size();
for (size_t i = 0; i < num; i++)
if (defs[i])
{
UInt64 value = vals[i];
for (int k = 0; k < 8; k++)
{
if (_writeToStream)
WriteByte_ToStream((Byte)value);
else
_outByte2.WriteByte((Byte)value);
// WriteByte((Byte)value);
value >>= 8;
}
// WriteUInt64(v.Vals[i]);
}
} }
HRESULT COutArchive::EncodeStream( HRESULT COutArchive::EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
CEncoder &encoder, const CByteBuffer &data, CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders) CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)
{ {
CBufInStream *streamSpec = new CBufInStream; CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec;
CMyComPtr<ISequentialInStream> stream = streamSpec;
streamSpec->Init(data, data.Size()); streamSpec->Init(data, data.Size());
outFolders.FolderUnpackCRCs.Defs.Add(true); outFolders.FolderUnpackCRCs.Defs.Add(true);
outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size())); outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));
@ -505,7 +572,7 @@ HRESULT COutArchive::EncodeStream(
const UInt64 expectSize = data.Size(); const UInt64 expectSize = data.Size();
RINOK(encoder.Encode1( RINOK(encoder.Encode1(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
stream, streamSpec,
// NULL, // NULL,
&dataSize64, // inSizeForReduce &dataSize64, // inSizeForReduce
expectSize, expectSize,
@ -528,13 +595,7 @@ void COutArchive::WriteHeader(
*/ */
_useAlign = true; _useAlign = true;
{ headerOffset = UInt64Vector_CountSum(db.PackSizes);
UInt64 packSize = 0;
FOR_VECTOR (i, db.PackSizes)
packSize += db.PackSizes[i];
headerOffset = packSize;
}
WriteByte(NID::kHeader); WriteByte(NID::kHeader);
@ -655,81 +716,97 @@ void COutArchive::WriteHeader(
{ {
/* ---------- Names ---------- */ /* ---------- Names ---------- */
unsigned numDefined = 0;
size_t namesDataSize = 0; size_t namesDataSize = 0;
FOR_VECTOR (i, db.Files)
{ {
const UString &name = db.Names[i];
if (!name.IsEmpty())
numDefined++;
const size_t numUtfChars =
/*
#if WCHAR_MAX > 0xffff
Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
#else
*/
name.Len();
// #endif
namesDataSize += (numUtfChars + 1) * 2;
}
if (numDefined > 0)
{
namesDataSize++;
SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
WriteByte(NID::kName);
WriteNumber(namesDataSize);
WriteByte(0);
FOR_VECTOR (i, db.Files) FOR_VECTOR (i, db.Files)
{ {
const UString &name = db.Names[i]; const UString &name = db.Names[i];
for (unsigned t = 0; t <= name.Len(); t++) const size_t numUtfChars =
{ /*
wchar_t c = name[t]; #if WCHAR_MAX > 0xffff
Get_Num_Utf16_chars_from_wchar_string(name.Ptr());
#else
*/
name.Len();
// #endif
namesDataSize += numUtfChars;
}
}
if (namesDataSize)
{
namesDataSize += db.Files.Size(); // we will write tail zero wchar for each name
namesDataSize *= 2; // 2 bytes per wchar for UTF16 encoding
namesDataSize++; // for additional switch byte (zero value)
SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);
WriteByte(NID::kName);
WriteNumber(namesDataSize);
/* if (_countMode)
#if WCHAR_MAX > 0xffff _countSize += namesDataSize;
if (c >= 0x10000) else
{
WriteByte(0);
FOR_VECTOR (i, db.Files)
{
const UString &name = db.Names[i];
const wchar_t *p = name.Ptr();
const size_t len = (size_t)name.Len() + 1;
const wchar_t * const lim = p + len;
if (_writeToStream)
{ {
c -= 0x10000; do
if (c < (1 << 20))
{ {
unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF); const wchar_t c = *p++;
WriteByte((Byte)c0); WriteByte_ToStream((Byte)c);
WriteByte((Byte)(c0 >> 8)); WriteByte_ToStream((Byte)(c >> 8));
c = 0xdc00 + (c & 0x3FF);
} }
else while (p != lim);
c = '_'; // we change character unsupported by UTF16 }
else
{
Byte *dest = _outByte2.GetDest_and_Update(len * 2);
do
{
/*
#if WCHAR_MAX > 0xffff
if (c >= 0x10000)
{
c -= 0x10000;
if (c < (1 << 20))
{
unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
WriteByte((Byte)c0);
WriteByte((Byte)(c0 >> 8));
c = 0xdc00 + (c & 0x3FF);
}
else
c = '_'; // we change character unsupported by UTF16
}
#endif
*/
const wchar_t c = *p++;
SetUi16(dest, (UInt16)c)
dest += 2;
}
while (p != lim);
} }
#endif
*/
WriteByte((Byte)c);
WriteByte((Byte)(c >> 8));
} }
} }
} }
} }
/* if (headerOptions.WriteCTime) */ WriteUInt64DefVector(db.CTime, NID::kCTime); /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime);
/* if (headerOptions.WriteATime) */ WriteUInt64DefVector(db.ATime, NID::kATime); /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime);
/* if (headerOptions.WriteMTime) */ WriteUInt64DefVector(db.MTime, NID::kMTime); /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime);
WriteUInt64DefVector(db.StartPos, NID::kStartPos); Write_UInt64DefVector_type(db.StartPos, NID::kStartPos);
{ {
/* ---------- Write Attrib ---------- */ /* ---------- Write Attrib ---------- */
const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs); const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);
if (numDefined != 0) if (numDefined != 0)
{ {
WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2); WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);
FOR_VECTOR (i, db.Attrib.Defs) Write_UInt32DefVector_numDefined(db.Attrib, numDefined);
{
if (db.Attrib.Defs[i])
WriteUInt32(db.Attrib.Vals[i]);
}
} }
} }
@ -765,13 +842,7 @@ void COutArchive::WriteHeader(
WriteByte(NID::kParent); WriteByte(NID::kParent);
WriteNumber(dataSize); WriteNumber(dataSize);
if (numIsDir == boolVector.Size()) Write_BoolVector_numDefined(boolVector, numIsDir);
WriteByte(1);
else
{
WriteByte(0);
WriteBoolVector(boolVector);
}
for (i = 0; i < db.Files.Size(); i++) for (i = 0; i < db.Files.Size(); i++)
{ {
const CFileItem &file = db.Files[i]; const CFileItem &file = db.Files[i];
@ -818,17 +889,17 @@ HRESULT COutArchive::WriteDatabase(
if (!db.CheckNumFiles()) if (!db.CheckNumFiles())
return E_FAIL; return E_FAIL;
UInt64 headerOffset; CStartHeader sh;
UInt32 headerCRC; sh.NextHeaderOffset = 0;
UInt64 headerSize; sh.NextHeaderSize = 0;
if (db.IsEmpty()) sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0);
{
headerSize = 0; if (!db.IsEmpty())
headerOffset = 0;
headerCRC = CrcCalc(NULL, 0);
}
else
{ {
CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream;
crcStream->SetStream(SeqStream);
crcStream->Init();
bool encodeHeaders = false; bool encodeHeaders = false;
if (options) if (options)
if (options->IsEmpty()) if (options->IsEmpty())
@ -837,13 +908,15 @@ HRESULT COutArchive::WriteDatabase(
if (options->PasswordIsDefined || headerOptions.CompressMainHeader) if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
encodeHeaders = true; encodeHeaders = true;
_outByte.SetStream(SeqStream); if (!_outByte.Create(1 << 16))
return E_OUTOFMEMORY;
_outByte.SetStream(crcStream.Interface());
_outByte.Init(); _outByte.Init();
_crc = CRC_INIT_VAL; // _crc = CRC_INIT_VAL;
_countMode = encodeHeaders; _countMode = encodeHeaders;
_writeToStream = true; _writeToStream = true;
_countSize = 0; _countSize = 0;
WriteHeader(db, /* headerOptions, */ headerOffset); WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
if (encodeHeaders) if (encodeHeaders)
{ {
@ -852,7 +925,7 @@ HRESULT COutArchive::WriteDatabase(
_countMode = false; _countMode = false;
_writeToStream = false; _writeToStream = false;
WriteHeader(db, /* headerOptions, */ headerOffset); WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);
if (_countSize != _outByte2.GetPos()) if (_countSize != _outByte2.GetPos())
return E_FAIL; return E_FAIL;
@ -876,15 +949,17 @@ HRESULT COutArchive::WriteDatabase(
throw 1; throw 1;
WriteID(NID::kEncodedHeader); WriteID(NID::kEncodedHeader);
WritePackInfo(headerOffset, packSizes, CUInt32DefVector()); WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector());
WriteUnpackInfo(folders, outFolders); WriteUnpackInfo(folders, outFolders);
WriteByte(NID::kEnd); WriteByte(NID::kEnd);
FOR_VECTOR (i, packSizes)
headerOffset += packSizes[i]; sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes);
} }
RINOK(_outByte.Flush()) RINOK(_outByte.Flush())
headerCRC = CRC_GET_DIGEST(_crc); sh.NextHeaderCRC = crcStream->GetCRC();
headerSize = _outByte.GetProcessedSize(); // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc);
// if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1;
sh.NextHeaderSize = _outByte.GetProcessedSize();
} }
#ifdef Z7_7Z_VOL #ifdef Z7_7Z_VOL
if (_endMarker) if (_endMarker)
@ -904,12 +979,8 @@ HRESULT COutArchive::WriteDatabase(
#endif #endif
if (Stream) if (Stream)
{ {
CStartHeader h;
h.NextHeaderSize = headerSize;
h.NextHeaderCRC = headerCRC;
h.NextHeaderOffset = headerOffset;
RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL)) RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))
return WriteStartHeader(h); return WriteStartHeader(sh);
} }
return S_OK; return S_OK;
} }

View file

@ -19,32 +19,41 @@ const unsigned k_StartHeadersRewriteSize = 32;
class CWriteBufferLoc class CWriteBufferLoc
{ {
Byte *_data; Byte *_data;
size_t _size; Byte *_dataLim;
size_t _pos; Byte *_dataBase;
public: public:
CWriteBufferLoc(): _size(0), _pos(0) {} // CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {}
void Init(Byte *data, size_t size) void Init(Byte *data, size_t size)
{ {
_data = data; _data = data;
_size = size; _dataBase = data;
_pos = 0; _dataLim = data + size;
}
Byte *GetDest_and_Update(size_t size)
{
Byte *dest = _data;
if (size > (size_t)(_dataLim - dest))
throw 1;
_data = dest + size;
return dest;
} }
void WriteBytes(const void *data, size_t size) void WriteBytes(const void *data, size_t size)
{ {
if (size == 0) if (size == 0)
return; return;
if (size > _size - _pos) Byte *dest = GetDest_and_Update(size);
throw 1; memcpy(dest, data, size);
memcpy(_data + _pos, data, size);
_pos += size;
} }
void WriteByte(Byte b) void WriteByte(Byte b)
{ {
if (_size == _pos) Byte *dest = _data;
if (dest == _dataLim)
throw 1; throw 1;
_data[_pos++] = b; *dest++ = b;
_data = dest;
} }
size_t GetPos() const { return _pos; } size_t GetPos() const { return (size_t)(_data - _dataBase); }
}; };
@ -248,14 +257,20 @@ class COutArchive
void WriteBytes(const void *data, size_t size); void WriteBytes(const void *data, size_t size);
void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }
void WriteByte(Byte b); void WriteByte(Byte b);
void WriteUInt32(UInt32 value); void WriteByte_ToStream(Byte b)
void WriteUInt64(UInt64 value); {
_outByte.WriteByte(b);
// _crc = CRC_UPDATE_BYTE(_crc, b);
}
// void WriteUInt32(UInt32 value);
// void WriteUInt64(UInt64 value);
void WriteNumber(UInt64 value); void WriteNumber(UInt64 value);
void WriteID(UInt64 value) { WriteNumber(value); } void WriteID(UInt64 value) { WriteNumber(value); }
void WriteFolder(const CFolder &folder); void WriteFolder(const CFolder &folder);
HRESULT WriteFileHeader(const CFileItem &itemInfo); HRESULT WriteFileHeader(const CFileItem &itemInfo);
void WriteBoolVector(const CBoolVector &boolVector); void Write_BoolVector(const CBoolVector &boolVector);
void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined);
void WritePropBoolVector(Byte id, const CBoolVector &boolVector); void WritePropBoolVector(Byte id, const CBoolVector &boolVector);
void WriteHashDigests(const CUInt32DefVector &digests); void WriteHashDigests(const CUInt32DefVector &digests);
@ -277,7 +292,8 @@ class COutArchive
void SkipToAligned(unsigned pos, unsigned alignShifts); void SkipToAligned(unsigned pos, unsigned alignShifts);
void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts); void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);
void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined);
void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type);
HRESULT EncodeStream( HRESULT EncodeStream(
DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS
@ -294,7 +310,7 @@ class COutArchive
#ifdef Z7_7Z_VOL #ifdef Z7_7Z_VOL
bool _endMarker; bool _endMarker;
#endif #endif
UInt32 _crc; // UInt32 _crc;
size_t _countSize; size_t _countSize;
CWriteBufferLoc _outByte2; CWriteBufferLoc _outByte2;
COutBuffer _outByte; COutBuffer _outByte;
@ -310,7 +326,7 @@ class COutArchive
public: public:
CMyComPtr<ISequentialOutStream> SeqStream; CMyComPtr<ISequentialOutStream> SeqStream;
COutArchive() { _outByte.Create(1 << 16); } // COutArchive();
HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */); HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);
void Close(); void Close();
HRESULT WriteDatabase( HRESULT WriteDatabase(

View file

@ -33,7 +33,7 @@ struct CFilterMode
UInt32 Id; UInt32 Id;
UInt32 Delta; // required File Size alignment, if Id is not k_Delta. UInt32 Delta; // required File Size alignment, if Id is not k_Delta.
// (Delta == 0) means unknown alignment // (Delta == 0) means unknown alignment
UInt32 Offset; // for k_ARM64 UInt32 Offset; // for k_ARM64 / k_RISCV
// UInt32 AlignSizeOpt; // for k_ARM64 // UInt32 AlignSizeOpt; // for k_ARM64
CFilterMode(): CFilterMode():
@ -59,7 +59,7 @@ struct CFilterMode
Delta = 16; Delta = 16;
else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC) else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC)
Delta = 4; Delta = 4;
else if (Id == k_ARMT) else if (Id == k_ARMT || Id == k_RISCV)
Delta = 2; Delta = 2;
else if (Id == k_BCJ || Id == k_BCJ2) else if (Id == k_BCJ || Id == k_BCJ2)
Delta = 1; // do we need it? Delta = 1; // do we need it?
@ -95,7 +95,9 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
return 0; return 0;
p += 4; p += 4;
switch (GetUi16(p)) const unsigned machine = GetUi16(p);
switch (machine)
{ {
case 0x014C: case 0x014C:
case 0x8664: filterId = k_X86; break; case 0x8664: filterId = k_X86; break;
@ -112,11 +114,16 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
case 0x01C2: filterId = k_ARM; break; // WinCE new case 0x01C2: filterId = k_ARM; break; // WinCE new
case 0x01C4: filterId = k_ARMT; break; // WinRT case 0x01C4: filterId = k_ARMT; break; // WinRT
case 0x5032: // RISCV32
case 0x5064: // RISCV64
// case 0x5128: // RISCV128
filterId = k_RISCV; break;
case 0x0200: filterId = k_IA64; break; case 0x0200: filterId = k_IA64; break;
default: return 0; default: return 0;
} }
// const UInt32 numSections = GetUi16(p + 2); const UInt32 numSections = GetUi16(p + 2);
optHeaderSize = GetUi16(p + 16); optHeaderSize = GetUi16(p + 16);
if (optHeaderSize > (1 << 10)) if (optHeaderSize > (1 << 10))
return 0; return 0;
@ -132,34 +139,49 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
return 0; return 0;
} }
/*
// Windows exe file sizes are not aligned for 4 KiB. // Windows exe file sizes are not aligned for 4 KiB.
// So we can't use (CFilterMode::Offset != 0) in solid archives. // So we can't use (CFilterMode::Offset != 0) in solid archives.
// So we just don't set Offset here. // So we just don't set Offset here.
#define NUM_SCAN_SECTIONS_MAX (1 << 6) #define NUM_SCAN_SECTIONS_MAX (1 << 6)
#define EXE_SECTION_OFFSET_MAX (1 << 27) // #define EXE_SECTION_OFFSET_MAX (1 << 27)
#define EXE_SECTION_SIZE_MIN (1 << 8) // #define EXE_SECTION_SIZE_MIN (1 << 8)
#define EXE_SECTION_SIZE_MAX (1 << 27) // #define EXE_SECTION_SIZE_MAX (1 << 27)
#define PE_SectHeaderSize 40 #define PE_SectHeaderSize 40
#define PE_SECT_EXECUTE 0x20000000 // #define PE_SECT_EXECUTE 0x20000000
/*
if (numSections > NUM_SCAN_SECTIONS_MAX) if (numSections > NUM_SCAN_SECTIONS_MAX)
return 0; return 0;
*/
if ((size_t)(p - buf) + optHeaderSize <= size)
{
p += optHeaderSize; p += optHeaderSize;
/*
// UInt32 numExeSections = 0; // UInt32 numExeSections = 0;
// bool execute_finded = false; // bool execute_finded = false;
// UInt32 sect_va = 0; // UInt32 sect_va = 0;
// UInt32 sect_size = 0; // UInt32 sect_size = 0;
// UInt32 sect_offset = 0; // UInt32 sect_offset = 0;
*/
if (numSections <= NUM_SCAN_SECTIONS_MAX)
if (machine == 0x8664)
for (UInt32 i = 0; i < numSections for (UInt32 i = 0; i < numSections
// && numExeSections < numSectionsMax
; i++, p += PE_SectHeaderSize) ; i++, p += PE_SectHeaderSize)
{ {
UInt32 characts, rawSize, offset; // UInt32 characts, rawSize, offset;
if ((UInt32)(p - buf) + PE_SectHeaderSize > size) if ((UInt32)(p - buf) + PE_SectHeaderSize > size)
return 0; {
// return 0;
break;
}
if (memcmp(p, ".a64xrm", 8) == 0)
{
// ARM64EC
filterId = k_ARM64;
break;
}
/*
rawSize = GetUi32(p + 16); rawSize = GetUi32(p + 16);
offset = GetUi32(p + 20); offset = GetUi32(p + 20);
characts = GetUi32(p + 36); characts = GetUi32(p + 36);
@ -178,8 +200,11 @@ static int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)
break; break;
} }
} }
*/
}
} }
/*
filterMode->Offset = 0; filterMode->Offset = 0;
if (filterId == k_ARM64) if (filterId == k_ARM64)
{ {
@ -243,8 +268,9 @@ static int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)
case 43: filterId = k_SPARC; break; case 43: filterId = k_SPARC; break;
case 20: case 20:
case 21: if (!be) return 0; filterId = k_PPC; break; case 21: if (!be) return 0; filterId = k_PPC; break;
case 40: if ( be) return 0; filterId = k_ARM; break; case 40: if (be) return 0; filterId = k_ARM; break;
case 183: if (be) return 0; filterId = k_ARM64; break; case 183: if (be) return 0; filterId = k_ARM64; break;
case 243: if (be) return 0; filterId = k_RISCV; break;
/* Some IA-64 ELF executables have size that is not aligned for 16 bytes. /* Some IA-64 ELF executables have size that is not aligned for 16 bytes.
So we don't use IA-64 filter for IA-64 ELF */ So we don't use IA-64 filter for IA-64 ELF */
@ -482,6 +508,7 @@ static inline bool IsExeFilter(CMethodId m)
switch (m) switch (m)
{ {
case k_ARM64: case k_ARM64:
case k_RISCV:
case k_BCJ: case k_BCJ:
case k_BCJ2: case k_BCJ2:
case k_ARM: case k_ARM:
@ -490,6 +517,7 @@ static inline bool IsExeFilter(CMethodId m)
case k_SPARC: case k_SPARC:
case k_IA64: case k_IA64:
return true; return true;
default: break;
} }
return false; return false;
} }
@ -521,7 +549,8 @@ static unsigned Get_FilterGroup_for_Folder(
if (m.Id == k_BCJ2) if (m.Id == k_BCJ2)
m.Id = k_BCJ; m.Id = k_BCJ;
m.SetDelta(); m.SetDelta();
if (m.Id == k_ARM64) if (m.Id == k_ARM64 ||
m.Id == k_RISCV)
if (coder.Props.Size() == 4) if (coder.Props.Size() == 4)
m.Offset = GetUi32(coder.Props); m.Offset = GetUi32(coder.Props);
} }
@ -537,15 +566,12 @@ static HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,
UInt64 position, UInt64 size, ICompressProgressInfo *progress) UInt64 position, UInt64 size, ICompressProgressInfo *progress)
{ {
RINOK(InStream_SeekSet(inStream, position)) RINOK(InStream_SeekSet(inStream, position))
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;
CMyComPtr<ISequentialInStream> inStreamLimited(streamSpec);
streamSpec->SetStream(inStream); streamSpec->SetStream(inStream);
streamSpec->Init(size); streamSpec->Init(size);
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress))
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; return (copyCoder->TotalSize == size ? S_OK : E_FAIL);
RINOK(copyCoder->Code(inStreamLimited, outStream, NULL, NULL, progress))
return (copyCoderSpec->TotalSize == size ? S_OK : E_FAIL);
} }
/* /*
@ -759,9 +785,9 @@ struct CRefItem
{ {
if (sortByType) if (sortByType)
{ {
int slashPos = ui.Name.ReverseFind_PathSepar(); const int slashPos = ui.Name.ReverseFind_PathSepar();
NamePos = (unsigned)(slashPos + 1); NamePos = (unsigned)(slashPos + 1);
int dotPos = ui.Name.ReverseFind_Dot(); const int dotPos = ui.Name.ReverseFind_Dot();
if (dotPos <= slashPos) if (dotPos <= slashPos)
ExtensionPos = ui.Name.Len(); ExtensionPos = ui.Name.Len();
else else
@ -772,7 +798,7 @@ struct CRefItem
AString s; AString s;
for (unsigned pos = ExtensionPos;; pos++) for (unsigned pos = ExtensionPos;; pos++)
{ {
wchar_t c = ui.Name[pos]; const wchar_t c = ui.Name[pos];
if (c >= 0x80) if (c >= 0x80)
break; break;
if (c == 0) if (c == 0)
@ -780,7 +806,7 @@ struct CRefItem
ExtensionIndex = GetExtIndex(s); ExtensionIndex = GetExtIndex(s);
break; break;
} }
s += (char)MyCharLower_Ascii((char)c); s.Add_Char((char)MyCharLower_Ascii((char)c));
} }
} }
} }
@ -1123,6 +1149,12 @@ HRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMo
#ifdef MY_CPU_ARM64 #ifdef MY_CPU_ARM64
filterModeTemp.Id = k_ARM64; filterModeTemp.Id = k_ARM64;
#endif #endif
#ifdef MY_CPU_RISCV
filterModeTemp.Id = k_RISCV;
#endif
#ifdef MY_CPU_SPARC
filterModeTemp.Id = k_SPARC;
#endif
parseRes = true; parseRes = true;
} }
@ -1172,6 +1204,8 @@ static inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull
m.NumStreams = numStreams; m.NumStreams = numStreams;
} }
// we add bond for mode.Methods[0] that is filter
static HRESULT AddBondForFilter(CCompressionMethodMode &mode) static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
{ {
for (unsigned c = 1; c < mode.Methods.Size(); c++) for (unsigned c = 1; c < mode.Methods.Size(); c++)
@ -1189,16 +1223,19 @@ static HRESULT AddBondForFilter(CCompressionMethodMode &mode)
return E_INVALIDARG; return E_INVALIDARG;
} }
static HRESULT AddFilterBond(CCompressionMethodMode &mode) /*
static HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode)
{ {
if (!mode.Bonds.IsEmpty()) if (!mode.Bonds.IsEmpty())
return AddBondForFilter(mode); return AddBondForFilter(mode);
return S_OK; return S_OK;
} }
*/
static HRESULT AddBcj2Methods(CCompressionMethodMode &mode) static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
{ {
// mode.Methods[0] must be k_BCJ2 method ! // mode.Methods[0] must be k_BCJ2 method !
// mode.Methods[1] : we expect that there is at least one method after BCJ2
CMethodFull m; CMethodFull m;
GetMethodFull(k_LZMA, 1, m); GetMethodFull(k_LZMA, 1, m);
@ -1210,7 +1247,7 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
m.AddProp32(NCoderPropID::kLitContextBits, 0); m.AddProp32(NCoderPropID::kLitContextBits, 0);
// m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2"); // m.AddProp_Ascii(NCoderPropID::kMatchFinder, "BT2");
unsigned methodIndex = mode.Methods.Size(); const unsigned methodIndex = mode.Methods.Size();
if (mode.Bonds.IsEmpty()) if (mode.Bonds.IsEmpty())
{ {
@ -1229,109 +1266,140 @@ static HRESULT AddBcj2Methods(CCompressionMethodMode &mode)
RINOK(AddBondForFilter(mode)) RINOK(AddBondForFilter(mode))
CBond2 bond; CBond2 bond;
bond.OutCoder = 0; bond.OutCoder = 0; // index of BCJ2 coder
bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond); bond.InCoder = methodIndex; bond.OutStream = 1; mode.Bonds.Add(bond);
bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond); bond.InCoder = methodIndex + 1; bond.OutStream = 2; mode.Bonds.Add(bond);
return S_OK; return S_OK;
} }
static HRESULT MakeExeMethod(CCompressionMethodMode &mode, static HRESULT MakeExeMethod(CCompressionMethodMode &mode,
const CFilterMode &filterMode, /* bool addFilter, */ bool bcj2Filter) const CFilterMode &filterMode,
const bool bcj2_IsAllowed,
const CUIntVector &disabledFilterIDs)
{ {
if (mode.Filter_was_Inserted) if (mode.Filter_was_Inserted)
{ {
// filter was inserted, but bond for that filter was not added still.
const CMethodFull &m = mode.Methods[0]; const CMethodFull &m = mode.Methods[0];
const CMethodId id = m.Id; if (m.Id == k_BCJ2)
if (id == k_BCJ2)
return AddBcj2Methods(mode); return AddBcj2Methods(mode);
if (!m.IsSimpleCoder()) if (!m.IsSimpleCoder())
return E_NOTIMPL; return E_NOTIMPL;
// if (Bonds.IsEmpty()) we can create bonds later if (mode.Bonds.IsEmpty())
return AddFilterBond(mode); return S_OK;
return AddBondForFilter(mode);
} }
if (filterMode.Id == 0) if (filterMode.Id == 0)
return S_OK; return S_OK;
CMethodFull &m = mode.Methods.InsertNew(0); unsigned nextCoder;
{ const bool useBcj2 = bcj2_IsAllowed
FOR_VECTOR (k, mode.Bonds) && Is86Filter(filterMode.Id)
{ && disabledFilterIDs.FindInSorted(k_BCJ2) < 0;
CBond2 &bond = mode.Bonds[k];
bond.InCoder++;
bond.OutCoder++;
}
}
HRESULT res; if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0)
if (bcj2Filter && Is86Filter(filterMode.Id))
{ {
GetMethodFull(k_BCJ2, 4, m); // required filter is disabled,
res = AddBcj2Methods(mode); // but we still can use information about data alignment.
#if 0 // 1 for debug
// we can return here, if we want default lzma properties
return S_OK;
#else
// we will try to change lzma/lzma2 properties
nextCoder = 0;
if (!mode.Bonds.IsEmpty())
for (unsigned c = 0;; c++)
{
if (c == mode.Methods.Size())
return S_OK;
if (!mode.IsThereBond_to_Coder(c))
{
nextCoder = c;
break;
}
}
#endif
} }
else else
{ {
// we insert new filter method:
CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item
{
// we move all coder indexes in bonds up for 1 position:
FOR_VECTOR (k, mode.Bonds)
{
CBond2 &bond = mode.Bonds[k];
bond.InCoder++;
bond.OutCoder++;
}
}
if (useBcj2)
{
GetMethodFull(k_BCJ2, 4, m);
return AddBcj2Methods(mode);
}
GetMethodFull(filterMode.Id, 1, m); GetMethodFull(filterMode.Id, 1, m);
if (filterMode.Id == k_Delta) if (filterMode.Id == k_Delta)
m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta); m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);
else if (filterMode.Id == k_ARM64) else if (filterMode.Id == k_ARM64
|| filterMode.Id == k_RISCV)
{ {
// if (filterMode.Offset != 0) // if (filterMode.Offset != 0)
m.AddProp32( m.AddProp32(
NCoderPropID::kDefaultProp, NCoderPropID::kDefaultProp,
// NCoderPropID::kBranchOffset, // NCoderPropID::kBranchOffset,
filterMode.Offset); filterMode.Offset);
} }
res = AddFilterBond(mode);
nextCoder = 1;
int alignBits = -1; if (!mode.Bonds.IsEmpty())
{ {
const UInt32 delta = filterMode.Delta; RINOK(AddBondForFilter(mode))
if (delta == 0 || delta > 16) nextCoder = mode.Bonds.Back().InCoder;
{
// if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
}
else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
// else alignBits = 0;
/* alignBits=0 is default mode for lzma/lzma2.
So we don't set alignBits=0 here. */
}
if (res == S_OK && alignBits > 0)
{
unsigned nextCoder = 1;
if (!mode.Bonds.IsEmpty())
{
nextCoder = mode.Bonds.Back().InCoder;
}
if (nextCoder < mode.Methods.Size())
{
CMethodFull &nextMethod = mode.Methods[nextCoder];
if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
{
if (!nextMethod.Are_Lzma_Model_Props_Defined())
{
if (alignBits != 0)
{
if (alignBits > 2 || filterMode.Id == k_Delta)
nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
unsigned lc = 0;
if (alignBits < 3)
lc = (unsigned)(3 - alignBits);
nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
}
}
}
}
} }
} }
return res; if (nextCoder >= mode.Methods.Size())
{
// we don't expect that case, if there was non-filter method.
// but we return S_OK to support filter-only case.
return S_OK;
}
int alignBits = -1;
{
const UInt32 delta = filterMode.Delta;
if (delta == 0 || delta > 16)
{
// if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);
}
else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;
else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;
else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;
else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;
// else alignBits = 0;
/* alignBits=0 is default mode for lzma/lzma2.
So we don't set alignBits=0 here. */
}
if (alignBits <= 0)
return S_OK;
// (alignBits > 0)
CMethodFull &nextMethod = mode.Methods[nextCoder];
if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)
if (!nextMethod.Are_Lzma_Model_Props_Defined())
{
if (alignBits > 2 || filterMode.Id == k_Delta)
nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);
const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u;
nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);
nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);
}
return S_OK;
} }
@ -1859,6 +1927,7 @@ HRESULT Update(
CIntArr fileIndexToUpdateIndexMap; CIntArr fileIndexToUpdateIndexMap;
UInt64 complexity = 0; UInt64 complexity = 0;
bool isThere_UnknownSize = false;
UInt64 inSizeForReduce2 = 0; UInt64 inSizeForReduce2 = 0;
#ifndef Z7_NO_CRYPTO #ifndef Z7_NO_CRYPTO
@ -1971,28 +2040,36 @@ HRESULT Update(
UInt64 inSizeForReduce = 0; UInt64 inSizeForReduce = 0;
{ {
bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0); const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);
FOR_VECTOR (i, updateItems) FOR_VECTOR (i, updateItems)
{ {
const CUpdateItem &ui = updateItems[i]; const CUpdateItem &ui = updateItems[i];
if (ui.NewData) if (ui.NewData)
{ {
complexity += ui.Size; if (ui.Size == (UInt64)(Int64)-1)
if (isSolid) isThere_UnknownSize = true;
inSizeForReduce += ui.Size; else
else if (inSizeForReduce < ui.Size) {
inSizeForReduce = ui.Size; complexity += ui.Size;
if (isSolid)
inSizeForReduce += ui.Size;
else if (inSizeForReduce < ui.Size)
inSizeForReduce = ui.Size;
}
} }
} }
} }
if (isThere_UnknownSize)
inSizeForReduce = (UInt64)(Int64)-1;
else
RINOK(updateCallback->SetTotal(complexity))
if (inSizeForReduce < inSizeForReduce2) if (inSizeForReduce < inSizeForReduce2)
inSizeForReduce = inSizeForReduce2; inSizeForReduce = inSizeForReduce2;
RINOK(updateCallback->SetTotal(complexity))
CLocalProgress *lps = new CLocalProgress; CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(updateCallback, true); lps->Init(updateCallback, true);
#ifndef Z7_ST #ifndef Z7_ST
@ -2232,12 +2309,13 @@ HRESULT Update(
CCompressionMethodMode method = *options.Method; CCompressionMethodMode method = *options.Method;
{ {
const HRESULT res = MakeExeMethod(method, filterMode, const HRESULT res = MakeExeMethod(method, filterMode,
// bcj2_IsAllowed:
#ifdef Z7_ST #ifdef Z7_ST
false false
#else #else
options.MaxFilter && options.MultiThreadMixer options.MaxFilter && options.MultiThreadMixer
#endif #endif
); , options.DisabledFilterIDs);
RINOK(res) RINOK(res)
} }
@ -2299,7 +2377,7 @@ HRESULT Update(
const UInt64 packSize = db->GetFolderFullPackSize(folderIndex); const UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
RINOK(WriteRange(inStream, archive.SeqStream, RINOK(WriteRange(inStream, archive.SeqStream,
db->GetFolderStreamPos(folderIndex, 0), packSize, progress)) db->GetFolderStreamPos(folderIndex, 0), packSize, lps))
lps->ProgressOffset += packSize; lps->ProgressOffset += packSize;
const unsigned folderIndex_New = newDatabase.Folders.Size(); const unsigned folderIndex_New = newDatabase.Folders.Size();
@ -2321,7 +2399,7 @@ HRESULT Update(
size_t indexStart = db->FoToCoderUnpackSizes[folderIndex]; size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];
const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1]; const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];
for (; indexStart < indexEnd; indexStart++) for (; indexStart < indexEnd; indexStart++)
newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes[indexStart]); newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]);
} }
else else
{ {
@ -2481,7 +2559,7 @@ HRESULT Update(
sizeToEncode, // expectedDataSize sizeToEncode, // expectedDataSize
newDatabase.Folders.AddNew(), newDatabase.Folders.AddNew(),
// newDatabase.CoderUnpackSizes, curUnpackSize, // newDatabase.CoderUnpackSizes, curUnpackSize,
archive.SeqStream, newDatabase.PackSizes, progress); archive.SeqStream, newDatabase.PackSizes, lps);
if (encodeRes == k_My_HRESULT_CRC_ERROR) if (encodeRes == k_My_HRESULT_CRC_ERROR)
return E_FAIL; return E_FAIL;
@ -2680,8 +2758,7 @@ HRESULT Update(
*/ */
CFolderInStream *inStreamSpec = new CFolderInStream; CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream;
CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
// inStreamSpec->_reportArcProp = reportArcProp; // inStreamSpec->_reportArcProp = reportArcProp;
@ -2702,13 +2779,13 @@ HRESULT Update(
RINOK(encoder.Encode1( RINOK(encoder.Encode1(
EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS
solidInStream, inStreamSpec,
// NULL, // NULL,
&inSizeForReduce, &inSizeForReduce,
expectedDataSize, // expected size expectedDataSize, // expected size
newDatabase.Folders.AddNew(), newDatabase.Folders.AddNew(),
// newDatabase.CoderUnpackSizes, curFolderUnpackSize, // newDatabase.CoderUnpackSizes, curFolderUnpackSize,
archive.SeqStream, newDatabase.PackSizes, progress)) archive.SeqStream, newDatabase.PackSizes, lps))
if (!inStreamSpec->WasFinished()) if (!inStreamSpec->WasFinished())
return E_FAIL; return E_FAIL;
@ -2970,7 +3047,7 @@ HRESULT Update(
if (newDatabase.NumUnpackStreamsVector.Size() != numFolders if (newDatabase.NumUnpackStreamsVector.Size() != numFolders
|| newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders) || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders)
return E_FAIL; return E_FAIL;
newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResedue_with_false(numFolders); newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders);
} }
updateItems.ClearAndFree(); updateItems.ClearAndFree();

View file

@ -111,6 +111,25 @@ struct CUpdateOptions
CHeaderOptions HeaderOptions; CHeaderOptions HeaderOptions;
CUIntVector DisabledFilterIDs;
void Add_DisabledFilter_for_id(UInt32 id,
const CUIntVector &enabledFilters)
{
if (enabledFilters.FindInSorted(id) < 0)
DisabledFilterIDs.AddToUniqueSorted(id);
}
void SetFilterSupporting_ver_enabled_disabled(
UInt32 compatVer,
const CUIntVector &enabledFilters,
const CUIntVector &disabledFilters)
{
DisabledFilterIDs = disabledFilters;
if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters);
if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters);
}
CUpdateOptions(): CUpdateOptions():
Method(NULL), Method(NULL),
HeaderMethod(NULL), HeaderMethod(NULL),
@ -128,7 +147,9 @@ struct CUpdateOptions
Need_MTime(false), Need_MTime(false),
Need_Attrib(false) Need_Attrib(false)
// , Need_Crc(true) // , Need_Crc(true)
{} {
DisabledFilterIDs.Add(k_RISCV);
}
}; };
HRESULT Update( HRESULT Update(

View file

@ -54,31 +54,18 @@
namespace NArchive { namespace NArchive {
namespace NApfs { namespace NApfs {
#define ValToHex(t) ((char)(((t) < 10) ? ('0' + (t)) : ('a' + ((t) - 10))))
static void ConvertByteToHex(unsigned val, char *s)
{
unsigned t;
t = val >> 4;
s[0] = ValToHex(t);
t = val & 0xF;
s[1] = ValToHex(t);
}
struct CUuid struct CUuid
{ {
Byte Data[16]; Byte Data[16];
void SetHex_To_str(char *s) const void SetHex_To_str(char *s) const
{ {
for (unsigned i = 0; i < 16; i++) ConvertDataToHex_Lower(s, Data, sizeof(Data));
ConvertByteToHex(Data[i], s + i * 2);
s[32] = 0;
} }
void AddHexToString(UString &dest) const void AddHexToString(UString &dest) const
{ {
char temp[32 + 4]; char temp[sizeof(Data) * 2 + 4];
SetHex_To_str(temp); SetHex_To_str(temp);
dest += temp; dest += temp;
} }
@ -2151,7 +2138,7 @@ HRESULT CDatabase::ReadMap(UInt64 oid, bool noHeader,
if (bti.Is_NOHEADER() != noHeader) if (bti.Is_NOHEADER() != noHeader)
return S_FALSE; return S_FALSE;
// we don't allow volumes with big number of Keys // we don't allow volumes with big number of Keys
const UInt32 kNumItemsMax = k_VectorSizeMax; const unsigned kNumItemsMax = k_VectorSizeMax;
if (map.bti.node_count > kNumItemsMax) if (map.bti.node_count > kNumItemsMax)
return S_FALSE; return S_FALSE;
if (map.bti.key_count > kNumItemsMax) if (map.bti.key_count > kNumItemsMax)
@ -3759,7 +3746,7 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::
#ifdef APFS_SHOW_ALT_STREAMS #ifdef APFS_SHOW_ALT_STREAMS
if (IsViDef(ref.AttrIndex) && inode) if (IsViDef(ref.AttrIndex) && inode)
{ {
s += ':'; s.Add_Colon();
Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2); Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2);
// s2 += "a\\b"; // for debug // s2 += "a\\b"; // for debug
s += s2; s += s2;
@ -4094,7 +4081,6 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (numItems == 0) if (numItems == 0)
return S_OK; return S_OK;
UInt32 i; UInt32 i;
{ {
UInt64 totalSize = 0; UInt64 totalSize = 0;
for (i = 0; i < numItems; i++) for (i = 0; i < numItems; i++)
@ -4107,14 +4093,15 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 currentTotalSize = 0, currentItemSize = 0; UInt64 currentTotalSize = 0, currentItemSize = 0;
CLocalProgress *lps = new CLocalProgress; CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
NHfs::CDecoder decoder; // We don't know if zlib without Adler is allowed in APFS.
// But zlib without Adler is allowed in HFS.
// So here we allow apfs/zlib without Adler:
NHfs::CDecoder decoder(true); // IsAdlerOptional
for (i = 0;; i++, currentTotalSize += currentItemSize) for (i = 0;; i++, currentTotalSize += currentItemSize)
{ {
@ -4131,8 +4118,9 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
currentItemSize = GetSize(index); currentItemSize = GetSize(index);
int opRes;
{
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
const Int32 askMode = testMode ? const Int32 askMode = testMode ?
NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract; NExtract::NAskMode::kExtract;
@ -4165,7 +4153,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
if (!testMode && !realOutStream) if (!testMode && !realOutStream)
continue; continue;
RINOK(extractCallback->PrepareOperation(askMode)) RINOK(extractCallback->PrepareOperation(askMode))
int opRes = NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
if (IsViDef(ref.NodeIndex)) if (IsViDef(ref.NodeIndex))
{ {
@ -4221,38 +4209,38 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
CMyComPtr<ISequentialInStream> inStream; CMyComPtr<ISequentialInStream> inStream;
if (GetStream(index, &inStream) == S_OK && inStream) if (GetStream(index, &inStream) == S_OK && inStream)
{ {
COutStreamWithHash *hashStreamSpec = NULL; CMyComPtr2<ISequentialOutStream, COutStreamWithHash> hashStream;
CMyComPtr<ISequentialOutStream> hashStream;
if (vol.integrity.Is_SHA256()) if (vol.integrity.Is_SHA256())
{ {
const int hashIndex = FindHashIndex_for_Item(index); const int hashIndex = FindHashIndex_for_Item(index);
if (hashIndex != -1) if (hashIndex != -1)
{ {
hashStreamSpec = new COutStreamWithHash; hashStream.Create_if_Empty();
hashStream = hashStreamSpec; hashStream->SetStream(realOutStream);
hashStreamSpec->SetStream(realOutStream); hashStream->Init(&(vol.Hash_Vectors[(unsigned)hashIndex]), sb.block_size_Log);
hashStreamSpec->Init(&(vol.Hash_Vectors[(unsigned)hashIndex]), sb.block_size_Log);
} }
} }
RINOK(copyCoder->Code(inStream, RINOK(copyCoder.Interface()->Code(inStream,
hashStream ? hashStream : realOutStream, NULL, NULL, progress)) hashStream.IsDefined() ?
hashStream.Interface() :
realOutStream.Interface(),
NULL, NULL, lps))
opRes = NExtract::NOperationResult::kDataError; opRes = NExtract::NOperationResult::kDataError;
if (copyCoderSpec->TotalSize == currentItemSize) if (copyCoder->TotalSize == currentItemSize)
{ {
opRes = NExtract::NOperationResult::kOK; opRes = NExtract::NOperationResult::kOK;
if (hashStream) if (hashStream.IsDefined())
if (!hashStreamSpec->FinalCheck()) if (!hashStream->FinalCheck())
opRes = NExtract::NOperationResult::kCRCError; opRes = NExtract::NOperationResult::kCRCError;
} }
else if (copyCoderSpec->TotalSize < currentItemSize) else if (copyCoder->TotalSize < currentItemSize)
opRes = NExtract::NOperationResult::kUnexpectedEnd; opRes = NExtract::NOperationResult::kUnexpectedEnd;
} }
} }
} }
}
realOutStream.Release();
RINOK(extractCallback->SetOperationResult(opRes)) RINOK(extractCallback->SetOperationResult(opRes))
} }
return S_OK; return S_OK;
@ -4340,9 +4328,9 @@ Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
const CAttr &attr = inode.Attrs[(unsigned)attrIndex]; const CAttr &attr = inode.Attrs[(unsigned)attrIndex];
if (!attr.dstream_defined) if (!attr.dstream_defined)
{ {
CBufInStream *streamSpec = new CBufInStream; CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec; streamTemp.Create_if_Empty();
streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);
*stream = streamTemp.Detach(); *stream = streamTemp.Detach();
return S_OK; return S_OK;
} }
@ -4392,9 +4380,9 @@ HRESULT CDatabase::GetAttrStream(IInStream *apfsInStream, const CVol &vol,
*stream = NULL; *stream = NULL;
if (!attr.dstream_defined) if (!attr.dstream_defined)
{ {
CBufInStream *streamSpec = new CBufInStream; CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec; streamTemp.Create_if_Empty();
streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this); streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);
*stream = streamTemp.Detach(); *stream = streamTemp.Detach();
return S_OK; return S_OK;
} }
@ -4427,8 +4415,8 @@ HRESULT CDatabase::GetStream2(
const CRecordVector<CExtent> *extents, UInt64 rem, const CRecordVector<CExtent> *extents, UInt64 rem,
ISequentialInStream **stream) ISequentialInStream **stream)
{ {
CExtentsStream *extentStreamSpec = new CExtentsStream(); CMyComPtr2<ISequentialInStream, CExtentsStream> extentStream;
CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec; extentStream.Create_if_Empty();
UInt64 virt = 0; UInt64 virt = 0;
FOR_VECTOR (i, *extents) FOR_VECTOR (i, *extents)
@ -4452,7 +4440,7 @@ HRESULT CDatabase::GetStream2(
se.Virt = virt; se.Virt = virt;
virt += cur; virt += cur;
rem -= cur; rem -= cur;
extentStreamSpec->Extents.Add(se); extentStream->Extents.Add(se);
if (rem == 0) if (rem == 0)
if (i != extents->Size() - 1) if (i != extents->Size() - 1)
return S_FALSE; return S_FALSE;
@ -4464,9 +4452,9 @@ HRESULT CDatabase::GetStream2(
CSeekExtent se; CSeekExtent se;
se.Phy = 0; se.Phy = 0;
se.Virt = virt; se.Virt = virt;
extentStreamSpec->Extents.Add(se); extentStream->Extents.Add(se);
extentStreamSpec->Stream = apfsInStream; extentStream->Stream = apfsInStream;
extentStreamSpec->Init(); extentStream->Init();
*stream = extentStream.Detach(); *stream = extentStream.Detach();
return S_OK; return S_OK;
} }

View file

@ -5,36 +5,64 @@
#include "../../../C/CpuArch.h" #include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/Defs.h"
#include "../../Windows/PropVariant.h" #include "../../Windows/PropVariant.h"
#include "../../Windows/PropVariantUtils.h"
#include "../Common/RegisterArc.h" #include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h" #include "../Common/StreamUtils.h"
#include "HandlerCont.h" #include "HandlerCont.h"
#define Get16(p) GetBe16(p) // #define Get16(p) GetBe16(p)
#define Get32(p) GetBe32(p) #define Get32(p) GetBe32(p)
using namespace NWindows; using namespace NWindows;
namespace NArchive { namespace NArchive {
namespace NDmg {
const char *Find_Apple_FS_Ext(const AString &name);
bool Is_Apple_FS_Or_Unknown(const AString &name);
}
namespace NApm { namespace NApm {
static const Byte kSig0 = 'E'; static const Byte kSig0 = 'E';
static const Byte kSig1 = 'R'; static const Byte kSig1 = 'R';
static const CUInt32PCharPair k_Flags[] =
{
{ 0, "VALID" },
{ 1, "ALLOCATED" },
{ 2, "IN_USE" },
{ 3, "BOOTABLE" },
{ 4, "READABLE" },
{ 5, "WRITABLE" },
{ 6, "OS_PIC_CODE" },
// { 7, "OS_SPECIFIC_2" }, // "Unused"
// { 8, "ChainCompatible" }, // "OS_SPECIFIC_1"
// { 9, "RealDeviceDriver" },
// { 10, "CanChainToNext" },
{ 30, "MOUNTED_AT_STARTUP" },
{ 31, "STARTUP" }
};
#define DPME_FLAGS_VALID (1u << 0)
#define DPME_FLAGS_ALLOCATED (1u << 1)
static const unsigned k_Str_Size = 32;
struct CItem struct CItem
{ {
UInt32 StartBlock; UInt32 StartBlock;
UInt32 NumBlocks; UInt32 NumBlocks;
char Name[32]; UInt32 Flags; // pmPartStatus
char Type[32]; char Name[k_Str_Size];
char Type[k_Str_Size];
/* /*
UInt32 DataStartBlock; UInt32 DataStartBlock;
UInt32 NumDataBlocks; UInt32 NumDataBlocks;
UInt32 Status;
UInt32 BootStartBlock; UInt32 BootStartBlock;
UInt32 BootSize; UInt32 BootSize;
UInt32 BootAddr; UInt32 BootAddr;
@ -43,25 +71,28 @@ struct CItem
char Processor[16]; char Processor[16];
*/ */
bool Is_Valid_and_Allocated() const
{ return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }
bool Parse(const Byte *p, UInt32 &numBlocksInMap) bool Parse(const Byte *p, UInt32 &numBlocksInMap)
{ {
numBlocksInMap = Get32(p + 4); numBlocksInMap = Get32(p + 4);
StartBlock = Get32(p + 8); StartBlock = Get32(p + 8);
NumBlocks = Get32(p + 0xC); NumBlocks = Get32(p + 0xc);
memcpy(Name, p + 0x10, 32); Flags = Get32(p + 0x58);
memcpy(Type, p + 0x30, 32); memcpy(Name, p + 0x10, k_Str_Size);
if (p[0] != 0x50 || p[1] != 0x4D || p[2] != 0 || p[3] != 0) memcpy(Type, p + 0x30, k_Str_Size);
if (GetUi32(p) != 0x4d50) // "PM"
return false; return false;
/* /*
DataStartBlock = Get32(p + 0x50); DataStartBlock = Get32(p + 0x50);
NumDataBlocks = Get32(p + 0x54); NumDataBlocks = Get32(p + 0x54);
Status = Get32(p + 0x58); BootStartBlock = Get32(p + 0x5c);
BootStartBlock = Get32(p + 0x5C);
BootSize = Get32(p + 0x60); BootSize = Get32(p + 0x60);
BootAddr = Get32(p + 0x64); BootAddr = Get32(p + 0x64);
if (Get32(p + 0x68) != 0) if (Get32(p + 0x68) != 0)
return false; return false;
BootEntry = Get32(p + 0x6C); BootEntry = Get32(p + 0x6c);
if (Get32(p + 0x70) != 0) if (Get32(p + 0x70) != 0)
return false; return false;
BootChecksum = Get32(p + 0x74); BootChecksum = Get32(p + 0x74);
@ -71,6 +102,7 @@ struct CItem
} }
}; };
Z7_class_CHandler_final: public CHandlerCont Z7_class_CHandler_final: public CHandlerCont
{ {
Z7_IFACE_COM7_IMP(IInArchive_Cont) Z7_IFACE_COM7_IMP(IInArchive_Cont)
@ -81,7 +113,6 @@ Z7_class_CHandler_final: public CHandlerCont
UInt64 _phySize; UInt64 _phySize;
bool _isArc; bool _isArc;
HRESULT ReadTables(IInStream *stream);
UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; } UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
@ -95,47 +126,58 @@ Z7_class_CHandler_final: public CHandlerCont
static const UInt32 kSectorSize = 512; static const UInt32 kSectorSize = 512;
// we support only 4 cluster sizes: 512, 1024, 2048, 4096 */
API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size) API_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)
{ {
if (size < kSectorSize) if (size < kSectorSize)
return k_IsArc_Res_NEED_MORE; return k_IsArc_Res_NEED_MORE;
if (p[0] != kSig0 || p[1] != kSig1) if (GetUi64(p + 8) != 0)
return k_IsArc_Res_NO; return k_IsArc_Res_NO;
unsigned i; UInt32 v = GetUi32(p); // we read as little-endian
for (i = 8; i < 16; i++) v ^= (kSig0 | (unsigned)kSig1 << 8);
if (p[i] != 0) if ((v & ~((UInt32)0xf << 17)))
return k_IsArc_Res_NO; return k_IsArc_Res_NO;
UInt32 blockSize = Get16(p + 2); if ((0x116u >> (v >> 17)) & 1)
for (i = 9; ((UInt32)1 << i) != blockSize; i++) return k_IsArc_Res_YES;
if (i >= 12) return k_IsArc_Res_NO;
return k_IsArc_Res_NO;
return k_IsArc_Res_YES;
} }
} }
HRESULT CHandler::ReadTables(IInStream *stream) Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
{ {
COM_TRY_BEGIN
Close();
Byte buf[kSectorSize]; Byte buf[kSectorSize];
unsigned numSectors_in_Cluster;
{ {
RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
if (buf[0] != kSig0 || buf[1] != kSig1) if (GetUi64(buf + 8) != 0)
return S_FALSE; return S_FALSE;
UInt32 blockSize = Get16(buf + 2); UInt32 v = GetUi32(buf); // we read as little-endian
unsigned i; v ^= (kSig0 | (unsigned)kSig1 << 8);
for (i = 9; ((UInt32)1 << i) != blockSize; i++) if ((v & ~((UInt32)0xf << 17)))
if (i >= 12) return S_FALSE;
return S_FALSE; v >>= 16;
_blockSizeLog = i; if (v == 0)
_numBlocks = Get32(buf + 4); return S_FALSE;
for (i = 8; i < 16; i++) if (v & (v - 1))
if (buf[i] != 0) return S_FALSE;
return S_FALSE; const unsigned a = (0x30210u >> v) & 3;
// a = 0; // for debug
numSectors_in_Cluster = 1u << a;
_blockSizeLog = 9 + a;
} }
unsigned numSkips = (unsigned)1 << (_blockSizeLog - 9); UInt32 numBlocks = Get32(buf + 4);
for (unsigned j = 1; j < numSkips; j++) _numBlocks = numBlocks;
{ {
RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) for (unsigned k = numSectors_in_Cluster; --k != 0;)
{
RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
}
} }
UInt32 numBlocksInMap = 0; UInt32 numBlocksInMap = 0;
@ -152,19 +194,20 @@ HRESULT CHandler::ReadTables(IInStream *stream)
if (i == 0) if (i == 0)
{ {
numBlocksInMap = numBlocksInMap2; numBlocksInMap = numBlocksInMap2;
if (numBlocksInMap > (1 << 8)) if (numBlocksInMap > (1 << 8) || numBlocksInMap == 0)
return S_FALSE; return S_FALSE;
} }
else if (numBlocksInMap2 != numBlocksInMap) else if (numBlocksInMap2 != numBlocksInMap)
return S_FALSE; return S_FALSE;
UInt32 finish = item.StartBlock + item.NumBlocks; const UInt32 finish = item.StartBlock + item.NumBlocks;
if (finish < item.StartBlock) if (finish < item.StartBlock)
return S_FALSE; return S_FALSE;
_numBlocks = MyMax(_numBlocks, finish); if (numBlocks < finish)
numBlocks = finish;
_items.Add(item); _items.Add(item);
for (unsigned j = 1; j < numSkips; j++) for (unsigned k = numSectors_in_Cluster; --k != 0;)
{ {
RINOK(ReadStream_FALSE(stream, buf, kSectorSize)) RINOK(ReadStream_FALSE(stream, buf, kSectorSize))
} }
@ -172,21 +215,15 @@ HRESULT CHandler::ReadTables(IInStream *stream)
break; break;
} }
_phySize = BlocksToBytes(_numBlocks); _phySize = BlocksToBytes(numBlocks);
_isArc = true; _isArc = true;
return S_OK;
}
Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))
{
COM_TRY_BEGIN
Close();
RINOK(ReadTables(stream))
_stream = stream; _stream = stream;
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END
} }
Z7_COM7F_IMF(CHandler::Close()) Z7_COM7F_IMF(CHandler::Close())
{ {
_isArc = false; _isArc = false;
@ -196,16 +233,19 @@ Z7_COM7F_IMF(CHandler::Close())
return S_OK; return S_OK;
} }
static const Byte kProps[] = static const Byte kProps[] =
{ {
kpidPath, kpidPath,
kpidSize, kpidSize,
kpidOffset kpidOffset,
kpidCharacts
}; };
static const Byte kArcProps[] = static const Byte kArcProps[] =
{ {
kpidClusterSize kpidClusterSize,
kpidNumBlocks
}; };
IMP_IInArchive_Props IMP_IInArchive_Props
@ -214,8 +254,7 @@ IMP_IInArchive_ArcProps
static AString GetString(const char *s) static AString GetString(const char *s)
{ {
AString res; AString res;
for (unsigned i = 0; i < 32 && s[i] != 0; i++) res.SetFrom_CalcLen(s, k_Str_Size);
res += s[i];
return res; return res;
} }
@ -230,11 +269,13 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
int mainIndex = -1; int mainIndex = -1;
FOR_VECTOR (i, _items) FOR_VECTOR (i, _items)
{ {
AString s (GetString(_items[i].Type)); const CItem &item = _items[i];
if (s != "Apple_Free" && if (!item.Is_Valid_and_Allocated())
s != "Apple_partition_map") continue;
AString s (GetString(item.Type));
if (NDmg::Is_Apple_FS_Or_Unknown(s))
{ {
if (mainIndex >= 0) if (mainIndex != -1)
{ {
mainIndex = -1; mainIndex = -1;
break; break;
@ -242,12 +283,13 @@ Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
mainIndex = (int)i; mainIndex = (int)i;
} }
} }
if (mainIndex >= 0) if (mainIndex != -1)
prop = (UInt32)(Int32)mainIndex; prop = (UInt32)(Int32)mainIndex;
break; break;
} }
case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break; case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;
case kpidPhySize: prop = _phySize; break; case kpidPhySize: prop = _phySize; break;
case kpidNumBlocks: prop = _numBlocks; break;
case kpidErrorFlags: case kpidErrorFlags:
{ {
@ -281,8 +323,11 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (s.IsEmpty()) if (s.IsEmpty())
s.Add_UInt32(index); s.Add_UInt32(index);
AString type (GetString(item.Type)); AString type (GetString(item.Type));
if (type == "Apple_HFS") {
type = "hfs"; const char *ext = NDmg::Find_Apple_FS_Ext(type);
if (ext)
type = ext;
}
if (!type.IsEmpty()) if (!type.IsEmpty())
{ {
s.Add_Dot(); s.Add_Dot();
@ -296,6 +341,7 @@ Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
prop = BlocksToBytes(item.NumBlocks); prop = BlocksToBytes(item.NumBlocks);
break; break;
case kpidOffset: prop = BlocksToBytes(item.StartBlock); break; case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;
case kpidCharacts: FLAGS_TO_PROP(k_Flags, item.Flags, prop); break;
} }
prop.Detach(value); prop.Detach(value);
return S_OK; return S_OK;

View file

@ -274,18 +274,18 @@ HRESULT CInArchive::GetNextItem(CItem &item, bool &filled)
Z7_CLASS_IMP_CHandler_IInArchive_1( Z7_CLASS_IMP_CHandler_IInArchive_1(
IInArchiveGetStream IInArchiveGetStream
) )
bool _isArc;
CObjectVector<CItem> _items; CObjectVector<CItem> _items;
CMyComPtr<IInStream> _stream; CMyComPtr<IInStream> _stream;
Int32 _mainSubfile;
UInt64 _phySize; UInt64 _phySize;
Int32 _mainSubfile;
EType _type; EType _type;
ESubType _subType; ESubType _subType;
int _longNames_FileIndex; int _longNames_FileIndex;
AString _libFiles[2];
unsigned _numLibFiles; unsigned _numLibFiles;
AString _errorMessage; AString _errorMessage;
bool _isArc; AString _libFiles[2];
void UpdateErrorMessage(const char *s); void UpdateErrorMessage(const char *s);
@ -299,7 +299,7 @@ Z7_CLASS_IMP_CHandler_IInArchive_1(
void CHandler::UpdateErrorMessage(const char *s) void CHandler::UpdateErrorMessage(const char *s)
{ {
if (!_errorMessage.IsEmpty()) if (!_errorMessage.IsEmpty())
_errorMessage += '\n'; _errorMessage.Add_LF();
_errorMessage += s; _errorMessage += s;
} }
@ -437,8 +437,8 @@ HRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &
s.DeleteBack(); s.DeleteBack();
s += " "; s += " ";
s += (const char *)(data + pos); s += (const char *)(data + pos);
s += (char)0xD; // s.Add_Char((char)0xD);
s += (char)0xA; s.Add_LF();
pos = i; pos = i;
return S_OK; return S_OK;
} }
@ -473,7 +473,7 @@ HRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex)
if (size - pos < tableSize || (tableSize & 7) != 0) if (size - pos < tableSize || (tableSize & 7) != 0)
continue; continue;
size_t namesStart = pos + tableSize; size_t namesStart = pos + tableSize;
const UInt32 namesSize = Get32(p + namesStart, be); const UInt32 namesSize = Get32(p.ConstData() + namesStart, be);
namesStart += 4; namesStart += 4;
if (namesStart > size || namesStart + namesSize != size) if (namesStart > size || namesStart + namesSize != size)
continue; continue;
@ -582,7 +582,7 @@ Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
arc.SkipData(item.Size); arc.SkipData(item.Size);
if (callback && (_items.Size() & 0xFF) == 0) if (callback && (_items.Size() & 0xFF) == 0)
{ {
UInt64 numFiles = _items.Size(); const UInt64 numFiles = _items.Size();
RINOK(callback->SetCompleted(&numFiles, &arc.Position)) RINOK(callback->SetCompleted(&numFiles, &arc.Position))
} }
} }
@ -762,21 +762,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
UInt64 currentTotalSize = 0; UInt64 currentTotalSize = 0;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec); inStream->SetStream(_stream);
streamSpec->SetStream(_stream);
for (i = 0; i < numItems; i++) for (i = 0;; i++)
{ {
lps->InSize = lps->OutSize = currentTotalSize; lps->InSize = lps->OutSize = currentTotalSize;
RINOK(lps->SetCur()) RINOK(lps->SetCur())
if (i >= numItems)
break;
Int32 opRes;
{
CMyComPtr<ISequentialOutStream> realOutStream; CMyComPtr<ISequentialOutStream> realOutStream;
const Int32 askMode = testMode ? const Int32 askMode = testMode ?
NExtract::NAskMode::kTest : NExtract::NAskMode::kTest :
@ -795,7 +795,7 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
continue; continue;
} }
bool isOk = true; opRes = NExtract::NOperationResult::kOK;
if (item.TextFileIndex >= 0) if (item.TextFileIndex >= 0)
{ {
const AString &f = _libFiles[(unsigned)item.TextFileIndex]; const AString &f = _libFiles[(unsigned)item.TextFileIndex];
@ -805,14 +805,13 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else else
{ {
RINOK(InStream_SeekSet(_stream, item.GetDataPos())) RINOK(InStream_SeekSet(_stream, item.GetDataPos()))
streamSpec->Init(item.Size); inStream->Init(item.Size);
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)) RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
isOk = (copyCoderSpec->TotalSize == item.Size); if (copyCoder->TotalSize != item.Size)
opRes = NExtract::NOperationResult::kDataError;
} }
realOutStream.Release(); }
RINOK(extractCallback->SetOperationResult(isOk ? RINOK(extractCallback->SetOperationResult(opRes))
NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kDataError))
} }
return S_OK; return S_OK;
COM_TRY_END COM_TRY_END

View file

@ -4,6 +4,7 @@
#include "../../../C/CpuArch.h" #include "../../../C/CpuArch.h"
#include "../../Common/AutoPtr.h"
#include "../../Common/ComTry.h" #include "../../Common/ComTry.h"
#include "../../Common/StringConvert.h" #include "../../Common/StringConvert.h"
@ -28,16 +29,13 @@ namespace NArj {
namespace NDecoder { namespace NDecoder {
static const unsigned kMatchMinLen = 3; static const unsigned kMatchMinLen = 3;
static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14) static const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)
class CCoder
Z7_CLASS_IMP_NOQIB_1( {
CCoder
, ICompressCoder
)
CLzOutWindow _outWindow; CLzOutWindow _outWindow;
NBitm::CDecoder<CInBuffer> _inBitStream; NBitm::CDecoder<CInBuffer> _inBitStream;
// bool FinishMode;
class CCoderReleaser class CCoderReleaser
{ {
@ -49,19 +47,20 @@ Z7_CLASS_IMP_NOQIB_1(
}; };
friend class CCoderReleaser; friend class CCoderReleaser;
HRESULT CodeReal(UInt64 outSize, ICompressProgressInfo *progress); HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);
public: public:
bool FinishMode;
CCoder(): FinishMode(false) {} // CCoder(): FinishMode(true) {}
UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); } UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }
HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
UInt32 outSize, ICompressProgressInfo *progress);
}; };
HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress) HRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)
{ {
const UInt32 kStep = 1 << 20; const UInt32 kStep = 1 << 20;
UInt64 next = 0; UInt32 next = 0;
if (rem > kStep && progress) if (rem > kStep && progress)
next = rem - kStep; next = rem - kStep;
@ -71,9 +70,8 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
{ {
if (_inBitStream.ExtraBitsWereRead()) if (_inBitStream.ExtraBitsWereRead())
return S_FALSE; return S_FALSE;
const UInt64 packSize = _inBitStream.GetProcessedSize();
UInt64 packSize = _inBitStream.GetProcessedSize(); const UInt64 pos = _outWindow.GetProcessedSize();
UInt64 pos = _outWindow.GetProcessedSize();
RINOK(progress->SetRatioInfo(&packSize, &pos)) RINOK(progress->SetRatioInfo(&packSize, &pos))
next = 0; next = 0;
if (rem > kStep) if (rem > kStep)
@ -81,12 +79,11 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
} }
UInt32 len; UInt32 len;
{ {
const unsigned kNumBits = 7 + 7; const unsigned kNumBits = 7 + 7;
UInt32 val = _inBitStream.GetValue(kNumBits); const UInt32 val = _inBitStream.GetValue(kNumBits);
if ((val & (1 << (kNumBits - 1))) == 0) if ((val & (1u << (kNumBits - 1))) == 0)
{ {
_outWindow.PutByte((Byte)(val >> 5)); _outWindow.PutByte((Byte)(val >> 5));
_inBitStream.MovePos(1 + 8); _inBitStream.MovePos(1 + 8);
@ -94,27 +91,24 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
continue; continue;
} }
UInt32 mask = 1 << (kNumBits - 2);
unsigned w; unsigned w;
{
for (w = 1; w < 7; w++, mask >>= 1) UInt32 flag = (UInt32)1 << (kNumBits - 2);
if ((val & mask) == 0) for (w = 1; w < 7; w++, flag >>= 1)
break; if ((val & flag) == 0)
break;
unsigned readBits = (w != 7 ? 1 : 0); }
readBits += w + w; const unsigned readBits = (w != 7 ? 1 : 0) + w * 2;
len = (1 << w) - 1 + kMatchMinLen - 1 + const UInt32 mask = ((UInt32)1 << w) - 1;
(((val >> (kNumBits - readBits)) & ((1 << w) - 1))); len = mask + kMatchMinLen - 1 +
((val >> (kNumBits - readBits)) & mask);
_inBitStream.MovePos(readBits); _inBitStream.MovePos(readBits);
} }
{ {
const unsigned kNumBits = 4 + 13; const unsigned kNumBits = 4 + 13;
UInt32 val = _inBitStream.GetValue(kNumBits); const UInt32 val = _inBitStream.GetValue(kNumBits);
unsigned readBits = 1; unsigned readBits = 1;
unsigned w; unsigned w;
if ((val & ((UInt32)1 << 16)) == 0) w = 9; if ((val & ((UInt32)1 << 16)) == 0) w = 9;
else if ((val & ((UInt32)1 << 15)) == 0) w = 10; else if ((val & ((UInt32)1 << 15)) == 0) w = 10;
else if ((val & ((UInt32)1 << 14)) == 0) w = 11; else if ((val & ((UInt32)1 << 14)) == 0) w = 11;
@ -122,61 +116,50 @@ HRESULT CCoder::CodeReal(UInt64 rem, ICompressProgressInfo *progress)
else { w = 13; readBits = 0; } else { w = 13; readBits = 0; }
readBits += w + w - 9; readBits += w + w - 9;
const UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
UInt32 dist = ((UInt32)1 << w) - (1 << 9) +
(((val >> (kNumBits - readBits)) & ((1 << w) - 1))); (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));
_inBitStream.MovePos(readBits); _inBitStream.MovePos(readBits);
if (len > rem) if (len > rem)
len = (UInt32)rem; {
// if (FinishMode)
return S_FALSE;
// else len = (UInt32)rem;
}
if (!_outWindow.CopyBlock(dist, len)) if (!_outWindow.CopyBlock(dist, len))
return S_FALSE; return S_FALSE;
rem -= len; rem -= len;
} }
} }
if (FinishMode) // if (FinishMode)
{ {
if (_inBitStream.ReadAlignBits() != 0) if (_inBitStream.ReadAlignBits() != 0)
return S_FALSE; return S_FALSE;
} }
if (_inBitStream.ExtraBitsWereRead()) if (_inBitStream.ExtraBitsWereRead())
return S_FALSE; return S_FALSE;
return S_OK; return S_OK;
} }
HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
Z7_COM7F_IMF(CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt32 outSize, ICompressProgressInfo *progress)
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))
{ {
try try
{ {
if (!outSize)
return E_INVALIDARG;
if (!_outWindow.Create(kWindowSize)) if (!_outWindow.Create(kWindowSize))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if (!_inBitStream.Create(1 << 17)) if (!_inBitStream.Create(1 << 17))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
_outWindow.SetStream(outStream); _outWindow.SetStream(outStream);
_outWindow.Init(false); _outWindow.Init(false);
_inBitStream.SetStream(inStream); _inBitStream.SetStream(inStream);
_inBitStream.Init(); _inBitStream.Init();
CCoderReleaser coderReleaser(this);
HRESULT res;
{ {
res = CodeReal(*outSize, progress); CCoderReleaser coderReleaser(this);
if (res != S_OK) RINOK(CodeReal(outSize, progress))
return res; coderReleaser.Disable();
} }
coderReleaser.Disable();
return _outWindow.Flush(); return _outWindow.Flush();
} }
catch(const CInBufferException &e) { return e.ErrorCode; } catch(const CInBufferException &e) { return e.ErrorCode; }
@ -858,74 +841,70 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
totalUnpacked += item.Size; totalUnpacked += item.Size;
// totalPacked += item.PackSize; // totalPacked += item.PackSize;
} }
extractCallback->SetTotal(totalUnpacked); RINOK(extractCallback->SetTotal(totalUnpacked))
totalUnpacked = totalPacked = 0; totalUnpacked = totalPacked = 0;
UInt64 curUnpacked, curPacked; UInt32 curUnpacked, curPacked;
NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = NULL; CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
CMyComPtr<ICompressCoder> lzhDecoder;
NCompress::NArj::NDecoder::CCoder *arjDecoderSpec = NULL;
CMyComPtr<ICompressCoder> arjDecoder;
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
CLocalProgress *lps = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = lps;
lps->Init(extractCallback, false); lps->Init(extractCallback, false);
CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
CMyUniquePtr<NCompress::NArj::NDecoder::CCoder> arjDecoder;
CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;
inStream->SetStream(_stream);
CLimitedSequentialInStream *inStreamSpec = new CLimitedSequentialInStream; for (i = 0;; i++,
CMyComPtr<ISequentialInStream> inStream(inStreamSpec); totalUnpacked += curUnpacked,
inStreamSpec->SetStream(_stream); totalPacked += curPacked)
for (i = 0; i < numItems; i++, totalUnpacked += curUnpacked, totalPacked += curPacked)
{ {
lps->InSize = totalPacked; lps->InSize = totalPacked;
lps->OutSize = totalUnpacked; lps->OutSize = totalUnpacked;
RINOK(lps->SetCur()) RINOK(lps->SetCur())
if (i >= numItems)
break;
curUnpacked = curPacked = 0; curUnpacked = curPacked = 0;
CMyComPtr<ISequentialOutStream> realOutStream; Int32 opRes;
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
const UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
if (item.IsDir())
{ {
// if (!testMode) CMyComPtr<ISequentialOutStream> realOutStream;
const Int32 askMode = testMode ?
NExtract::NAskMode::kTest :
NExtract::NAskMode::kExtract;
const UInt32 index = allFilesMode ? i : indices[i];
const CItem &item = _items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
if (item.IsDir())
{ {
RINOK(extractCallback->PrepareOperation(askMode)) // if (!testMode)
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) {
RINOK(extractCallback->PrepareOperation(askMode))
// realOutStream.Release();
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
}
continue;
} }
continue;
} if (!testMode && !realOutStream)
continue;
RINOK(extractCallback->PrepareOperation(askMode))
curUnpacked = item.Size;
curPacked = item.PackSize;
if (!testMode && !realOutStream) CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;
continue; outStream->SetStream(realOutStream);
// realOutStream.Release();
RINOK(extractCallback->PrepareOperation(askMode)) outStream->Init();
curUnpacked = item.Size;
curPacked = item.PackSize;
{
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->SetStream(realOutStream);
realOutStream.Release();
outStreamSpec->Init();
inStreamSpec->Init(item.PackSize); inStream->Init(item.PackSize);
RINOK(InStream_SeekSet(_stream, item.DataPosition)) RINOK(InStream_SeekSet(_stream, item.DataPosition))
HRESULT result = S_OK; HRESULT result = S_OK;
Int32 opRes = NExtract::NOperationResult::kOK; opRes = NExtract::NOperationResult::kOK;
if (item.IsEncrypted()) if (item.IsEncrypted())
opRes = NExtract::NOperationResult::kUnsupportedMethod; opRes = NExtract::NOperationResult::kUnsupportedMethod;
@ -935,8 +914,8 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
{ {
case NCompressionMethod::kStored: case NCompressionMethod::kStored:
{ {
result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); result = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);
if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) if (result == S_OK && copyCoder->TotalSize != item.PackSize)
result = S_FALSE; result = S_FALSE;
break; break;
} }
@ -944,29 +923,21 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
case NCompressionMethod::kCompressed1b: case NCompressionMethod::kCompressed1b:
case NCompressionMethod::kCompressed1c: case NCompressionMethod::kCompressed1c:
{ {
if (!lzhDecoder) lzhDecoder.Create_if_Empty();
{ // lzhDecoder->FinishMode = true;
lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
lzhDecoder = lzhDecoderSpec;
}
lzhDecoderSpec->FinishMode = true;
const UInt32 kHistorySize = 26624; const UInt32 kHistorySize = 26624;
lzhDecoderSpec->SetDictSize(kHistorySize); lzhDecoder->SetDictSize(kHistorySize);
result = lzhDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress); result = lzhDecoder->Code(inStream, outStream, curUnpacked, lps);
if (result == S_OK && lzhDecoderSpec->GetInputProcessedSize() != item.PackSize) if (result == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)
result = S_FALSE; result = S_FALSE;
break; break;
} }
case NCompressionMethod::kCompressed2: case NCompressionMethod::kCompressed2:
{ {
if (!arjDecoder) arjDecoder.Create_if_Empty();
{ // arjDecoderSpec->FinishMode = true;
arjDecoderSpec = new NCompress::NArj::NDecoder::CCoder; result = arjDecoder->Code(inStream, outStream, curUnpacked, lps);
arjDecoder = arjDecoderSpec; if (result == S_OK && arjDecoder->GetInputProcessedSize() != item.PackSize)
}
arjDecoderSpec->FinishMode = true;
result = arjDecoder->Code(inStream, outStream, NULL, &curUnpacked, progress);
if (result == S_OK && arjDecoderSpec->GetInputProcessedSize() != item.PackSize)
result = S_FALSE; result = S_FALSE;
break; break;
} }
@ -982,15 +953,13 @@ Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
else else
{ {
RINOK(result) RINOK(result)
opRes = (outStreamSpec->GetCRC() == item.FileCRC) ? opRes = (outStream->GetCRC() == item.FileCRC) ?
NExtract::NOperationResult::kOK: NExtract::NOperationResult::kOK:
NExtract::NOperationResult::kCRCError; NExtract::NOperationResult::kCRCError;
} }
} }
outStream.Release();
RINOK(extractCallback->SetOperationResult(opRes))
} }
RINOK(extractCallback->SetOperationResult(opRes))
} }
return S_OK; return S_OK;

View file

@ -0,0 +1,596 @@
// AvbHandler.cpp
#include "StdAfx.h"
#include "../../../C/CpuArch.h"
#include "../../Common/ComTry.h"
#include "../../Common/MyBuffer.h"
#include "../../Windows/PropVariant.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"
#include "HandlerCont.h"
#define Get32(p) GetBe32(p)
#define Get64(p) GetBe64(p)
#define G32(_offs_, dest) dest = Get32(p + (_offs_))
#define G64(_offs_, dest) dest = Get64(p + (_offs_))
using namespace NWindows;
namespace NArchive {
namespace NExt {
API_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);
}
namespace NAvb {
static void AddNameToString(AString &s, const Byte *name, unsigned size, bool strictConvert)
{
for (unsigned i = 0; i < size; i++)
{
Byte c = name[i];
if (c == 0)
return;
if (strictConvert && c < 32)
c = '_';
s += (char)c;
}
}
/* Maximum size of a vbmeta image - 64 KiB. */
#define VBMETA_MAX_SIZE (64 * 1024)
#define SIGNATURE { 'A', 'V', 'B', 'f', 0, 0, 0, 1 }
static const unsigned k_SignatureSize = 8;
static const Byte k_Signature[k_SignatureSize] = SIGNATURE;
// #define AVB_FOOTER_MAGIC "AVBf"
// #define AVB_FOOTER_MAGIC_LEN 4
/* The current footer version used - keep in sync with avbtool. */
#define AVB_FOOTER_VERSION_MAJOR 1
/* The struct used as a footer used on partitions, used to find the
* AvbVBMetaImageHeader struct. This struct is always stored at the
* end of a partition.
*/
// #define AVB_FOOTER_SIZE 64
static const unsigned kFooterSize = 64;
struct CFooter
{
/* 0: Four bytes equal to "AVBf" (AVB_FOOTER_MAGIC). */
// Byte magic[AVB_FOOTER_MAGIC_LEN];
/* 4: The major version of the footer struct. */
UInt32 version_major;
/* 8: The minor version of the footer struct. */
UInt32 version_minor;
/* 12: The original size of the image on the partition. */
UInt64 original_image_size;
/* 20: The offset of the |AvbVBMetaImageHeader| struct. */
UInt64 vbmeta_offset;
/* 28: The size of the vbmeta block (header + auth + aux blocks). */
UInt64 vbmeta_size;
/* 36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This
* must be set to zeroes.
*/
Byte reserved[28];
void Parse(const Byte *p)
{
G32 (4, version_major);
G32 (8, version_minor);
G64 (12, original_image_size);
G64 (20, vbmeta_offset);
G64 (28, vbmeta_size);
}
};
/* Size of the vbmeta image header. */
#define AVB_VBMETA_IMAGE_HEADER_SIZE 256
/* Magic for the vbmeta image header. */
// #define AVB_MAGIC "AVB0"
// #define AVB_MAGIC_LEN 4
/* Maximum size of the release string including the terminating NUL byte. */
#define AVB_RELEASE_STRING_SIZE 48
struct AvbVBMetaImageHeader
{
/* 0: Four bytes equal to "AVB0" (AVB_MAGIC). */
// Byte magic[AVB_MAGIC_LEN];
/* 4: The major version of libavb required for this header. */
UInt32 required_libavb_version_major;
/* 8: The minor version of libavb required for this header. */
UInt32 required_libavb_version_minor;
/* 12: The size of the signature block. */
UInt64 authentication_data_block_size;
/* 20: The size of the auxiliary data block. */
UInt64 auxiliary_data_block_size;
/* 28: The verification algorithm used, see |AvbAlgorithmType| enum. */
UInt32 algorithm_type;
/* 32: Offset into the "Authentication data" block of hash data. */
UInt64 hash_offset;
/* 40: Length of the hash data. */
UInt64 hash_size;
/* 48: Offset into the "Authentication data" block of signature data. */
UInt64 signature_offset;
/* 56: Length of the signature data. */
UInt64 signature_size;
/* 64: Offset into the "Auxiliary data" block of public key data. */
UInt64 public_key_offset;
/* 72: Length of the public key data. */
UInt64 public_key_size;
/* 80: Offset into the "Auxiliary data" block of public key metadata. */
UInt64 public_key_metadata_offset;
/* 88: Length of the public key metadata. Must be set to zero if there
* is no public key metadata.
*/
UInt64 public_key_metadata_size;
/* 96: Offset into the "Auxiliary data" block of descriptor data. */
UInt64 descriptors_offset;
/* 104: Length of descriptor data. */
UInt64 descriptors_size;
/* 112: The rollback index which can be used to prevent rollback to
* older versions.
*/
UInt64 rollback_index;
/* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be
* set to zero if the vbmeta image is not a top-level image.
*/
UInt32 flags;
/* 124: The location of the rollback index defined in this header.
* Only valid for the main vbmeta. For chained partitions, the rollback
* index location must be specified in the AvbChainPartitionDescriptor
* and this value must be set to 0.
*/
UInt32 rollback_index_location;
/* 128: The release string from avbtool, e.g. "avbtool 1.0.0" or
* "avbtool 1.0.0 xyz_board Git-234abde89". Is guaranteed to be NUL
* terminated. Applications must not make assumptions about how this
* string is formatted.
*/
Byte release_string[AVB_RELEASE_STRING_SIZE];
/* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
* bytes. This must be set to zeroes.
*/
// Byte reserved[80];
bool Parse(const Byte *p);
};
bool AvbVBMetaImageHeader::Parse(const Byte *p)
{
// Byte magic[AVB_MAGIC_LEN];
if (Get32(p) != 0x41564230) // "AVB0"
return false;
G32 (4, required_libavb_version_major);
if (required_libavb_version_major != AVB_FOOTER_VERSION_MAJOR) // "AVB0"
return false;
G32 (8, required_libavb_version_minor);
G64 (12, authentication_data_block_size);
G64 (20, auxiliary_data_block_size);
G32 (28, algorithm_type);
G64 (32, hash_offset);
G64 (40, hash_size);
G64 (48, signature_offset);
G64 (56, signature_size);
G64 (64, public_key_offset);
G64 (72, public_key_size);
G64 (80, public_key_metadata_offset);
G64 (88, public_key_metadata_size);
G64 (96, descriptors_offset);
G64 (104, descriptors_size);
G64 (112, rollback_index);
G32 (120, flags);
G32 (124, rollback_index_location);
memcpy(release_string, p + 128, AVB_RELEASE_STRING_SIZE);
/* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE
* bytes. This must be set to zeroes.
*/
// Byte reserved[80];
return true;
}
static const unsigned k_Descriptor_Size = 16;
enum AvbDescriptorTag
{
AVB_DESCRIPTOR_TAG_PROPERTY,
AVB_DESCRIPTOR_TAG_HASHTREE,
AVB_DESCRIPTOR_TAG_HASH,
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION
};
struct AvbDescriptor
{
UInt64 Tag;
UInt64 Size;
void Parse(const Byte *p)
{
G64 (0, Tag);
G64 (8, Size);
}
};
enum AvbHashtreeDescriptorFlags
{
AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),
AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1)
};
/* A descriptor containing information about a dm-verity hashtree.
*
* Hash-trees are used to verify large partitions typically containing
* file systems. See
* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more
* information about dm-verity.
*
* Following this struct are |partition_name_len| bytes of the
* partition name (UTF-8 encoded), |salt_len| bytes of salt, and then
* |root_digest_len| bytes of the root digest.
*
* The |reserved| field is for future expansion and must be set to NUL
* bytes.
*
* Changes in v1.1:
* - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB
* - digest_len may be zero, which indicates the use of a persistent digest
*/
static const unsigned k_Hashtree_Size_Min = 164;
struct AvbHashtreeDescriptor
{
UInt32 dm_verity_version;
UInt64 image_size;
UInt64 tree_offset;
UInt64 tree_size;
UInt32 data_block_size;
UInt32 hash_block_size;
UInt32 fec_num_roots;
UInt64 fec_offset;
UInt64 fec_size;
Byte hash_algorithm[32];
UInt32 partition_name_len;
UInt32 salt_len;
UInt32 root_digest_len;
UInt32 flags;
Byte reserved[60];
void Parse(const Byte *p)
{
G32 (0, dm_verity_version);
G64 (4, image_size);
G64 (12, tree_offset);
G64 (20, tree_size);
G32 (28, data_block_size);
G32 (32, hash_block_size);
G32 (36, fec_num_roots);
G64 (40, fec_offset);
G64 (48, fec_size);
memcpy(hash_algorithm, p + 56, 32);
G32 (88, partition_name_len);
G32 (92, salt_len);
G32 (96, root_digest_len);
G32 (100, flags);
}
};
static const unsigned k_PropertyDescriptor_Size_Min = 16;
struct AvbPropertyDescriptor
{
UInt64 key_num_bytes;
UInt64 value_num_bytes;
void Parse(const Byte *p)
{
G64 (0, key_num_bytes);
G64 (8, value_num_bytes);
}
};
Z7_class_CHandler_final: public CHandlerCont
{
Z7_IFACE_COM7_IMP(IInArchive_Cont)
// UInt64 _startOffset;
UInt64 _phySize;
CFooter Footer;
AString Name;
const char *Ext;
HRESULT Open2(IInStream *stream);
virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override
{
if (index != 0)
return NExtract::NOperationResult::kUnavailable;
// pos = _startOffset;
pos = 0;
size = Footer.original_image_size;
return NExtract::NOperationResult::kOK;
}
};
HRESULT CHandler::Open2(IInStream *stream)
{
UInt64 fileSize;
{
Byte buf[kFooterSize];
RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))
if (fileSize < kFooterSize)
return S_FALSE;
RINOK(InStream_SeekSet(stream, fileSize - kFooterSize))
RINOK(ReadStream_FALSE(stream, buf, kFooterSize))
if (memcmp(buf, k_Signature, k_SignatureSize) != 0)
return S_FALSE;
Footer.Parse(buf);
if (Footer.vbmeta_size > VBMETA_MAX_SIZE ||
Footer.vbmeta_size < AVB_VBMETA_IMAGE_HEADER_SIZE)
return S_FALSE;
for (unsigned i = 36; i < kFooterSize; i++)
if (buf[i] != 0)
return S_FALSE;
}
{
CByteBuffer buf;
buf.Alloc((size_t)Footer.vbmeta_size);
RINOK(InStream_SeekSet(stream, Footer.vbmeta_offset))
RINOK(ReadStream_FALSE(stream, buf, (size_t)Footer.vbmeta_size))
AvbVBMetaImageHeader meta;
if (!meta.Parse(buf))
return S_FALSE;
unsigned offset = (unsigned)AVB_VBMETA_IMAGE_HEADER_SIZE;
unsigned rem = (unsigned)(Footer.vbmeta_size - offset);
if (meta.authentication_data_block_size != 0)
{
if (rem < meta.authentication_data_block_size)
return S_FALSE;
const unsigned u = (unsigned)meta.authentication_data_block_size;
offset += u;
rem -= u;
}
if (rem < meta.descriptors_offset ||
rem - meta.descriptors_offset < meta.descriptors_size)
return S_FALSE;
rem = (unsigned)meta.descriptors_size;
while (rem != 0)
{
if (rem < k_Descriptor_Size)
return S_FALSE;
AvbDescriptor desc;
desc.Parse(buf + offset);
offset += k_Descriptor_Size;
rem -= k_Descriptor_Size;
if (desc.Size > rem)
return S_FALSE;
const unsigned descSize = (unsigned)desc.Size;
if (desc.Tag == AVB_DESCRIPTOR_TAG_HASHTREE)
{
if (descSize < k_Hashtree_Size_Min)
return S_FALSE;
AvbHashtreeDescriptor ht;
ht.Parse(buf + offset);
unsigned pos = k_Hashtree_Size_Min;
if (pos + ht.partition_name_len > descSize)
return S_FALSE;
Name.Empty(); // UTF-8
AddNameToString(Name, buf + offset + pos, ht.partition_name_len, false);
pos += ht.partition_name_len;
if (pos + ht.salt_len > descSize)
return S_FALSE;
CByteBuffer salt;
salt.CopyFrom(buf + offset + pos, ht.salt_len);
pos += ht.salt_len;
if (pos + ht.root_digest_len > descSize)
return S_FALSE;
CByteBuffer digest;
digest.CopyFrom(buf + offset + pos, ht.root_digest_len);
pos += ht.root_digest_len;
// what is that digest?
}
else if (desc.Tag == AVB_DESCRIPTOR_TAG_PROPERTY)
{
if (descSize < k_PropertyDescriptor_Size_Min + 2)
return S_FALSE;
AvbPropertyDescriptor pt;
pt.Parse(buf + offset);
unsigned pos = k_PropertyDescriptor_Size_Min;
if (pt.key_num_bytes > descSize - pos - 1)
return S_FALSE;
AString key; // UTF-8
AddNameToString(key, buf + offset + pos, (unsigned)pt.key_num_bytes, false);
pos += (unsigned)pt.key_num_bytes + 1;
if (descSize < pos)
return S_FALSE;
if (pt.value_num_bytes > descSize - pos - 1)
return S_FALSE;
AString value; // UTF-8
AddNameToString(value, buf + offset + pos, (unsigned)pt.value_num_bytes, false);
pos += (unsigned)pt.value_num_bytes + 1;
}
offset += descSize;
rem -= descSize;
}
_phySize = fileSize;
// _startOffset = 0;
return S_OK;
}
}
Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
const UInt64 * /* maxCheckStartPosition */,
IArchiveOpenCallback * /* openArchiveCallback */))
{
COM_TRY_BEGIN
Close();
try
{
if (Open2(stream) != S_OK)
return S_FALSE;
_stream = stream;
{
CMyComPtr<ISequentialInStream> parseStream;
if (GetStream(0, &parseStream) == S_OK && parseStream)
{
const size_t kParseSize = 1 << 11;
Byte buf[kParseSize];
if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)
{
UInt64 extSize;
if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)
if (extSize == Footer.original_image_size)
Ext = "ext";
}
}
}
}
catch(...) { return S_FALSE; }
return S_OK;
COM_TRY_END
}
Z7_COM7F_IMF(CHandler::Close())
{
_stream.Release();
// _startOffset = 0;
_phySize = 0;
Ext = NULL;
Name.Empty();
return S_OK;
}
static const Byte kArcProps[] =
{
kpidName
};
static const Byte kProps[] =
{
kpidSize,
kpidPackSize,
};
IMP_IInArchive_Props
IMP_IInArchive_ArcProps
Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch (propID)
{
case kpidMainSubfile: prop = (UInt32)0; break;
case kpidPhySize: prop = _phySize; break;
case kpidName:
{
if (!Name.IsEmpty())
{
AString s (Name);
s += ".avb";
prop = s;
}
break;
}
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
switch (propID)
{
case kpidPath:
{
if (!Name.IsEmpty())
{
AString s (Name);
s += '.';
s += Ext ? Ext : "img";
prop = s;
}
break;
}
case kpidPackSize:
case kpidSize:
prop = Footer.original_image_size;
break;
case kpidExtension: prop = (Ext ? Ext : "img"); break;
}
prop.Detach(value);
return S_OK;
COM_TRY_END
}
Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
{
*numItems = 1;
return S_OK;
}
REGISTER_ARC_I_NO_SIG(
"AVB", "avb img", NULL, 0xc0,
/* k_Signature, */
0,
/* NArcInfoFlags::kUseGlobalOffset | */
NArcInfoFlags::kBackwardOpen
,
NULL)
}}

Some files were not shown because too many files have changed in this diff Show more