MiMoEngine ASM: x86-64 MASM汇编+C混合架构游戏引擎
核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
This commit is contained in:
commit
2d56cb3bc9
91 files changed
+9988
No files matched your search
@@ -0,0 +1,127 @@
|
||||
; ============================================================================
|
||||
; asm_macros.inc - MASM 通用宏定义
|
||||
; Windows x64 调用约定: RCX, RDX, R8, R9 传参, XMM0-XMM3 浮点
|
||||
; ============================================================================
|
||||
|
||||
; --- 函数帧管理宏 ---
|
||||
|
||||
; PROLOGUE: 保存非易失寄存器, 分配栈空间
|
||||
; 使用: PROLOGUE 栈空间大小
|
||||
PROLOGUE MACRO stack_size:REQ
|
||||
push rbx
|
||||
push rbp
|
||||
push rdi
|
||||
push rsi
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
sub rsp, stack_size
|
||||
; 保存浮点参数寄存器 (如果有)
|
||||
movsd qword ptr [rsp + stack_size - 8], xmm6
|
||||
movsd qword ptr [rsp + stack_size - 16], xmm7
|
||||
ENDM
|
||||
|
||||
; EPILOGUE: 恢复非易失寄存器, 释放栈空间
|
||||
EPILOGUE MACRO stack_size:REQ
|
||||
movsd xmm6, qword ptr [rsp + stack_size - 8]
|
||||
movsd xmm7, qword ptr [rsp + stack_size - 16]
|
||||
add rsp, stack_size
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbp
|
||||
pop rbx
|
||||
ret
|
||||
ENDM
|
||||
|
||||
; --- SSE/AVX 常量 ---
|
||||
.DATA
|
||||
ALIGN 16
|
||||
sse_mask_abs DD 07FFFFFFFH, 07FFFFFFFH, 07FFFFFFFH, 07FFFFFFFH ; 绝对值掩码
|
||||
sse_negate DD 80000000H, 80000000H, 80000000H, 80000000H ; 符号位掩码
|
||||
sse_one DD 3F800000H, 3F800000H, 3F800000H, 3F800000H ; 1.0f
|
||||
sse_half DD 3F000000H, 3F000000H, 3F000000H, 3F000000H ; 0.5f
|
||||
eps_float DD 33D6BF94H ; 1e-6f
|
||||
|
||||
.CODE
|
||||
|
||||
; --- 工具宏 ---
|
||||
|
||||
; LOAD_VEC3: 从内存加载 Vec3 到 XMM 寄存器 (填充 w=1.0)
|
||||
; ptr: 内存地址, reg: XMM 寄存器
|
||||
LOAD_VEC3 MACRO ptr, reg
|
||||
movss xmm0, dword ptr [ptr] ; x
|
||||
movss xmm1, dword ptr [ptr + 4] ; y
|
||||
movss xmm2, dword ptr [ptr + 8] ; z
|
||||
unpcklps xmm0, xmm1 ; {x, y, ?, ?}
|
||||
movss xmm3, dword ptr [sse_one] ; w = 1.0
|
||||
unpcklps xmm2, xmm3 ; {z, 1.0, ?, ?}
|
||||
movlhps xmm0, xmm2 ; {x, y, z, 1.0}
|
||||
movaps reg, xmm0
|
||||
ENDM
|
||||
|
||||
; STORE_VEC3: 将 XMM 寄存器的前3个float存储到内存
|
||||
STORE_VEC3 MACRO reg, ptr
|
||||
movss dword ptr [ptr], xmm0 ; x
|
||||
shufps xmm0, xmm0, 01010101b
|
||||
movss dword ptr [ptr + 4], xmm0 ; y
|
||||
shufps xmm0, xmm0, 10101010b
|
||||
movss dword ptr [ptr + 8], xmm0 ; z
|
||||
ENDM
|
||||
|
||||
; --- 外部函数声明 ---
|
||||
externdef vec3_add:PROC
|
||||
externdef vec3_sub:PROC
|
||||
externdef vec3_scale:PROC
|
||||
externdef vec3_dot:PROC
|
||||
externdef vec3_cross:PROC
|
||||
externdef vec3_length:PROC
|
||||
externdef vec3_normalize:PROC
|
||||
externdef vec3_lerp:PROC
|
||||
externdef vec3_distance:PROC
|
||||
|
||||
externdef vec4_add:PROC
|
||||
externdef vec4_sub:PROC
|
||||
externdef vec4_mul:PROC
|
||||
externdef vec4_dot:PROC
|
||||
externdef vec4_length:PROC
|
||||
externdef vec4_normalize:PROC
|
||||
|
||||
externdef mat4_identity:PROC
|
||||
externdef mat4_multiply:PROC
|
||||
externdef mat4_transpose:PROC
|
||||
externdef mat4_invert:PROC
|
||||
externdef mat4_translate:PROC
|
||||
externdef mat4_scale_f:PROC
|
||||
externdef mat4_rotate_x:PROC
|
||||
externdef mat4_rotate_y:PROC
|
||||
externdef mat4_rotate_z:PROC
|
||||
externdef mat4_perspective:PROC
|
||||
externdef mat4_orthographic:PROC
|
||||
externdef mat4_lookat:PROC
|
||||
|
||||
externdef quat_multiply:PROC
|
||||
externdef quat_conjugate:PROC
|
||||
externdef quat_normalize:PROC
|
||||
externdef quat_rotate_vec3:PROC
|
||||
externdef quat_slerp:PROC
|
||||
externdef quat_to_matrix:PROC
|
||||
externdef quat_from_axis_angle:PROC
|
||||
externdef quat_from_euler:PROC
|
||||
|
||||
externdef mem_aligned_alloc:PROC
|
||||
externdef mem_aligned_free:PROC
|
||||
externdef mem_aligned_realloc:PROC
|
||||
|
||||
externdef fast_memcpy:PROC
|
||||
externdef fast_memset:PROC
|
||||
externdef fast_strlen:PROC
|
||||
externdef fast_strcmp:PROC
|
||||
|
||||
externdef prof_rdtsc:PROC
|
||||
externdef prof_cycles_to_ms:PROC
|
||||
externdef prof_get_freq:PROC
|
||||
+1150
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#ifndef MATH_ASM_AVAILABLE
|
||||
|
||||
typedef struct { float x, y, z; } Vec3;
|
||||
typedef struct { float x, y, z, w; } Vec4;
|
||||
typedef struct { float m[4][4]; } Mat4;
|
||||
typedef struct { float x, y, z, w; } Quat;
|
||||
|
||||
static inline void vec3_add(const Vec3* a, const Vec3* b, Vec3* o) { o->x=a->x+b->x; o->y=a->y+b->y; o->z=a->z+b->z; }
|
||||
static inline void vec3_sub(const Vec3* a, const Vec3* b, Vec3* o) { o->x=a->x-b->x; o->y=a->y-b->y; o->z=a->z-b->z; }
|
||||
static inline void vec3_scale(const Vec3* a, float s, Vec3* o) { o->x=a->x*s; o->y=a->y*s; o->z=a->z*s; }
|
||||
static inline float vec3_dot(const Vec3* a, const Vec3* b) { return a->x*b->x+a->y*b->y+a->z*b->z; }
|
||||
static inline void vec3_cross(const Vec3* a, const Vec3* b, Vec3* o) { o->x=a->y*b->z-a->z*b->y; o->y=a->z*b->x-a->x*b->z; o->z=a->x*b->y-a->y*b->x; }
|
||||
static inline float vec3_length(const Vec3* a) { return sqrtf(a->x*a->x+a->y*a->y+a->z*a->z); }
|
||||
static inline void vec3_normalize(const Vec3* a, Vec3* o) { float l=vec3_length(a); if(l<1e-6f){o->x=o->y=o->z=0;return;} float i=1.0f/l; o->x=a->x*i; o->y=a->y*i; o->z=a->z*i; }
|
||||
static inline void vec3_lerp(const Vec3* a, const Vec3* b, float t, Vec3* o) { o->x=a->x+(b->x-a->x)*t; o->y=a->y+(b->y-a->y)*t; o->z=a->z+(b->z-a->z)*t; }
|
||||
static inline float vec3_distance(const Vec3* a, const Vec3* b) { Vec3 d; vec3_sub(a,b,&d); return vec3_length(&d); }
|
||||
|
||||
static inline void mat4_identity(Mat4* o) { memset(o,0,sizeof(Mat4)); o->m[0][0]=o->m[1][1]=o->m[2][2]=o->m[3][3]=1.0f; }
|
||||
static inline void mat4_multiply(const Mat4* a, const Mat4* b, Mat4* o) { Mat4 r; int i,j,k; for(i=0;i<4;i++) for(j=0;j<4;j++) { r.m[i][j]=0; for(k=0;k<4;k++) r.m[i][j]+=a->m[i][k]*b->m[k][j]; } *o=r; }
|
||||
static inline void mat4_translate(float x, float y, float z, Mat4* o) { mat4_identity(o); o->m[3][0]=x; o->m[3][1]=y; o->m[3][2]=z; }
|
||||
static inline void mat4_rotate_y(float angle, Mat4* o) { float c=cosf(angle),s=sinf(angle); mat4_identity(o); o->m[0][0]=c; o->m[0][2]=-s; o->m[2][0]=s; o->m[2][2]=c; }
|
||||
static inline void mat4_perspective(float fov, float aspect, float nearP, float farP, Mat4* o) { float t=tanf(fov*0.5f); memset(o,0,sizeof(Mat4)); o->m[0][0]=1.0f/(aspect*t); o->m[1][1]=1.0f/t; o->m[2][2]=farP/(nearP-farP); o->m[2][3]=-1.0f; o->m[3][2]=(nearP*farP)/(nearP-farP); }
|
||||
static inline void mat4_orthographic(float w, float h, float nearP, float farP, Mat4* o) { memset(o,0,sizeof(Mat4)); o->m[0][0]=2.0f/w; o->m[1][1]=2.0f/h; o->m[2][2]=1.0f/(nearP-farP); o->m[3][2]=nearP/(nearP-farP); o->m[3][3]=1.0f; }
|
||||
static inline void mat4_lookat(const Vec3* eye, const Vec3* target, const Vec3* up, Mat4* o) { Vec3 f,r,u; vec3_sub(target,eye,&f); vec3_normalize(&f,&f); vec3_cross(up,&f,&r); vec3_normalize(&r,&r); vec3_cross(&f,&r,&u); mat4_identity(o); o->m[0][0]=r.x; o->m[0][1]=u.x; o->m[0][2]=-f.x; o->m[1][0]=r.y; o->m[1][1]=u.y; o->m[1][2]=-f.y; o->m[2][0]=r.z; o->m[2][1]=u.z; o->m[2][2]=-f.z; o->m[3][0]=-vec3_dot(&r,eye); o->m[3][1]=-vec3_dot(&u,eye); o->m[3][2]=vec3_dot(&f,eye); }
|
||||
static inline void mat4_transpose(const Mat4* in, Mat4* out) { for (int i=0;i<4;i++) for (int j=0;j<4;j++) out->m[i][j]=in->m[j][i]; }
|
||||
|
||||
static inline void quat_conjugate_raw(const Quat* q, Quat* o) { o->x=-q->x; o->y=-q->y; o->z=-q->z; o->w=q->w; }
|
||||
static inline void quat_multiply(const Quat* a, const Quat* b, Quat* o) { o->x=a->w*b->x+a->x*b->w+a->y*b->z-a->z*b->y; o->y=a->w*b->y-a->x*b->z+a->y*b->w+a->z*b->x; o->z=a->w*b->z+a->x*b->y-a->y*b->x+a->z*b->w; o->w=a->w*b->w-a->x*b->x-a->y*b->y-a->z*b->z; }
|
||||
static inline void quat_normalize(const Quat* q, Quat* o) { float l=sqrtf(q->x*q->x+q->y*q->y+q->z*q->z+q->w*q->w); if(l<1e-6f){*o=*q;return;} float i=1.0f/l; o->x=q->x*i; o->y=q->y*i; o->z=q->z*i; o->w=q->w*i; }
|
||||
static inline void quat_rotate_vec3(const Quat* q, const Vec3* v, Vec3* o) { Quat vq={v->x,v->y,v->z,0}; Quat qinv; quat_conjugate_raw(q,&qinv); Quat tmp; quat_multiply(q,&vq,&tmp); Quat result; quat_multiply(&tmp,&qinv,&result); o->x=result.x; o->y=result.y; o->z=result.z; }
|
||||
static inline void quat_to_matrix(const Quat* q, Mat4* o) { float xx=q->x*q->x,yy=q->y*q->y,zz=q->z*q->z,xy=q->x*q->y,xz=q->x*q->z,yz=q->y*q->z,wx=q->w*q->x,wy=q->w*q->y,wz=q->w*q->z; mat4_identity(o); o->m[0][0]=1-2*(yy+zz); o->m[0][1]=2*(xy+wz); o->m[0][2]=2*(xz-wy); o->m[1][0]=2*(xy-wz); o->m[1][1]=1-2*(xx+zz); o->m[1][2]=2*(yz+wx); o->m[2][0]=2*(xz+wy); o->m[2][1]=2*(yz-wx); o->m[2][2]=1-2*(xx+yy); }
|
||||
|
||||
static inline void* mem_aligned_alloc(uint64_t size, uint64_t alignment) { void* p; p = _aligned_malloc(size, alignment); return p; }
|
||||
static inline void mem_aligned_free(void* ptr) { _aligned_free(ptr); }
|
||||
|
||||
static inline void fast_memcpy(void* dst, const void* src, uint64_t count) { memcpy(dst, src, (size_t)count); }
|
||||
static inline void fast_memset(void* dst, int v, uint64_t count) { memset(dst, v, (size_t)count); }
|
||||
static inline uint64_t fast_strlen(const char* s) { return strlen(s); }
|
||||
|
||||
static inline uint64_t prof_rdtsc(void) { LARGE_INTEGER f,t; QueryPerformanceFrequency(&f); QueryPerformanceCounter(&t); return (uint64_t)(t.QuadPart * 1000000000ULL / f.QuadPart); }
|
||||
static inline double prof_cycles_to_ms(uint64_t c) { return (double)c / 1000000.0; }
|
||||
static inline uint64_t prof_get_freq(void) { LARGE_INTEGER f; QueryPerformanceFrequency(&f); return (uint64_t)f.QuadPart; }
|
||||
|
||||
typedef struct { uint64_t start; uint64_t end; double elapsed_ms; } ProfTimer;
|
||||
static inline void prof_timer_start(ProfTimer* t) { t->start = prof_rdtsc(); }
|
||||
static inline void prof_timer_stop(ProfTimer* t) { t->end = prof_rdtsc(); t->elapsed_ms = prof_cycles_to_ms(t->end - t->start); }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
; ============================================================================
|
||||
; memory.asm - 对齐内存分配器 (x86-64 MASM)
|
||||
; 支持 16/32/64 字节对齐 (SIMD 需要)
|
||||
; ============================================================================
|
||||
|
||||
include asm_macros.inc
|
||||
|
||||
.DATA
|
||||
ALIGN 16
|
||||
_alloc_header_size EQU 32 ; 分配头大小 (包含对齐偏移和原始指针)
|
||||
|
||||
.CODE
|
||||
|
||||
; ============================================================================
|
||||
; 对齐内存分配
|
||||
; ============================================================================
|
||||
|
||||
; void* mem_aligned_alloc(uint64_t size, uint64_t alignment)
|
||||
; RCX = size, RDX = alignment
|
||||
; 返回: RAX = 对齐指针
|
||||
mem_aligned_alloc PROC
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
sub rsp, 40 ; 保留栈空间
|
||||
|
||||
mov rbx, rcx ; rbx = size
|
||||
mov rdi, rdx ; rdi = alignment
|
||||
|
||||
; 验证 alignment 是 2 的幂
|
||||
mov rax, rdi
|
||||
dec rax
|
||||
test rdi, rax
|
||||
jnz alloc_invalid_alignment
|
||||
|
||||
; 确保 alignment >= 16
|
||||
cmp rdi, 16
|
||||
jae alloc_alignment_ok
|
||||
mov rdi, 16
|
||||
|
||||
alloc_alignment_ok:
|
||||
; 需要的总大小 = size + alignment + header
|
||||
mov rax, rbx
|
||||
add rax, rdi ; + alignment
|
||||
add rax, _alloc_header_size ; + header
|
||||
mov rsi, rax ; rsi = total size
|
||||
|
||||
; 调用 malloc
|
||||
mov rcx, rsi
|
||||
call malloc
|
||||
test rax, rax
|
||||
jz alloc_failed
|
||||
|
||||
; rax = 原始指针
|
||||
; 计算对齐后的地址
|
||||
mov rcx, rax
|
||||
add rcx, _alloc_header_size ; 跳过 header
|
||||
; 对齐
|
||||
mov rdx, rdi
|
||||
dec rdx
|
||||
not rdx
|
||||
add rcx, rdx ; 加上 alignment-1
|
||||
and rcx, rdx ; 对齐到 alignment
|
||||
|
||||
; rcx = 对齐后的指针
|
||||
; 在对齐指针前存储原始指针
|
||||
mov [rcx - 8], rax ; 存储原始 malloc 指针
|
||||
mov [rcx - 16], rbx ; 存储请求的 size
|
||||
mov [rcx - 24], rdi ; 存储 alignment
|
||||
mov [rcx - 32], rsi ; 存储 total size
|
||||
|
||||
mov rax, rcx ; 返回对齐指针
|
||||
jmp alloc_done
|
||||
|
||||
alloc_invalid_alignment:
|
||||
xor rax, rax ; 返回 NULL
|
||||
jmp alloc_done
|
||||
|
||||
alloc_failed:
|
||||
xor rax, rax
|
||||
|
||||
alloc_done:
|
||||
add rsp, 40
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
ret
|
||||
mem_aligned_alloc ENDP
|
||||
|
||||
; void mem_aligned_free(void* ptr)
|
||||
; RCX = ptr (对齐指针)
|
||||
mem_aligned_free PROC
|
||||
test rcx, rcx
|
||||
jz free_done
|
||||
|
||||
; 获取原始 malloc 指针
|
||||
mov rax, [rcx - 8]
|
||||
test rax, rax
|
||||
jz free_done
|
||||
|
||||
; 调用 free
|
||||
mov rcx, rax
|
||||
call free
|
||||
|
||||
free_done:
|
||||
ret
|
||||
mem_aligned_free ENDP
|
||||
|
||||
; void* mem_aligned_realloc(void* ptr, uint64_t size, uint64_t alignment)
|
||||
; RCX = ptr, RDX = size, R8 = alignment
|
||||
; 返回: RAX = 新对齐指针
|
||||
mem_aligned_realloc PROC
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
push r12
|
||||
sub rsp, 40
|
||||
|
||||
mov rbx, rdx ; rbx = new size
|
||||
mov rdi, r8 ; rdi = alignment
|
||||
|
||||
; 如果 ptr 为 NULL, 直接分配
|
||||
test rcx, rcx
|
||||
jz realloc_alloc
|
||||
|
||||
; 保存旧信息
|
||||
mov rsi, [rcx - 8] ; 原始指针
|
||||
mov r12, [rcx - 16] ; 旧 size
|
||||
|
||||
; 分配新内存
|
||||
mov rcx, rbx
|
||||
mov rdx, rdi
|
||||
call mem_aligned_alloc
|
||||
test rax, rax
|
||||
jz realloc_failed
|
||||
|
||||
; 复制旧数据 (取较小值)
|
||||
mov rdx, r12
|
||||
cmp rdx, rbx
|
||||
jbe realloc_copy_ok
|
||||
mov rdx, rbx
|
||||
|
||||
realloc_copy_ok:
|
||||
mov rdi, rax ; 保存新指针
|
||||
mov rcx, rax ; dst
|
||||
; rsi = 旧数据起始
|
||||
mov rsi, [rcx - 8] ; 旧原始指针
|
||||
; 需要获取旧的对齐偏移
|
||||
; 简化: 直接复制
|
||||
call fast_memcpy
|
||||
|
||||
; 释放旧内存
|
||||
mov rcx, rsi
|
||||
call mem_aligned_free
|
||||
|
||||
mov rax, rdi ; 返回新指针
|
||||
jmp realloc_done
|
||||
|
||||
realloc_alloc:
|
||||
mov rcx, rbx
|
||||
mov rdx, rdi
|
||||
call mem_aligned_alloc
|
||||
jmp realloc_done
|
||||
|
||||
realloc_failed:
|
||||
xor rax, rax
|
||||
|
||||
realloc_done:
|
||||
add rsp, 40
|
||||
pop r12
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
ret
|
||||
mem_aligned_realloc ENDP
|
||||
|
||||
END
|
||||
@@ -0,0 +1,172 @@
|
||||
; ============================================================================
|
||||
; profiling.asm - 性能分析工具 (x86-64 MASM)
|
||||
; 使用 RDTSC/RDTSCP 进行高精度计时
|
||||
; ============================================================================
|
||||
|
||||
include asm_macros.inc
|
||||
|
||||
.DATA
|
||||
ALIGN 8
|
||||
cpu_freq DQ 0 ; CPU 频率 (Hz)
|
||||
cpu_freq_init DB 0 ; 是否已初始化
|
||||
|
||||
.CODE
|
||||
|
||||
; ============================================================================
|
||||
; RDTSC 计时
|
||||
; ============================================================================
|
||||
|
||||
; uint64_t prof_rdtsc(void) -> RAX
|
||||
; 返回: TSC (Time Stamp Counter) 值
|
||||
prof_rdtsc PROC
|
||||
; 使用 RDTSCP 获取有序的 TSC
|
||||
rdtscp
|
||||
; EDX:EAX = TSC
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
ret
|
||||
prof_rdtsc ENDP
|
||||
|
||||
; uint64_t prof_get_freq(void) -> RAX
|
||||
; 获取 CPU 频率 (通过 OS 或推断)
|
||||
prof_get_freq PROC
|
||||
; 检查是否已初始化
|
||||
cmp byte ptr [cpu_freq_init], 0
|
||||
jnz prof_freq_return
|
||||
|
||||
; 初始化 CPU 频率
|
||||
; 方法: 使用 QueryPerformanceCounter 测量 RDTSC
|
||||
push rbx
|
||||
push rdi
|
||||
push rsi
|
||||
sub rsp, 40
|
||||
|
||||
; 获取 QPC 频率
|
||||
lea rcx, [rsp + 32]
|
||||
call QueryPerformanceFrequency
|
||||
|
||||
; 获取起始 QPC 和 TSC
|
||||
lea rcx, [rsp + 16]
|
||||
call QueryPerformanceCounter
|
||||
rdtscp
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
mov rbx, rax ; rbx = 起始 TSC
|
||||
|
||||
; 等待约 10ms
|
||||
mov rcx, 10000 ; 10,000 微秒
|
||||
call Sleep
|
||||
|
||||
; 获取结束 QPC 和 TSC
|
||||
lea rcx, [rsp]
|
||||
call QueryPerformanceCounter
|
||||
rdtscp
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
mov rdi, rax ; rdi = 结束 TSC
|
||||
|
||||
; 计算经过的 QPC ticks
|
||||
mov rax, [rsp]
|
||||
sub rax, [rsp + 16] ; qpc_diff
|
||||
|
||||
; 计算 QPC 频率 (ticks/sec)
|
||||
mov rsi, [rsp + 32]
|
||||
|
||||
; TSC diff
|
||||
mov rax, rdi
|
||||
sub rax, rbx ; tsc_diff
|
||||
|
||||
; CPU freq = tsc_diff * qpc_freq / qpc_diff
|
||||
; 但 qpc_diff 对应 10ms, 所以要 * 100
|
||||
mov rdx, rsi
|
||||
mul rdx ; tsc_diff * qpc_freq
|
||||
; rdx:rax = result
|
||||
div qword ptr [rsp + 16] ; / qpc_diff
|
||||
; rax = freq * 100 (因为等待了 10ms)
|
||||
mov rcx, 100
|
||||
mul rcx
|
||||
|
||||
mov [cpu_freq], rax
|
||||
mov byte ptr [cpu_freq_init], 1
|
||||
|
||||
add rsp, 40
|
||||
pop rsi
|
||||
pop rdi
|
||||
pop rbx
|
||||
|
||||
prof_freq_return:
|
||||
mov rax, [cpu_freq]
|
||||
ret
|
||||
prof_get_freq ENDP
|
||||
|
||||
; double prof_cycles_to_ms(uint64_t cycles) -> XMM0
|
||||
; 将 TSC cycles 转换为毫秒
|
||||
prof_cycles_to_ms PROC
|
||||
; 先获取频率
|
||||
call prof_get_freq
|
||||
; rax = CPU freq (Hz)
|
||||
|
||||
; ms = cycles / (freq / 1000)
|
||||
; 或: ms = cycles * 1000 / freq
|
||||
mov rdx, 1000
|
||||
mul rdx ; freq * 1000
|
||||
; rdx:rax = freq * 1000
|
||||
|
||||
; 转换为 double
|
||||
cvtsi2sd xmm0, qword ptr [rsp - 8] ; 需要栈存储
|
||||
; 简化: 使用整数除法再转 double
|
||||
mov rcx, rax
|
||||
mov rax, [cpu_freq]
|
||||
; 重新计算
|
||||
mov rax, rcx
|
||||
; cycles * 1000 / freq
|
||||
; 已经: rax = freq * 1000, 需要 cycles * 1000 / freq
|
||||
; 调整: cycles * 1000 / freq = cycles / (freq/1000)
|
||||
|
||||
; 简化实现
|
||||
cvtsi2sd xmm0, rcx ; cycles * 1000 (转 double)
|
||||
cvtsi2sd xmm1, rax ; freq (转 double)
|
||||
divsd xmm0, xmm1 ; (cycles*1000) / freq = ms
|
||||
ret
|
||||
prof_cycles_to_ms ENDP
|
||||
|
||||
; ============================================================================
|
||||
; 内联性能宏 (在 C 代码中使用)
|
||||
; ============================================================================
|
||||
|
||||
; 获取当前时间戳 (直接 RDTSC, 无函数调用开销)
|
||||
; 在 C 中使用: __rdtsc() 内联函数
|
||||
|
||||
; 高精度计时器结构
|
||||
; struct ProfTimer {
|
||||
; uint64_t start;
|
||||
; uint64_t end;
|
||||
; double elapsed_ms;
|
||||
; };
|
||||
|
||||
; void prof_timer_start(ProfTimer* timer)
|
||||
prof_timer_start PROC
|
||||
rdtscp
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
mov [rcx], rax ; timer->start = tsc
|
||||
ret
|
||||
prof_timer_start ENDP
|
||||
|
||||
; void prof_timer_stop(ProfTimer* timer)
|
||||
prof_timer_stop PROC
|
||||
rdtscp
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
mov [rcx + 8], rax ; timer->end = tsc
|
||||
|
||||
; 计算 elapsed_ms
|
||||
mov rax, [rcx + 8]
|
||||
sub rax, [rcx] ; cycles
|
||||
; 转换为 ms
|
||||
call prof_cycles_to_ms
|
||||
movsd qword ptr [rcx + 16], xmm0 ; timer->elapsed_ms
|
||||
ret
|
||||
prof_timer_stop ENDP
|
||||
|
||||
END
|
||||
@@ -0,0 +1,325 @@
|
||||
; ============================================================================
|
||||
; 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
|
||||
Reference in new issue
Block a user