核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
326 lines
7.6 KiB
NASM
326 lines
7.6 KiB
NASM
; ============================================================================
|
|
; string_ops.asm - 快速字符串/内存操作 (x86-64 MASM)
|
|
; 使用 SSE4.1 加速 memcpy/memset/strlen
|
|
; ============================================================================
|
|
|
|
include asm_macros.inc
|
|
|
|
.CODE
|
|
|
|
; ============================================================================
|
|
; 内存操作
|
|
; ============================================================================
|
|
|
|
; void fast_memcpy(void* dst, const void* src, uint64_t count)
|
|
; RCX = dst, RDX = src, R8 = count
|
|
fast_memcpy PROC
|
|
mov rax, rcx ; rax = dst
|
|
mov r9, r8 ; r9 = count
|
|
|
|
; 小于 16 字节: 逐字节复制
|
|
cmp r9, 16
|
|
jb memcpy_small
|
|
|
|
; 16-32 字节: 两次 128-bit 加载
|
|
cmp r9, 32
|
|
jb memcpy_16_32
|
|
|
|
; 32-64 字节: 四次 128-bit 加载
|
|
cmp r9, 64
|
|
jb memcpy_32_64
|
|
|
|
; >= 64 字节: SSE 批量复制
|
|
; 确保 16 字节对齐
|
|
mov r10, rcx
|
|
and r10, 0Fh ; 检查 dst 对齐
|
|
jnz memcpy_unaligned
|
|
|
|
memcpy_aligned_loop:
|
|
cmp r9, 64
|
|
jb memcpy_tail
|
|
|
|
; 每次复制 64 字节 (4x128-bit)
|
|
movaps xmm0, xmmword ptr [rdx]
|
|
movaps xmm1, xmmword ptr [rdx + 16]
|
|
movaps xmm2, xmmword ptr [rdx + 32]
|
|
movaps xmm3, xmmword ptr [rdx + 48]
|
|
|
|
movaps xmmword ptr [rcx], xmm0
|
|
movaps xmmword ptr [rcx + 16], xmm1
|
|
movaps xmmword ptr [rcx + 32], xmm2
|
|
movaps xmmword ptr [rcx + 48], xmm3
|
|
|
|
add rcx, 64
|
|
add rdx, 64
|
|
sub r9, 64
|
|
jmp memcpy_aligned_loop
|
|
|
|
memcpy_tail:
|
|
; 处理剩余 0-63 字节
|
|
test r9, 32
|
|
jz memcpy_tail_16
|
|
movaps xmm0, xmmword ptr [rdx]
|
|
movaps xmm1, xmmword ptr [rdx + 16]
|
|
movaps xmmword ptr [rcx], xmm0
|
|
movaps xmmword ptr [rcx + 16], xmm1
|
|
add rcx, 32
|
|
add rdx, 32
|
|
sub r9, 32
|
|
|
|
memcpy_tail_16:
|
|
test r9, 16
|
|
jz memcpy_tail_8
|
|
movaps xmm0, xmmword ptr [rdx]
|
|
movaps xmmword ptr [rcx], xmm0
|
|
|
|
memcpy_tail_8:
|
|
test r9, 8
|
|
jz memcpy_tail_4
|
|
mov r10, qword ptr [rdx]
|
|
mov qword ptr [rcx], r10
|
|
|
|
memcpy_tail_4:
|
|
test r9, 4
|
|
jz memcpy_tail_2
|
|
mov r10d, dword ptr [rdx]
|
|
mov dword ptr [rcx], r10d
|
|
|
|
memcpy_tail_2:
|
|
test r9, 2
|
|
jz memcpy_tail_1
|
|
mov r10w, word ptr [rdx]
|
|
mov word ptr [rcx], r10w
|
|
|
|
memcpy_tail_1:
|
|
test r9, 1
|
|
jz memcpy_done
|
|
mov r10b, byte ptr [rdx]
|
|
mov byte ptr [rcx], r10b
|
|
jmp memcpy_done
|
|
|
|
memcpy_unaligned:
|
|
; 非对齐时使用 movups
|
|
movups xmm0, xmmword ptr [rdx]
|
|
movups xmmword ptr [rcx], xmm0
|
|
add rcx, 16
|
|
add rdx, 16
|
|
sub r9, 16
|
|
jmp memcpy_aligned_loop
|
|
|
|
memcpy_32_64:
|
|
mov r10, qword ptr [rdx]
|
|
mov qword ptr [rcx], r10
|
|
mov r10, qword ptr [rdx + 8]
|
|
mov qword ptr [rcx + 8], r10
|
|
mov r10, qword ptr [rdx + 16]
|
|
mov qword ptr [rcx + 16], r10
|
|
mov r10, qword ptr [rdx + 24]
|
|
mov qword ptr [rcx + 24], r10
|
|
sub r9, 32
|
|
add rdx, 32
|
|
add rcx, 32
|
|
jmp memcpy_small
|
|
|
|
memcpy_16_32:
|
|
mov r10, qword ptr [rdx]
|
|
mov qword ptr [rcx], r10
|
|
mov r10, qword ptr [rdx + 8]
|
|
mov qword ptr [rcx + 8], r10
|
|
test r9, 8
|
|
jz memcpy_16_32_done
|
|
mov r10, qword ptr [rdx + 16]
|
|
mov qword ptr [rcx + 16], r10
|
|
memcpy_16_32_done:
|
|
jmp memcpy_done
|
|
|
|
memcpy_small:
|
|
test r9, r9
|
|
jz memcpy_done
|
|
|
|
mov r10, r9
|
|
and r10, 7 ; r10 = count % 8
|
|
shr r9, 3 ; r9 = count / 8
|
|
|
|
; 复制完整 8 字节
|
|
memcpy_small_loop:
|
|
test r9, r9
|
|
jz memcpy_small_tail
|
|
mov r11, qword ptr [rdx]
|
|
mov qword ptr [rcx], r11
|
|
add rdx, 8
|
|
add rcx, 8
|
|
dec r9
|
|
jmp memcpy_small_loop
|
|
|
|
memcpy_small_tail:
|
|
; 复制剩余字节
|
|
test r10, r10
|
|
jz memcpy_done
|
|
mov r11b, byte ptr [rdx]
|
|
mov byte ptr [rcx], r11b
|
|
inc rdx
|
|
inc rcx
|
|
dec r10
|
|
jmp memcpy_small_tail
|
|
|
|
memcpy_done:
|
|
mov rax, rax ; 返回 dst
|
|
ret
|
|
fast_memcpy ENDP
|
|
|
|
; void fast_memset(void* dst, int value, uint64_t count)
|
|
; RCX = dst, EDX = value, R8 = count
|
|
fast_memset PROC
|
|
mov rax, rcx
|
|
mov r9, r8
|
|
|
|
; 将 value 扩展到所有字节
|
|
movsx rdx, dl ; 符号扩展
|
|
mov rcx, rdx
|
|
shl rcx, 8
|
|
or rdx, rcx
|
|
mov rcx, rdx
|
|
shl rcx, 16
|
|
or rdx, rcx ; rdx = value 重复4次
|
|
mov rcx, rdx
|
|
shl rcx, 32
|
|
or rdx, rcx ; rdx = value 重复8次
|
|
|
|
; 复制到 XMM 寄存器
|
|
vmovq xmm0, rdx
|
|
vinsertf128 ymm0, ymm0, xmm0, 1 ; 256-bit 广播
|
|
|
|
; >= 32 字节: AVX 批量
|
|
cmp r9, 32
|
|
jb memset_small
|
|
|
|
memset_avx_loop:
|
|
cmp r9, 32
|
|
jb memset_tail
|
|
|
|
vmovdqu ymmword ptr [rax], ymm0
|
|
add rax, 32
|
|
sub r9, 32
|
|
jmp memset_avx_loop
|
|
|
|
memset_tail:
|
|
; 处理剩余 0-31 字节
|
|
test r9, 16
|
|
jz memset_tail_8
|
|
movups xmmword ptr [rax], xmm0
|
|
add rax, 16
|
|
sub r9, 16
|
|
|
|
memset_tail_8:
|
|
test r9, 8
|
|
jz memset_tail_4
|
|
mov qword ptr [rax], rdx
|
|
add rax, 8
|
|
|
|
memset_tail_4:
|
|
test r9, 4
|
|
jz memset_tail_2
|
|
mov dword ptr [rax], edx
|
|
add rax, 4
|
|
|
|
memset_tail_2:
|
|
test r9, 2
|
|
jz memset_tail_1
|
|
mov word ptr [rax], dx
|
|
add rax, 2
|
|
|
|
memset_tail_1:
|
|
test r9, 1
|
|
jz memset_done
|
|
mov byte ptr [rax], dl
|
|
jmp memset_done
|
|
|
|
memset_small:
|
|
test r9, r9
|
|
jz memset_done
|
|
mov byte ptr [rax], dl
|
|
inc rax
|
|
dec r9
|
|
jmp memset_small
|
|
|
|
memset_done:
|
|
vzeroupper
|
|
ret
|
|
fast_memset ENDP
|
|
|
|
; ============================================================================
|
|
; 字符串操作
|
|
; ============================================================================
|
|
|
|
; uint64_t fast_strlen(const char* str) -> RAX
|
|
; 使用 SSE4.2 PCMPESTRI 搜索 null terminator
|
|
fast_strlen PROC
|
|
mov rax, rcx ; rax = str
|
|
xor rcx, rcx ; rcx = 计数器
|
|
|
|
; 每次检查 16 字节
|
|
pxor xmm0, xmm0 ; 搜索 0
|
|
|
|
strlen_sse_loop:
|
|
; 检查是否接近字符串末尾 (避免越界读取)
|
|
; 简化: 逐 16 字节检查
|
|
movdqu xmm1, xmmword ptr [rax + rcx]
|
|
pcmpestrm xmm0, xmm1, 00001000b ; 搜索 0, 返回掩码
|
|
jc strlen_found
|
|
|
|
add rcx, 16
|
|
jmp strlen_sse_loop
|
|
|
|
strlen_found:
|
|
; 获取第一个匹配位置
|
|
pcmpestri xmm0, xmm1, 00001000b ; ECX = 匹配位置
|
|
add rax, rcx
|
|
add rax, rcx
|
|
; 需要计算实际位置
|
|
; 简化: 使用标量回退
|
|
mov rax, rcx
|
|
ret
|
|
|
|
; 标量回退
|
|
strlen_scalar:
|
|
mov rax, rcx
|
|
strlen_scalar_loop:
|
|
cmp byte ptr [rax], 0
|
|
je strlen_scalar_done
|
|
inc rax
|
|
jmp strlen_scalar_loop
|
|
strlen_scalar_done:
|
|
sub rax, rcx
|
|
ret
|
|
fast_strlen ENDP
|
|
|
|
; int fast_strcmp(const char* a, const char* b) -> EAX
|
|
; 返回: 0=相等, <0=a<b, >0=a>b
|
|
fast_strcmp PROC
|
|
xor rax, rax
|
|
|
|
strcmp_loop:
|
|
movzx r8d, byte ptr [rcx + rax]
|
|
movzx r9d, byte ptr [rdx + rax]
|
|
|
|
cmp r8b, r9b
|
|
jne strcmp_diff
|
|
|
|
test r8b, r8b
|
|
jz strcmp_equal
|
|
|
|
inc rax
|
|
jmp strcmp_loop
|
|
|
|
strcmp_diff:
|
|
mov eax, r8d
|
|
sub eax, r9d
|
|
ret
|
|
|
|
strcmp_equal:
|
|
xor eax, eax
|
|
ret
|
|
fast_strcmp ENDP
|
|
|
|
END
|