export shared code
This commit is contained in:
parent
4690b3c7ec
commit
ca9fd58bed
8
stages/shared/Makefile
Normal file
8
stages/shared/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
lib.o: lib.asm
|
||||
nasm -g -f elf64 -o lib.o lib.asm
|
||||
|
||||
alloc.o: alloc.asm
|
||||
nasm -g -f elf64 -o alloc.o alloc.asm
|
||||
|
||||
vec.o: vec.asm
|
||||
nasm -g -f elf64 -o vec.o vec.asm
|
||||
253
stages/shared/alloc.asm
Normal file
253
stages/shared/alloc.asm
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
;; Allocator
|
||||
global alloc_pages
|
||||
global dealloc_pages
|
||||
global realloc_pages
|
||||
|
||||
global heap_alloc
|
||||
global heap_dealloc
|
||||
global heap_realloc
|
||||
|
||||
extern memcpy
|
||||
|
||||
section .bss
|
||||
heap resq 1
|
||||
|
||||
section .text
|
||||
|
||||
oom_msg: db "Out of memory!", 10
|
||||
oom:
|
||||
lea rdi, [abs oom_msg]
|
||||
mov esi, 15
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 2 ; fd: stderr
|
||||
syscall
|
||||
mov rax, 60 ; syscall: exit
|
||||
mov rdi, -1 ; status: -1
|
||||
syscall
|
||||
|
||||
;; allocates $rdi bytes worth of pages via mmap
|
||||
alloc_pages:
|
||||
mov rax, 9 ; syscall: mmap
|
||||
mov rsi, rdi ; length: rdi
|
||||
xor rdi, rdi ; addr: NULL
|
||||
mov rdx, 3 ; prot: PROT_READ | PROT_WRITE
|
||||
mov r10, 34 ; flags: MAP_PRIVATE | MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd: -1
|
||||
xor r9, r9 ; offset: 0
|
||||
syscall
|
||||
cmp rax, -1
|
||||
jle oom
|
||||
ret
|
||||
|
||||
dealloc_pages:
|
||||
mov rax, 11 ; syscall: munmap
|
||||
mov rdi, rsi ; addr: rsi
|
||||
mov rsi, rdx ; length: rdx
|
||||
syscall
|
||||
cmp rax, -1
|
||||
jle oom
|
||||
ret
|
||||
|
||||
;; reallocates memory at $rdi[..$rsi] to a new location of size $rdx.
|
||||
realloc_pages:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 32
|
||||
mov qword [rsp], rsi
|
||||
mov qword [rsp + 8], rdi
|
||||
mov rdi, rdx
|
||||
call alloc_pages
|
||||
mov rsi, rdi
|
||||
mov rdi, qword [rsp + 8]
|
||||
mov rdx, qword [rsp]
|
||||
mov qword [rsp + 16], rax
|
||||
call memcpy
|
||||
mov rdi, qword [rsp + 8]
|
||||
mov rsi, qword [rsp]
|
||||
call dealloc_pages
|
||||
mov rax, qword [rsp + 16]
|
||||
add rsp, 32
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
make_slab:
|
||||
push rdi
|
||||
mov rdi, 0x4000
|
||||
call alloc_pages
|
||||
mov qword [rax + 0x4000 - 8], 0 ; initialize the tail pointer to NULL
|
||||
pop rdi
|
||||
mov qword [rdi], 0 ; tail_end = 0
|
||||
mov qword [rdi + 8], 0 ; free = NULL
|
||||
mov qword [rdi + 16], rax ; first_block = allocated
|
||||
mov qword [rdi + 24], rax ; last_block = allocated
|
||||
mov rax, rdi
|
||||
ret
|
||||
|
||||
init_heap:
|
||||
push r14
|
||||
xor r14, r14
|
||||
mov rax, qword [rel heap]
|
||||
test rax, rax
|
||||
jnz .done
|
||||
mov rdi, 0x1000
|
||||
call alloc_pages
|
||||
mov qword [rel heap], rax
|
||||
.loop:
|
||||
cmp r14, 9
|
||||
jge .done
|
||||
mov rdi, r14
|
||||
shl rdi, 5 ; idx * 32
|
||||
mov rax, qword [rel heap]
|
||||
lea rdi, [rax + rdi] ; &heap.slabs[idx]
|
||||
call make_slab
|
||||
inc r14
|
||||
jmp .loop
|
||||
.done:
|
||||
pop r14
|
||||
ret
|
||||
|
||||
;; finds the correct slab for an allocation with size $rdi and align $rsi
|
||||
slab_bucket:
|
||||
xor rax, rax
|
||||
dec rdi ; if size is a power of two, dec so we can later inc
|
||||
dec rsi ; ^^
|
||||
or rdi, rsi ; we only care about the log2, so just gather all the bits
|
||||
bsr rsi, rdi ; log2((size-1) | (align-1))
|
||||
sub rsi, 2 ; +1 for the dec, -3 to collapse the first 3 slabs into one
|
||||
cmovae rax, rsi ; saturating sub
|
||||
ret
|
||||
|
||||
slab_alloc:
|
||||
push rbx
|
||||
mov rax, qword [rdi + 8] ; free
|
||||
test rax, rax
|
||||
jz .no_free
|
||||
mov rdx, qword [rax] ; next free chunk
|
||||
mov qword [rdi + 8], rdx ; free = next
|
||||
pop rbx
|
||||
ret
|
||||
.no_free:
|
||||
add esi, 3 ; undo the -3 from slab_bucket to get the actual log2(size)
|
||||
and esi, 63 ; clamp for safety
|
||||
mov edx, 16376 ; 0x4000 - 8
|
||||
mov ecx, esi
|
||||
shr rdx, cl ; 0x4000 - 8 >> log2(size)
|
||||
mov rax, qword [rdi] ; tail_end
|
||||
mov rbx, qword [rdi + 24] ; last_block
|
||||
cmp rax, rdx
|
||||
jb .alloc_from_block
|
||||
push rsi
|
||||
push rax
|
||||
push rdi
|
||||
mov rdi, 0x4000 ; allocate a new block
|
||||
call alloc_pages
|
||||
mov qword [rax + 0x4000 - 8], 0 ; initialize the tail pointer to NULL
|
||||
pop rdi
|
||||
mov rsi, qword [rdi + 24] ; last_block
|
||||
mov qword [rsi + 0x4000 - 8], rax
|
||||
mov qword [rdi + 24], rax ; last_block = new block
|
||||
mov rbx, rax
|
||||
pop rax
|
||||
pop rsi
|
||||
.alloc_from_block:
|
||||
inc qword [rdi] ; tail_end++
|
||||
mov ecx, esi
|
||||
shl rax, cl
|
||||
add rax, rbx
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
;; allocate a chunk of memory of size $rdi and alignment $rsi
|
||||
heap_alloc:
|
||||
mov rax, qword [rel heap]
|
||||
cmp rax, 0
|
||||
je .init
|
||||
.is_init:
|
||||
push rdi
|
||||
call slab_bucket
|
||||
cmp rax, 9
|
||||
jge .mmap
|
||||
mov rsi, rax
|
||||
shl rax, 5 ; idx * 32
|
||||
mov rdi, qword [rel heap]
|
||||
lea rdi, [rdi + rax] ; &heap.slabs[idx]
|
||||
call slab_alloc
|
||||
pop rdi
|
||||
ret
|
||||
.init:
|
||||
push rdi
|
||||
push rsi
|
||||
call init_heap
|
||||
pop rsi
|
||||
pop rdi
|
||||
jmp .is_init
|
||||
.mmap:
|
||||
pop rdi
|
||||
call alloc_pages
|
||||
ret
|
||||
|
||||
;; deallocates a chunk of memory at $rdi of size $rsi and alignment $rdx
|
||||
heap_dealloc:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rsi
|
||||
push rdi
|
||||
mov rdi, rsi
|
||||
mov rsi, rdx
|
||||
call slab_bucket
|
||||
cmp rax, 9
|
||||
jge .mmap
|
||||
mov rsi, rax
|
||||
shl rax, 5 ; idx * 32
|
||||
mov rdi, qword [rel heap]
|
||||
lea rdi, [rdi + rax] ; &heap.slabs[idx]
|
||||
mov rax, qword [rdi + 8] ; free
|
||||
pop rsi
|
||||
mov qword [rsi], rax
|
||||
mov qword [rdi + 8], rsi
|
||||
pop rsi
|
||||
pop rbp
|
||||
ret
|
||||
.mmap:
|
||||
pop rdi
|
||||
pop rsi
|
||||
call dealloc_pages
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; reallocates a chunk of memory at $rdi of size $rsi and alignment $rdx to a new location of size $rcx
|
||||
heap_realloc:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rbx
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
|
||||
mov rbx, rdi
|
||||
mov r12, rsi
|
||||
mov r13, rdx
|
||||
mov r14, rcx
|
||||
|
||||
mov rdi, r14
|
||||
mov rsi, r13
|
||||
call heap_alloc
|
||||
mov r14, rax
|
||||
|
||||
mov rdi, rbx
|
||||
mov rsi, rax
|
||||
mov rdx, r12
|
||||
call memcpy
|
||||
|
||||
mov rdi, rbx
|
||||
mov rsi, r12
|
||||
mov rdx, r13
|
||||
call heap_dealloc
|
||||
|
||||
mov rax, r14
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
428
stages/shared/alloc.hex1
Normal file
428
stages/shared/alloc.hex1
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
@oom_msg:
|
||||
4f 75 74 20 6f 66 20 6d 65 6d 6f 72 79 21 0a
|
||||
@oom:
|
||||
# lea rdi, ['oom_msg]
|
||||
48 8d 3d 'oom_msg
|
||||
# mov esi, 15
|
||||
be 0f 00 00 00
|
||||
# mov eax, 1
|
||||
b8 01 00 00 00
|
||||
# mov edi, 2
|
||||
bf 02 00 00 00
|
||||
# syscall
|
||||
0f 05
|
||||
# mov eax, 60
|
||||
b8 3c 00 00 00
|
||||
# mov rdi, -1
|
||||
48 c7 c7 ff ff ff ff
|
||||
# syscall
|
||||
0f 05
|
||||
|
||||
@alloc_pages:
|
||||
# mov rax, 9
|
||||
b8 09 00 00 00
|
||||
# mov rsi, rdi
|
||||
48 89 fe
|
||||
# xor rdi, rdi
|
||||
48 31 ff
|
||||
# mov edi, 3
|
||||
ba 03 00 00 00
|
||||
# mov r10, 0x22
|
||||
41 ba 22 00 00 00
|
||||
# mov r8, -1
|
||||
49 c7 c0 ff ff ff ff
|
||||
# xor r9, r9
|
||||
4d 31 c9
|
||||
# syscall
|
||||
0f 05
|
||||
# cmp rax, -1
|
||||
48 83 f8 ff
|
||||
# jle 'oom
|
||||
0f 8e 'oom
|
||||
# ret
|
||||
c3
|
||||
|
||||
@dealloc_pages:
|
||||
# mov rax, 11
|
||||
b8 0b 00 00 00
|
||||
# mov rdi, rsi
|
||||
48 89 f7
|
||||
# mov rsi, rdx
|
||||
48 89 d6
|
||||
# syscall
|
||||
0f 05
|
||||
# cmp rax, -1
|
||||
48 83 f8 ff
|
||||
# jle 'oom
|
||||
0f 8e 'oom
|
||||
# ret
|
||||
c3
|
||||
|
||||
@realloc_pages:
|
||||
# push rbp
|
||||
55
|
||||
# mov rbp, rsp
|
||||
48 89 e5
|
||||
# sub rsp, 32
|
||||
48 83 ec 20
|
||||
# mov qword [rsp], rsi
|
||||
48 89 34 24
|
||||
# mov qword [rsp + 8], rdi
|
||||
48 89 7c 24 08
|
||||
# mov rdi, rdx
|
||||
48 89 d7
|
||||
# call 'alloc_pages
|
||||
e8 'alloc_pages
|
||||
# mov rsi, rax
|
||||
48 89 fe
|
||||
# mov rdi, qword [rsp + 8]
|
||||
48 8b 7c 24 08
|
||||
# mov rdx, qword [rsp]
|
||||
48 8b 14 24
|
||||
# mov qword [rsp + 16], rax
|
||||
48 89 44 24 10
|
||||
# call 'memcpy
|
||||
e8 'memcpy
|
||||
# mov rdi, qword [rsp + 8]
|
||||
48 8b 7c 24 08
|
||||
# mov rsi, qword [rsp]
|
||||
48 8b 34 24
|
||||
# call 'dealloc_pagesA
|
||||
e8 'dealloc_pages
|
||||
# mov rax, qword [rsp + 16]
|
||||
48 8b 44 24 10
|
||||
# add rsp, 32
|
||||
48 83 c4 20
|
||||
# pop rbp
|
||||
5d
|
||||
# ret
|
||||
c3
|
||||
|
||||
@make_slab:
|
||||
# push rdi
|
||||
57
|
||||
# mov rdi, 0x4000
|
||||
bf 00 40 00 00
|
||||
# call 'alloc_pages
|
||||
e8 'alloc_pages
|
||||
# mov qword [rsp + 0x4000 - 8], 0
|
||||
48 c7 80 f8 3f 00 00 00 00 00 00
|
||||
# pop rdi
|
||||
5f
|
||||
# mov qword [rdi], 0
|
||||
48 c7 07 00 00 00 00
|
||||
# mov qword [rdi + 8], 0
|
||||
48 c7 47 08 00 00 00 00
|
||||
# mov qword [rdi + 16], rax
|
||||
48 89 47 10
|
||||
# mov qword [rdi + 24], rax
|
||||
48 89 47 18
|
||||
# mov rax, rdi
|
||||
48 89 f8
|
||||
# ret
|
||||
c3
|
||||
|
||||
@heap:
|
||||
00 00 00 00 00 00 00 00
|
||||
@init_heap.done:
|
||||
# pop r14
|
||||
41 5e
|
||||
# ret
|
||||
c3
|
||||
@init_heap:
|
||||
# push r14
|
||||
41 56
|
||||
# xor r14, r14
|
||||
4d 31 f6
|
||||
# mov rax, ['heap]
|
||||
48 8b 05 'heap
|
||||
# test rax, rax
|
||||
48 85 c0
|
||||
# jne .done
|
||||
0f 85 'init_heap.done
|
||||
# mov rdi, 0x1000
|
||||
bf 00 10 00 00
|
||||
# call alloc_pages
|
||||
e8 'alloc_pages
|
||||
# mov ['heap], rax
|
||||
48 89 05 'heap
|
||||
@init_heap.loop:
|
||||
# cmp r14, 9
|
||||
49 83 fe 09
|
||||
# jge .done
|
||||
0f 8d 'init_heap.done
|
||||
# mov rdi, r14
|
||||
4c 89 f7
|
||||
# shl rdi, 12
|
||||
48 c1 e7 05
|
||||
# mov rax, ['heap]
|
||||
48 8b 05 'heap
|
||||
# lea rdi, [rax + rdi]
|
||||
48 8d 3c 38
|
||||
# call make_slab
|
||||
e8 'make_slab
|
||||
# inc r14
|
||||
49 ff c6
|
||||
# jmp .loop
|
||||
e9 'init_heap.loop
|
||||
|
||||
@slab_bucket:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# dec rdi
|
||||
48 ff cf
|
||||
# dec rsi
|
||||
48 ff ce
|
||||
# or rdi, rsi
|
||||
48 09 f7
|
||||
# bsr rsi, rdi
|
||||
48 0f bd f7
|
||||
# sub rsi, 2
|
||||
48 83 ee 02
|
||||
# cmovae rax, rsi
|
||||
48 0f 43 c6
|
||||
# ret
|
||||
c3
|
||||
|
||||
@slab_alloc.alloc_from_block:
|
||||
# inc qword [rdi]
|
||||
48 ff 07
|
||||
#mov ecx, esi
|
||||
89 f1
|
||||
# shl rax, cl
|
||||
48 d3 e0
|
||||
# add rax, rbx
|
||||
48 01 d8
|
||||
# pop rbx
|
||||
5b
|
||||
# ret
|
||||
c3
|
||||
@slab_alloc.no_free:
|
||||
# add esi, 3
|
||||
83 c6 03
|
||||
# and esi, 63
|
||||
83 e6 3f
|
||||
# mov edx, 0x4000 - 8
|
||||
ba f8 3f 00 00
|
||||
# mov ecx, esi
|
||||
89 f1
|
||||
# shr rdx, cl
|
||||
48 d3 ea
|
||||
# mov rax, qword [rdi]
|
||||
48 8b 07
|
||||
# mov rbx, qword [rdi + 24]
|
||||
48 8b 5f 18
|
||||
# cmp rax, rdx
|
||||
48 39 d0
|
||||
# jb .alloc_from_block
|
||||
0f 82 'slab_alloc.alloc_from_block
|
||||
# push rsi
|
||||
56
|
||||
# push rax
|
||||
50
|
||||
# push rdi
|
||||
57
|
||||
# mov rdi, 0x4000
|
||||
bf 00 40 00 00
|
||||
# call 'alloc_pages
|
||||
e8 'alloc_pages
|
||||
# mov qword [rax + 0x4000 - 8], 0
|
||||
48 c7 80 f8 3f 00 00 00 00 00 00
|
||||
# pop rdi
|
||||
5f
|
||||
# mov rsi, qword [rdi + 24]
|
||||
48 8b 77 18
|
||||
# mov qword [rdi + 24], rax
|
||||
48 89 86 f8 3f 00 00
|
||||
# mov qword [rdi + 24], rax
|
||||
48 89 47 18
|
||||
# mov rbx, rax
|
||||
48 89 c3
|
||||
# pop rax
|
||||
58
|
||||
# pop rsi
|
||||
5e
|
||||
@slab_alloc:
|
||||
# push rbx
|
||||
53
|
||||
# mov rax, qword [rdi + 8]
|
||||
48 8b 47 08
|
||||
# test rax, rax
|
||||
48 85 c0
|
||||
# je .no_free
|
||||
0f 84 'slab_alloc.no_free
|
||||
# mov rdx, qword [rax]
|
||||
48 8b 10
|
||||
# mov qword [rdi + 8], rdx
|
||||
48 89 57 08
|
||||
# pop rbx
|
||||
5b
|
||||
# ret
|
||||
c3
|
||||
|
||||
@heap_alloc.mmap:
|
||||
# pop rdi
|
||||
5f
|
||||
# call 'alloc_pages
|
||||
e8 'alloc_pages
|
||||
# ret
|
||||
c3
|
||||
@heap_alloc.is_init:
|
||||
# push rdi
|
||||
57
|
||||
# call slab_bucket
|
||||
e8 'slab_bucket
|
||||
# cmp rax, 9
|
||||
48 83 f8 09
|
||||
# jge .mmap
|
||||
0f 8d 'heap_alloc.mmap
|
||||
# mov rsi, rax
|
||||
48 89 c6
|
||||
# shl rax, 5
|
||||
48 c1 e0 05
|
||||
# mov rdi, qword ['heap]
|
||||
48 8b 3d 'heap
|
||||
# lea rdi, [rdi + rax]
|
||||
48 8d 3c 07
|
||||
# call 'slab_alloc
|
||||
e8 'slab_alloc
|
||||
# pop rdi
|
||||
5f
|
||||
# ret
|
||||
c3
|
||||
@heap_alloc.init:
|
||||
# push rdi
|
||||
57
|
||||
# push rsi
|
||||
56
|
||||
# call 'init_heap
|
||||
e8 'init_heap
|
||||
# pop rsi
|
||||
5e
|
||||
# pop rdi
|
||||
5f
|
||||
# jmp 'heap_alloc.is_init
|
||||
e9 'heap_alloc.is_init
|
||||
@heap_alloc:
|
||||
# mov rax, qword ['heap]
|
||||
48 8b 05 'heap
|
||||
# cmp rax, 0
|
||||
48 83 f8 00
|
||||
# je .init
|
||||
0f 84 'heap_alloc.init
|
||||
# jmp 'heap_alloc.is_init
|
||||
e9 'heap_alloc.is_init
|
||||
|
||||
@heap_dealloc.mmap:
|
||||
# pop rdi
|
||||
5f
|
||||
# pop rsi
|
||||
5e
|
||||
# call 'dealloc_pages
|
||||
e8 'dealloc_pages
|
||||
# pop rbp
|
||||
5d
|
||||
# ret
|
||||
c3
|
||||
@heap_dealloc:
|
||||
# push rbp
|
||||
55
|
||||
# mov rbp, rsp
|
||||
48 89 e5
|
||||
# push rsi
|
||||
56
|
||||
# push rdi
|
||||
57
|
||||
# mov rdi, rsi
|
||||
48 89 f7
|
||||
# mov rsi, rdx
|
||||
48 89 d6
|
||||
# call 'slab_bucket
|
||||
e8 'slab_bucket
|
||||
# cmp rax, 9
|
||||
48 83 f8 09
|
||||
# jge 'heap_dealloc.mmap
|
||||
0f 8d 'heap_dealloc.mmap
|
||||
# mov rsi, rax
|
||||
48 89 c6
|
||||
# shl rax, 5
|
||||
48 c1 e0 05
|
||||
# mov rdi, qword ['heap]
|
||||
48 8b 3d 'heap
|
||||
# lea rdi, [rdi + rax]
|
||||
48 8d 3c 07
|
||||
# mov rax, qword [rdi + 8]
|
||||
48 8b 47 08
|
||||
# pop rsi
|
||||
5e
|
||||
# mov qword [rsi], rax
|
||||
48 89 06
|
||||
# mov qword [rdi + 8], rsi
|
||||
48 89 77 08
|
||||
# pop rsi
|
||||
5e
|
||||
# pop rbp
|
||||
5d
|
||||
# ret
|
||||
c3
|
||||
|
||||
|
||||
@heap_realloc:
|
||||
# push rbp
|
||||
55
|
||||
# mov rbp, rsp
|
||||
48 89 e5
|
||||
# push rbx
|
||||
53
|
||||
# push r12
|
||||
41 54
|
||||
# push r13
|
||||
41 55
|
||||
# push r14
|
||||
41 56
|
||||
# mov rbx, rdi
|
||||
48 89 fb
|
||||
# mov r12, rsi
|
||||
49 89 f4
|
||||
# mov r13, rdx
|
||||
49 89 d5
|
||||
# mov r14, rcx
|
||||
49 89 ce
|
||||
# mov rdi, r14
|
||||
4c 89 f7
|
||||
# mov rsi, r13
|
||||
4c 89 ee
|
||||
# call 'heap_alloc
|
||||
e8 'heap_alloc
|
||||
# mov r14, rax
|
||||
49 89 c6
|
||||
# mov rdi, rbx
|
||||
48 89 df
|
||||
# mov rsi, rax
|
||||
48 89 c6
|
||||
# mov rdx, r12
|
||||
4c 89 e2
|
||||
# call 'memcpy
|
||||
e8 'memcpy
|
||||
# mov rdi, rbx
|
||||
48 89 df
|
||||
# mov rsi, r12
|
||||
4c 89 e6
|
||||
# mov rdx, r13
|
||||
4c 89 ea
|
||||
# call 'heap_dealloc
|
||||
e8 'heap_dealloc
|
||||
# mov rax, r14
|
||||
4c 89 f0
|
||||
# pop r14
|
||||
41 5e
|
||||
# pop r13
|
||||
41 5d
|
||||
# pop r12
|
||||
41 5c
|
||||
# pop rbx
|
||||
5b
|
||||
# pop rbp
|
||||
5d
|
||||
# ret
|
||||
c3
|
||||
343
stages/shared/lib.asm
Normal file
343
stages/shared/lib.asm
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
;; Common Library Functions
|
||||
global strlen
|
||||
global strstr
|
||||
global strcmp
|
||||
global strfind
|
||||
global memcpy
|
||||
global is_alpha
|
||||
global is_digit
|
||||
global is_alphanumeric
|
||||
global is_id_start
|
||||
global is_id_cont
|
||||
global to_digit
|
||||
global parse_i64
|
||||
global parse_i64_cstr
|
||||
global exit
|
||||
global fasthash
|
||||
|
||||
section .text
|
||||
|
||||
;; fn strlen(s: *const u8) -> usize
|
||||
strlen:
|
||||
xor eax, eax
|
||||
.loop:
|
||||
cmp byte [rdi + rax], 0
|
||||
je .done
|
||||
inc rax
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
;; find in the first $rsi bytes of $rdi (haystack) the first $rcx bytes of $rdx (needle).
|
||||
;; returns the index in $rax, or -1 if not found.
|
||||
;; fn strstr(haystack: *const u8, haystack_len: usize, needle: *const u8, needle_len: usize) -> isize
|
||||
strstr:
|
||||
push rbx
|
||||
push r12
|
||||
push r13
|
||||
mov r13, rdi ; save original haystack pointer
|
||||
mov rax, rsi ; remaining haystack length
|
||||
.loop_haystack:
|
||||
cmp rax, rcx
|
||||
jb .not_found ; not enough haystack left for needle
|
||||
|
||||
xor rbx, rbx ; needle index
|
||||
.loop_needle:
|
||||
cmp rbx, rcx
|
||||
jz .found ; found the needle
|
||||
|
||||
mov r12b, byte [rdx + rbx] ; needle[needle_index]
|
||||
cmp r12b, byte [rdi + rbx] ; haystack[haystack_index + needle_index]
|
||||
jne .next_haystack ; mismatch, move to next haystack index
|
||||
inc rbx
|
||||
jmp .loop_needle
|
||||
.next_haystack:
|
||||
inc rdi ; move to next haystack index
|
||||
dec rax ; decrease remaining haystack length
|
||||
jmp .loop_haystack
|
||||
.not_found:
|
||||
xor eax, eax
|
||||
dec rax
|
||||
jmp .done
|
||||
.found:
|
||||
sub rdi, r13 ; calculate the index of the found needle
|
||||
mov rax, rdi
|
||||
.done:
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbx
|
||||
ret
|
||||
|
||||
|
||||
;; fn strcmp(s1: *const u8, s1_len: usize, s2: *const u8, s2_len: usize) -> i32
|
||||
strcmp:
|
||||
cmp rcx, rsi
|
||||
cmovb rsi, rcx ; if rhs is shorter, use its length for the loop
|
||||
xor eax, eax
|
||||
.strcmp_loop:
|
||||
cmp rsi, rax
|
||||
jz .strcmp_equal
|
||||
movzx ecx, byte [rdx + rax]
|
||||
cmp byte [rdi + rax], cl
|
||||
lea rax, [rax + 1]
|
||||
je .strcmp_loop
|
||||
seta al ; al = lhs > rhs
|
||||
sbb al, 0 ; al = al - CF
|
||||
ret
|
||||
.strcmp_equal:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
;; fn strfind(s: *const u8, len: usize, c: u8) -> isize
|
||||
strfind:
|
||||
strch:
|
||||
xor eax, eax
|
||||
.loop:
|
||||
cmp rax, rsi
|
||||
jge .not_found
|
||||
mov cl, byte [rdi + rax]
|
||||
cmp cl, dl
|
||||
je .found
|
||||
inc rax
|
||||
jmp .loop
|
||||
.not_found:
|
||||
xor eax, eax
|
||||
dec rax
|
||||
.found:
|
||||
ret
|
||||
|
||||
;; fn memcpy(src: *const u8, dst: *mut u8, len: usize)
|
||||
memcpy:
|
||||
.loop:
|
||||
test rdx, rdx
|
||||
jz .done
|
||||
mov al, byte [rdi]
|
||||
mov byte [rsi], al
|
||||
inc rsi
|
||||
inc rdi
|
||||
dec rdx
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
;; fn is_alpha(c: u8) -> bool
|
||||
is_alpha:
|
||||
movzx eax, dil
|
||||
and eax, 0x1fffdf ; ignore bit 5 (case)
|
||||
add eax, -65 ; subtract 'A'
|
||||
cmp eax, 26 ; check if in range 0-25
|
||||
setb al
|
||||
ret
|
||||
|
||||
;; fn is_digit(c: u8) -> bool
|
||||
is_digit:
|
||||
movzx edi, dil
|
||||
lea eax, [rdi - 48] ; subtract '0'
|
||||
cmp eax, 10 ; check if in range 0-9
|
||||
setb al
|
||||
ret
|
||||
|
||||
;; fn is_alphanumeric(c: u8) -> bool
|
||||
is_alphanumeric:
|
||||
lea eax, [rdi - 48]
|
||||
cmp eax, 10
|
||||
setb cl
|
||||
and dil, 0xdf
|
||||
add dil, -65
|
||||
cmp dil, 26
|
||||
setb al
|
||||
or al, cl
|
||||
ret
|
||||
|
||||
;; fn is_id_start(c: u8) -> bool
|
||||
is_id_start:
|
||||
call is_alpha
|
||||
cmp dil, 95
|
||||
sete cl
|
||||
or al, cl
|
||||
ret
|
||||
|
||||
;; fn is_id_continue(c: u8) -> bool
|
||||
is_id_cont:
|
||||
call is_alphanumeric
|
||||
cmp dil, 45
|
||||
sete cl
|
||||
or al, cl
|
||||
cmp dil, 95
|
||||
sete cl
|
||||
or al, cl
|
||||
ret
|
||||
|
||||
;; converts char $dil to a digit with radix $rsi, returning it in $edx. $al is set to 1 if the char is a valid digit, and 0 otherwise.
|
||||
;; fn to_digit(c: u8, radix: u8) -> (is_valid: bool, digit: u8)
|
||||
to_digit:
|
||||
lea eax, [rsi - 2]
|
||||
cmp eax, 35
|
||||
jae .invalid
|
||||
movzx rdi, dil
|
||||
lea edx, [rdi - 65] ; 'A' = 65
|
||||
and edx, -33 ; convert to uppercase
|
||||
add edx, 10 ; 'A' should map to 10
|
||||
lea eax, [rdi - 48] ; '0' = 48
|
||||
cmp esi, 11
|
||||
cmovb edx, eax ; if radix <= 10, then take the difference from '0'
|
||||
cmp edi, 58
|
||||
cmovb edx, eax ; or if char < '9', then take the difference from '0'
|
||||
xor eax, eax
|
||||
cmp edx, esi
|
||||
setb al ; al = edx < radix
|
||||
ret
|
||||
.invalid:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
;; fn parse_i64(s: *const u8) -> (is_valid: bool, value: i64)
|
||||
parse_i64_cstr:
|
||||
call strlen
|
||||
mov rsi, rax
|
||||
jmp parse_i64
|
||||
|
||||
;; fn parse_i64(s: *const u8, len: usize) -> (is_valid: bool, value: i64)
|
||||
parse_i64:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
push rbx ; buf
|
||||
push r12 ; radix
|
||||
push r13 ; acc
|
||||
push r14 ; end
|
||||
|
||||
push rdi
|
||||
|
||||
sub rsp, 8
|
||||
mov dword [rsp], 1 ; sign = 1
|
||||
mov rbx, rdi ; buf
|
||||
mov r12, 10 ; radix
|
||||
xor r13, r13 ; acc
|
||||
|
||||
xor eax, eax
|
||||
mov r14, rsi
|
||||
add r14, rdi ; end = buf + len
|
||||
|
||||
cmp rbx, r14
|
||||
jge .done ; if buf >= end, return 0
|
||||
|
||||
; eat leading -
|
||||
cmp byte [rbx], '-'
|
||||
sete al
|
||||
lea rbx, [rbx + rax]
|
||||
shl eax, 1
|
||||
sub dword [rsp], eax
|
||||
|
||||
cmp rbx, r14
|
||||
jge .done
|
||||
|
||||
; eat leading +
|
||||
cmp byte [rbx], '+'
|
||||
sete al
|
||||
lea rbx, [rbx + rax]
|
||||
|
||||
cmp rbx, r14
|
||||
jge .done
|
||||
|
||||
mov dil, byte [rbx]
|
||||
mov esi, 10
|
||||
call to_digit
|
||||
jnb .not_numeric
|
||||
|
||||
; radix
|
||||
cmp dil, '0'
|
||||
jne .loop
|
||||
inc rbx
|
||||
|
||||
cmp rbx, r14
|
||||
jge .done
|
||||
|
||||
mov dil, byte [rbx]
|
||||
and dil, 0xdf ; convert to uppercase
|
||||
cmp dil, 'X'
|
||||
sete al
|
||||
lea ecx, [eax + eax * 2]
|
||||
shl ecx, 1 ; multiply by 6
|
||||
add r12d, ecx ; radix += 'x' ? 6 : 0
|
||||
|
||||
cmp dil, 'O'
|
||||
sete al
|
||||
shl al, 1 ; multiply by 2
|
||||
sub r12d, eax ; radix -= 'o' ? 2 : 0
|
||||
|
||||
cmp dil, 'B'
|
||||
sete al
|
||||
shl al, 3 ; multiply by 8
|
||||
sub r12d, eax ; radix -= 'b' ? 8 : 0
|
||||
|
||||
cmp r12d, 10
|
||||
setne al
|
||||
lea rbx, [rbx + rax] ; skip the radix prefix if it was present
|
||||
|
||||
.loop:
|
||||
cmp rbx, r14
|
||||
jge .done
|
||||
|
||||
mov dil, byte [rbx]
|
||||
inc rbx
|
||||
|
||||
cmp dil, '_'
|
||||
je .loop
|
||||
mov esi, r12d
|
||||
call to_digit
|
||||
mov ecx, edx
|
||||
test al, al
|
||||
jz .done
|
||||
mov rax, r13
|
||||
imul r12
|
||||
add rax, rcx
|
||||
mov r13, rax
|
||||
jmp .loop
|
||||
.not_numeric:
|
||||
xor eax, eax
|
||||
xor edx, edx
|
||||
add rsp, 8
|
||||
pop rdi
|
||||
jmp .epilogue
|
||||
.done:
|
||||
|
||||
mov rdx, rax
|
||||
neg r13
|
||||
cmp dword [rsp], 0
|
||||
cmovl rdx, r13
|
||||
|
||||
add rsp, 8
|
||||
pop rdi
|
||||
|
||||
sub rbx, rdi
|
||||
mov rax, rbx
|
||||
|
||||
.epilogue:
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; fn exit() -> !
|
||||
exit:
|
||||
xor edi, edi
|
||||
mov rax, 60
|
||||
syscall
|
||||
|
||||
;; fn fasthash(s: *const u8, len: usize) -> u32
|
||||
fasthash:
|
||||
mov eax, 0x811C9DC5 ; FNV-1a 32-bit offset basis
|
||||
.loop:
|
||||
test rsi, rsi
|
||||
jz .done
|
||||
movzx ecx, byte [rdi]
|
||||
xor eax, ecx
|
||||
imul eax, 0x01000193 ; FNV prime
|
||||
inc rdi
|
||||
dec rsi
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
449
stages/shared/lib.hex1
Normal file
449
stages/shared/lib.hex1
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
@strlen.done:
|
||||
# ret
|
||||
c3
|
||||
@strlen:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
@strlen.loop:
|
||||
# cmp byte [rdi + rax], 0
|
||||
80 3c 07 00
|
||||
# je .done:
|
||||
0f 84 'strlen.done
|
||||
# inc rax
|
||||
48 ff c0
|
||||
# jmp .loop
|
||||
e9 'strlen.loop
|
||||
|
||||
|
||||
@strstr.found:
|
||||
# sub rdi, r13
|
||||
4c 29 ef
|
||||
# mov rax, rdi
|
||||
48 89 f8
|
||||
@strstr.done:
|
||||
# pop r13
|
||||
41 5d
|
||||
# pop r12
|
||||
41 5c
|
||||
# pop rbx
|
||||
5b
|
||||
# ret
|
||||
c3
|
||||
@strstr.notfound
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# dec rax
|
||||
48 ff c8
|
||||
# jmp .done
|
||||
e9 'strstr.done
|
||||
@strstr.next_hackstack:
|
||||
# inc rdi
|
||||
48 ff c7
|
||||
# dec rax
|
||||
48 ff c8
|
||||
@strstr.loop_haystack:
|
||||
# cmp rax, rcx
|
||||
48 39 c8
|
||||
# jb 'strstr.notfound
|
||||
0f 82 'strstr.notfound
|
||||
# xor ebx, ebx
|
||||
31 db
|
||||
@strstr.loop_needle:
|
||||
# cmp rbx, rcx
|
||||
48 39 cb
|
||||
# je .found
|
||||
0f 84 'strstr.found
|
||||
# mov r12b, byte [rdx + rbx]
|
||||
44 8a 24 1a
|
||||
# cmp r12b, byte [rdi + rbx]
|
||||
44 3a 24 1f
|
||||
# jne .next_haystack
|
||||
0f 85 'strstr.next_haystack
|
||||
# inc rbx
|
||||
48 ff c3
|
||||
# jmp .loop_needle
|
||||
e9 'strstr.loop_needle
|
||||
|
||||
@strstr:
|
||||
# push rbx
|
||||
53
|
||||
# push r12
|
||||
41 54
|
||||
# push r13
|
||||
41 55
|
||||
# mov r13, rdi
|
||||
49 89 fd
|
||||
# mov rax, rsi
|
||||
48 89 f0
|
||||
# jmp .loop_haystack
|
||||
e9 'strstr.loop_haystack
|
||||
|
||||
@strcmp.eq:
|
||||
31 c0
|
||||
c3
|
||||
@strcmp:
|
||||
# cmp rcx, rsi
|
||||
48 39 f1
|
||||
# cmovb rsi, rcx
|
||||
48 0f 42 f1
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
@strcmp.loop:
|
||||
# cmp rsi, rax
|
||||
48 39 c6
|
||||
# je .eq
|
||||
0f 84 'strcmp.eq
|
||||
# movzx ecx, byte [rdx + rax]
|
||||
0f b6 0c 02
|
||||
# cmp byte [rdi + rax, cl
|
||||
38 0c 07
|
||||
# inc rax
|
||||
48 ff c0
|
||||
# je .loop
|
||||
0f 84 'strcmp.loop
|
||||
# seta al
|
||||
0f 97 c0
|
||||
# sbb al, 0
|
||||
1c 00
|
||||
# ret
|
||||
c3
|
||||
|
||||
@strfind.nf:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# dec rax
|
||||
48 ff c8
|
||||
@strfind.f:
|
||||
c3
|
||||
@strfind:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# cmp rax, rsi
|
||||
48 39 f0
|
||||
# jge .nf
|
||||
0f 8d 'strfind.nf
|
||||
# mov cl, byte [rdi + rax]
|
||||
8a 0c 07
|
||||
# cmp cl, dl
|
||||
38 d1
|
||||
# je .f
|
||||
0f 84 'strfind.f
|
||||
# inc rax
|
||||
48 ff c0
|
||||
# jmp strfind
|
||||
e9 'strfind
|
||||
|
||||
@memcpy.done:
|
||||
c3
|
||||
@memcpy:
|
||||
# test rdx, rdx
|
||||
48 85 d2
|
||||
# jz .done
|
||||
0f 84 'memcpy.done
|
||||
# mov al, byte [rdi]
|
||||
8a 07
|
||||
# mov byte [rsi], al
|
||||
88 06
|
||||
# inc rsi
|
||||
48 ff c6
|
||||
# inc rdi
|
||||
48 ff c7
|
||||
# dec rdx
|
||||
48 ff ca
|
||||
# jmp .loop
|
||||
e9 'memcpy
|
||||
|
||||
@is_alpha:
|
||||
40 0f b6 c7
|
||||
25 df ff 1f 00
|
||||
83 c0 bf
|
||||
83 f8 1a
|
||||
0f 92 c0
|
||||
c3
|
||||
|
||||
@is_digit:
|
||||
40 0f b6 ff
|
||||
8d 47 d0
|
||||
83 f8 0a
|
||||
0f 92 c0
|
||||
c3
|
||||
|
||||
@is_alphanumeric:
|
||||
8d 47 d0
|
||||
83 f8 0a
|
||||
0f 92 c1
|
||||
40 80 e7 df
|
||||
40 80 c7 bf
|
||||
40 80 ff 1a
|
||||
0f 92 c0
|
||||
08 c8
|
||||
c3
|
||||
|
||||
@is_id_start:
|
||||
# call is_alpha
|
||||
e8 'is_alpha
|
||||
40 80 ff 5f
|
||||
0f 94 c1
|
||||
08 c8
|
||||
c3
|
||||
|
||||
@is_id_cont:
|
||||
# call is_alphanumeric
|
||||
e8 'is_alphanumeric
|
||||
40 80 ff 2d
|
||||
0f 94 c1
|
||||
08 c8
|
||||
40 80 ff 5f
|
||||
0f 94 c1
|
||||
08 c8
|
||||
c3
|
||||
|
||||
@to_digit.inv:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# ret
|
||||
c3
|
||||
@to_digit:
|
||||
8d 46 fe
|
||||
83 f8 23
|
||||
# jae .inv
|
||||
0f 83 'to_digit.inv
|
||||
48 0f b6 ff
|
||||
8d 57 bf
|
||||
83 e2 df
|
||||
83 c2 0a
|
||||
8d 47 d0
|
||||
83 fe 0b
|
||||
0f 42 d0
|
||||
83 ff 3a
|
||||
0f 42 d0
|
||||
31 c0
|
||||
39 f2
|
||||
0f 92 c0
|
||||
c3
|
||||
|
||||
@parse_i64.done:
|
||||
# mov rdx, rax
|
||||
48 89 c2
|
||||
# neg r13
|
||||
49 f7 dd
|
||||
# cmp dword [rsp], 0
|
||||
83 3c 24 00
|
||||
# cmovl rdx, r13
|
||||
49 0f 4c d5
|
||||
# add rsp, 8
|
||||
48 83 c4 08
|
||||
# pop rdi
|
||||
5f
|
||||
# sub rbx, rdi
|
||||
48 29 fb
|
||||
# mov rax, rbx
|
||||
48 89 d8
|
||||
@parse_i64.epilogue:
|
||||
# pop r14
|
||||
41 5e
|
||||
# pop r13
|
||||
41 5d
|
||||
# pop r12
|
||||
41 5c
|
||||
# pop rbx
|
||||
5b
|
||||
# pop rbp
|
||||
5d
|
||||
# ret
|
||||
c3
|
||||
@parse_i64.not_num:
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# xor edx, edx
|
||||
31 d2
|
||||
# add rsp, 8
|
||||
48 83 c4 08
|
||||
# pop rdi
|
||||
5f
|
||||
# jmp .epilogue
|
||||
e9 'parse_i64.epilogue
|
||||
|
||||
@parse_i64_cstr:
|
||||
e8 'strlen
|
||||
# mov rsi, rax
|
||||
48 89 c6
|
||||
|
||||
@parse_i64:
|
||||
# push rbp
|
||||
55
|
||||
# mov rbp, rsp
|
||||
48 89 e5
|
||||
# push rbx
|
||||
53
|
||||
# push r12
|
||||
41 54
|
||||
# push r13
|
||||
41 55
|
||||
# push r14
|
||||
41 56
|
||||
# push rdi
|
||||
57
|
||||
# sub rsp, 8
|
||||
48 83 ec 08
|
||||
# mov dword [rsp], 1
|
||||
c7 04 24 01 00 00 00
|
||||
# mov rbx, rdi
|
||||
48 89 fb
|
||||
# mov r12, 10
|
||||
41 bc 0a 00 00 00
|
||||
# xor r13, r13
|
||||
4d 31 ed
|
||||
# xor eax, eax
|
||||
31 c0
|
||||
# mov r14, rsi
|
||||
49 89 f6
|
||||
# add r14, rdi
|
||||
49 01 fe
|
||||
# cmp rbx, r14
|
||||
4c 39 f3
|
||||
# jge .done
|
||||
0f 8d 'parse_i64.done
|
||||
# cmp byte [rbx], '-'
|
||||
80 3b 2d
|
||||
# sete al
|
||||
0f 94 c0
|
||||
# lea rbx, [rbx + rax]
|
||||
48 8d 1c 03
|
||||
# shl eax, 1
|
||||
d1 e0
|
||||
# sub dword [rsp], eax
|
||||
29 04 24
|
||||
# cmp rbx, r14
|
||||
4c 39 f3
|
||||
# jge .done
|
||||
0f 8d 'parse_i64.done
|
||||
# cmp byte [rbx], '+'
|
||||
80 3b 2b
|
||||
# sete al
|
||||
0f 94 c0
|
||||
# lea rbx, [rbx + rax]
|
||||
48 8d 1c 03
|
||||
# cmp rbx, r14
|
||||
4c 39 f3
|
||||
# jge .done
|
||||
0f 8d 'parse_i64.done
|
||||
# mov dil, byte [rbx]
|
||||
40 8a 3b
|
||||
# mov esi, 10
|
||||
be 0a 00 00 00
|
||||
# call to_digit
|
||||
e8 'to_digit
|
||||
# jae .not_num
|
||||
0f 83 'parse_i64.not_num
|
||||
# cmp dil, '0'
|
||||
40 80 ff 30
|
||||
# jne .loop
|
||||
0f 85 'parse_i64.loop
|
||||
# inc rbx
|
||||
48 ff c3
|
||||
# cmp rbx, r14
|
||||
4c 39 f3
|
||||
# jge .done
|
||||
0f 8d 'parse_i64.done
|
||||
# mov dil, byte [rbx]
|
||||
40 8a 3b
|
||||
# and dil, 0xdf
|
||||
40 80 e7 df
|
||||
# cmp dil, 'X'
|
||||
40 80 ff 58
|
||||
# sete al
|
||||
0f 94 c0
|
||||
# lea ecx, [eax + eax * 2]
|
||||
67 8d 0c 40
|
||||
# shl ecx, 1
|
||||
d1 e1
|
||||
# add r12d, ecx
|
||||
41 01 cc
|
||||
# cmp dil, 'O'
|
||||
40 80 ff 4f
|
||||
# sete al
|
||||
0f 94 c0
|
||||
# shl al, 1
|
||||
d0 e0
|
||||
# sub r12d, eax
|
||||
41 29 c4
|
||||
# cmp dil, 'B'
|
||||
40 80 ff 42
|
||||
# sete al
|
||||
0f 94 c0
|
||||
# shl al, 3
|
||||
c0 e0 03
|
||||
# sub r12d, eax
|
||||
41 29 c4
|
||||
# cmp r12d, 10
|
||||
41 83 fc 0a
|
||||
# setne al
|
||||
0f 95 c0
|
||||
# lea rbx, [rbx + rax]
|
||||
48 8d 1c 03
|
||||
|
||||
@parse_i64.loop:
|
||||
# cmp rbx, r14
|
||||
4c 39 f3
|
||||
# jge .done
|
||||
0f 8d 'parse_i64.done
|
||||
# mov dil, byte [rbx]
|
||||
40 8a 3b
|
||||
# inc rbx
|
||||
48 ff c3
|
||||
# cmp dil, '_'
|
||||
40 80 ff 5f
|
||||
# je .loop
|
||||
0f 84 'parse_i64.loop
|
||||
# mov esi, r12d
|
||||
44 89 e6
|
||||
# call to_digit
|
||||
e8 'to_digit
|
||||
# mov ecx, edx
|
||||
89 d1
|
||||
# test al, al
|
||||
84 c0
|
||||
# je .done
|
||||
0f 84 'parse_i64.done
|
||||
# mov rax, r13
|
||||
4c 89 e8
|
||||
# imul r12
|
||||
49 f7 ec
|
||||
# add rax, rcx
|
||||
48 01 c8
|
||||
mov r13, rax
|
||||
49 89 c5
|
||||
# jmp .loop
|
||||
e9 'parse_i64.loop
|
||||
|
||||
@exit:
|
||||
# xor edi, edi
|
||||
31 ff
|
||||
# mov eax, 60
|
||||
b8 3c 00 00 00
|
||||
# syscall
|
||||
0f 05
|
||||
|
||||
@fasthash.done:
|
||||
c3
|
||||
@fasthash:
|
||||
# mov eax, 0x811c9dc5
|
||||
b8 c5 9d 1c 81
|
||||
@fasthash.loop:
|
||||
# test rsi, rsi
|
||||
48 85 f6
|
||||
# jz .done
|
||||
0f 84 'fasthash.done
|
||||
# movzx ecx, byte [rdi]
|
||||
0f b6 0f
|
||||
# xor eax, ecx
|
||||
31 c8
|
||||
# imul eax, 0x01000193
|
||||
69 c0 93 01 00 01
|
||||
# inc rdi
|
||||
48 ff c7
|
||||
# dec rsi
|
||||
48 ff ce
|
||||
# jmp .loop
|
||||
e9 'fasthash.loop
|
||||
77
stages/shared/vec.asm
Normal file
77
stages/shared/vec.asm
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
;; Vec / Dynamic Array Structure
|
||||
extern heap_realloc
|
||||
|
||||
global vec_init
|
||||
global vec_get_nth
|
||||
global vec_reserve
|
||||
|
||||
struc Vec
|
||||
.data resq 1 ; pointer to elements
|
||||
.size resd 1 ; size in element count
|
||||
.cap resd 1 ; cap in element count
|
||||
.ele_size resd 1 ; size of each element in bytes
|
||||
.ele_align resd 1 ; alignment of each element in bytes
|
||||
endstruc
|
||||
|
||||
;; fn vec_init(vec: *mut Vec, ele_size: usize, ele_align: usize) -> *mut Vec
|
||||
vec_init:
|
||||
mov qword [rdi + Vec.data], 0
|
||||
mov dword [rdi + Vec.size], 0
|
||||
mov dword [rdi + Vec.cap], 0
|
||||
mov dword [rdi + Vec.ele_size], esi
|
||||
mov dword [rdi + Vec.ele_align], edx
|
||||
mov rax, rdi
|
||||
ret
|
||||
|
||||
;; fn vec_get_nth(vec: *const Vec, idx: usize) -> *const u8
|
||||
vec_get_nth:
|
||||
mov rax, rsi
|
||||
mov ecx, dword [rdi + Vec.ele_size]
|
||||
mul ecx
|
||||
add rax, qword [rdi + Vec.data]
|
||||
ret
|
||||
|
||||
;; reserve space for $rsi additional entries in vec $rdi.
|
||||
;; fn vec_reserve(vec: *mut Vec, count: usize)
|
||||
vec_reserve:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, 16
|
||||
|
||||
mov edx, dword [rdi + Vec.ele_size]
|
||||
mov ecx, dword [rdi + Vec.ele_align]
|
||||
mov dword [rsp], edx ; obj-size
|
||||
mov dword [rsp + 4], ecx ; alignment
|
||||
mov qword [rsp + 8], rdi ; table pointer
|
||||
|
||||
mov eax, dword [rdi + Vec.size]
|
||||
add eax, esi
|
||||
cmp eax, dword [rdi + Vec.cap]
|
||||
jl .done
|
||||
|
||||
mov eax, esi
|
||||
add eax, dword [rdi + Vec.size]
|
||||
mov ecx, dword [rdi + Vec.cap]
|
||||
mov edx, ecx
|
||||
shl edx, 1
|
||||
cmp eax, edx
|
||||
cmovl eax, edx
|
||||
; new cap
|
||||
mul dword [rsp] ; obj-size
|
||||
|
||||
; old cap
|
||||
xchg eax, ecx
|
||||
mul dword [rsp] ; obj-size
|
||||
|
||||
mov rdi, qword [rdi + Vec.data] ; old pointer
|
||||
mov esi, eax ; old size
|
||||
mov edx, ecx ; new size
|
||||
mov ecx, dword [rsp + 4] ; alignment
|
||||
call heap_realloc
|
||||
mov rdi, qword [rsp + 8] ; table pointer
|
||||
mov qword [rdi + Vec.data], rax
|
||||
|
||||
.done:
|
||||
add rsp, 16
|
||||
pop rbp
|
||||
ret
|
||||
Loading…
Reference in a new issue