memmove, vec_insert, vec_binary_search_by working and tested
This commit is contained in:
parent
af19946dc4
commit
1a4055a69a
|
|
@ -16,6 +16,7 @@ global strcmp
|
||||||
global strchr
|
global strchr
|
||||||
global streq
|
global streq
|
||||||
global memcpy
|
global memcpy
|
||||||
|
global memmove
|
||||||
global memswap
|
global memswap
|
||||||
global eprint_str
|
global eprint_str
|
||||||
global exit
|
global exit
|
||||||
|
|
@ -162,6 +163,7 @@ strcmp:
|
||||||
mov rax, 1
|
mov rax, 1
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; a and b may be overlapping
|
||||||
;; Copy bytes from one memory location to another
|
;; Copy bytes from one memory location to another
|
||||||
;; rdi: destination pointer
|
;; rdi: destination pointer
|
||||||
;; rsi: source pointer
|
;; rsi: source pointer
|
||||||
|
|
@ -182,7 +184,42 @@ memcpy:
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: destination pointer
|
||||||
|
;; rsi: source pointer
|
||||||
|
;; rdx: number of bytes to move
|
||||||
|
memmove:
|
||||||
|
; if dest < src {
|
||||||
|
cmp rdi, rsi
|
||||||
|
jb .forward
|
||||||
|
; reverse
|
||||||
|
; for i in (0..n).rev() {
|
||||||
|
mov r8, rdx
|
||||||
|
.rev_loop:
|
||||||
|
cmp r8, 0
|
||||||
|
je .done
|
||||||
|
dec r8
|
||||||
|
; dest[i] = src[i];
|
||||||
|
mov al, [rsi + r8]
|
||||||
|
mov [rdi + r8], al
|
||||||
|
jmp .rev_loop
|
||||||
|
; }
|
||||||
|
.forward:
|
||||||
|
; for i in 0..n {
|
||||||
|
xor r8, r8
|
||||||
|
.fwd_loop:
|
||||||
|
cmp r8, rdx
|
||||||
|
jge .done
|
||||||
|
; dest[i] = src[i];
|
||||||
|
mov al, [rsi + r8]
|
||||||
|
mov [rdi + r8], al
|
||||||
|
inc r8
|
||||||
|
jmp .fwd_loop
|
||||||
|
; }
|
||||||
|
.done:
|
||||||
|
mov rax, rdi
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; a and b must not be overlapping
|
||||||
;; Swap bytes between two memory locations
|
;; Swap bytes between two memory locations
|
||||||
;; rdi: pointer to first memory location
|
;; rdi: pointer to first memory location
|
||||||
;; rsi: pointer to second memory location
|
;; rsi: pointer to second memory location
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ section .rdata
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
extern memcpy
|
extern memcpy
|
||||||
|
extern memmove
|
||||||
extern memswap
|
extern memswap
|
||||||
extern oom
|
extern oom
|
||||||
extern panic
|
extern panic
|
||||||
|
|
@ -127,21 +128,17 @@ vec_get:
|
||||||
|
|
||||||
;; rdi: pointer to Vec struct
|
;; rdi: pointer to Vec struct
|
||||||
;; rsi: pointer to data to push
|
;; rsi: pointer to data to push
|
||||||
;; rdx: size of data to push
|
|
||||||
;; fn vec_push(vec: *mut Vec, data: &[u8])
|
;; fn vec_push(vec: *mut Vec, data: &[u8])
|
||||||
vec_push:
|
vec_push:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
; if data.len() != vec.item_size panic();
|
|
||||||
mov rax, [rdi + 24]
|
|
||||||
cmp rdx, rax
|
|
||||||
jne .panic
|
|
||||||
; let vec, ptr, size;
|
; let vec, ptr, size;
|
||||||
sub rsp, 24
|
sub rsp, 24
|
||||||
mov [rsp], rdi ; save vec
|
mov [rsp], rdi ; save vec
|
||||||
mov [rsp + 8], rsi ; save data ptr
|
mov [rsp + 8], rsi ; save data ptr
|
||||||
mov [rsp + 16], rdx ; save data size
|
|
||||||
; vec_try_grow(vec, size);
|
; vec_try_grow(vec, size);
|
||||||
|
mov rsi, [rdi + 8]
|
||||||
|
inc rsi
|
||||||
call vec_try_grow
|
call vec_try_grow
|
||||||
; memcpy(&vec.data[vec.len], data, size);
|
; memcpy(&vec.data[vec.len], data, size);
|
||||||
mov rax, [rsp] ; vec
|
mov rax, [rsp] ; vec
|
||||||
|
|
@ -152,7 +149,8 @@ vec_push:
|
||||||
add rax, rcx ; data + len * item_size
|
add rax, rcx ; data + len * item_size
|
||||||
mov rdi, rax ; dest ptr
|
mov rdi, rax ; dest ptr
|
||||||
mov rsi, [rsp + 8] ; data ptr
|
mov rsi, [rsp + 8] ; data ptr
|
||||||
mov rdx, [rsp + 16] ; data size
|
mov rax, [rsp] ; vec
|
||||||
|
mov rdx, [rax + 24] ; item_size
|
||||||
call memcpy
|
call memcpy
|
||||||
; vec.len += 1;
|
; vec.len += 1;
|
||||||
mov rax, [rsp] ; vec
|
mov rax, [rsp] ; vec
|
||||||
|
|
@ -160,10 +158,6 @@ vec_push:
|
||||||
add rsp, 24
|
add rsp, 24
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
.panic:
|
|
||||||
call panic
|
|
||||||
pop rbp
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;; rdi: pointer to Vec struct
|
;; rdi: pointer to Vec struct
|
||||||
|
|
@ -239,11 +233,14 @@ vec_swap:
|
||||||
jge .panic
|
jge .panic
|
||||||
|
|
||||||
; a = a * item_size;
|
; a = a * item_size;
|
||||||
mov rax, [rdi + 24] ; item_size
|
mov rbx, [rdi + 24] ; item_size
|
||||||
|
mov rax, rdx
|
||||||
|
xor rdx, rdx
|
||||||
mul rbx ; b * item_size
|
mul rbx ; b * item_size
|
||||||
mov [rsp + 16], rax
|
mov [rsp + 16], rax
|
||||||
; b = b * item_size;
|
; b = b * item_size;
|
||||||
mov rax, rsi
|
mov rax, rsi
|
||||||
|
xor rdx, rdx
|
||||||
mul rbx ; a * item_size
|
mul rbx ; a * item_size
|
||||||
mov [rsp + 8], rax
|
mov [rsp + 8], rax
|
||||||
|
|
||||||
|
|
@ -308,16 +305,18 @@ vec_remove:
|
||||||
.panic:
|
.panic:
|
||||||
call panic
|
call panic
|
||||||
|
|
||||||
|
;; essentially a reserve() function
|
||||||
;; rdi: pointer to Vec struct
|
;; rdi: pointer to Vec struct
|
||||||
;; fn vec_try_grow(vec: *mut Vec, push_size: usize) -> bool
|
;; rsi: desired size
|
||||||
|
;; fn vec_try_grow(vec: *mut Vec, new_size: usize) -> bool
|
||||||
vec_try_grow:
|
vec_try_grow:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
push rbx
|
push rbx
|
||||||
mov rax, [rdi + 16] ; capacity
|
mov rax, [rdi + 16] ; capacity
|
||||||
mov rbx, [rdi + 8] ; len
|
mov rbx, [rdi + 8] ; len
|
||||||
cmp rbx, rax
|
cmp rsi, rax
|
||||||
jg .grow
|
jge .grow ; grow if new_size >= capacity
|
||||||
pop rbx
|
pop rbx
|
||||||
xor rax, rax
|
xor rax, rax
|
||||||
pop rbp
|
pop rbp
|
||||||
|
|
@ -459,20 +458,47 @@ vec_find:
|
||||||
vec_insert:
|
vec_insert:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
sub rsp, 32
|
push r12
|
||||||
|
push rbx
|
||||||
|
sub rsp, 0x20
|
||||||
mov [rsp], rdi ; save vec
|
mov [rsp], rdi ; save vec
|
||||||
mov [rsp + 8], rsi ; save index
|
mov [rsp + 8], rsi ; save index
|
||||||
mov [rsp + 16], rdx ; save data ptr
|
mov [rsp + 0x10], rdx ; save data ptr
|
||||||
|
|
||||||
mov rsi, rdx
|
|
||||||
mov rdx, rcx
|
|
||||||
call vec_push
|
|
||||||
mov rdi, [rsp]
|
|
||||||
mov rsi, [rdi + 8]
|
mov rsi, [rdi + 8]
|
||||||
sub rsi, 1
|
inc rsi
|
||||||
mov rdx, [rsp + 8]
|
call vec_try_grow
|
||||||
call vec_swap
|
|
||||||
|
mov rbx, [rsp] ; vec
|
||||||
|
mov rdi, [rbx] ; vec.data
|
||||||
|
mov rcx, [rbx + 24] ; item_size
|
||||||
|
mov rdx, [rbx + 8] ; len
|
||||||
|
sub rdx, [rsp + 8] ; len - index
|
||||||
|
mov rax, rdx
|
||||||
|
mul rcx ; (len - index) * item_size
|
||||||
|
mov r12, rax ; number of bytes to move
|
||||||
|
mov rsi, [rbx] ; vec.data
|
||||||
|
mov rax, [rsp + 8] ; index
|
||||||
|
mov rcx, [rbx + 24] ; item_size
|
||||||
|
mul rcx ; index * item_size
|
||||||
|
add rsi, rax ; src ptr
|
||||||
|
mov rdi, rsi
|
||||||
|
add rdi, rcx ; dst ptr
|
||||||
|
mov rdx, r12 ; number of bytes to move
|
||||||
|
call memmove
|
||||||
|
|
||||||
|
mov rdi, rsi
|
||||||
|
mov rsi, [rsp + 0x10]
|
||||||
|
mov rdx, [rbx + 24] ; item_size
|
||||||
|
call memcpy
|
||||||
|
|
||||||
|
mov rax, [rbx + 8] ; len
|
||||||
|
inc rax
|
||||||
|
mov [rbx + 8], rax
|
||||||
|
|
||||||
add rsp, 32
|
add rsp, 32
|
||||||
|
pop rbx
|
||||||
|
pop r12
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
@ -502,7 +528,7 @@ vec_binary_search_by:
|
||||||
mov rax, [rsp + 0x20] ; low
|
mov rax, [rsp + 0x20] ; low
|
||||||
mov rcx, [rsp + 0x30] ; high
|
mov rcx, [rsp + 0x30] ; high
|
||||||
cmp rax, rcx
|
cmp rax, rcx
|
||||||
jge .not_found
|
jg .not_found
|
||||||
; mid = (low + high) / 2
|
; mid = (low + high) / 2
|
||||||
sub rcx, rax
|
sub rcx, rax
|
||||||
shr rcx, 1
|
shr rcx, 1
|
||||||
|
|
@ -515,8 +541,8 @@ vec_binary_search_by:
|
||||||
mul rdx ; mid * item_size
|
mul rdx ; mid * item_size
|
||||||
add rax, rcx ; vec.data + mid * item_size
|
add rax, rcx ; vec.data + mid * item_size
|
||||||
mov rdi, [rsp + 0x18] ; compare ctx
|
mov rdi, [rsp + 0x18] ; compare ctx
|
||||||
mov rsi, rax
|
mov rsi, [rsp + 0x8] ; key
|
||||||
mov rdx, [rsp + 0x8] ; key
|
mov rdx, rax
|
||||||
mov rax, [rsp + 0x10] ; compare fn
|
mov rax, [rsp + 0x10] ; compare fn
|
||||||
call rax
|
call rax
|
||||||
cmp eax, 0
|
cmp eax, 0
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,36 @@ impl<T> VecT<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn binary_search_by<F>(&self, elem: &T, mut cmp: F) -> Result<usize, usize>
|
||||||
|
where
|
||||||
|
F: FnMut(&T, &T) -> i32,
|
||||||
|
{
|
||||||
|
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
|
||||||
|
f: *const (),
|
||||||
|
a: *const u8,
|
||||||
|
b: *const u8,
|
||||||
|
) -> i32 {
|
||||||
|
let f = unsafe { &mut *(f as *mut F) };
|
||||||
|
let a = unsafe { &*(a as *const T) };
|
||||||
|
let b = unsafe { &*(b as *const T) };
|
||||||
|
f(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let index = vec_binary_search_by(
|
||||||
|
&raw const self.vec as *mut _,
|
||||||
|
elem as *const T as *const u8,
|
||||||
|
cmp_trampoline::<T, F>,
|
||||||
|
&raw mut cmp as *mut F as *mut (),
|
||||||
|
);
|
||||||
|
if (index as isize) < 0 {
|
||||||
|
Err(!index)
|
||||||
|
} else {
|
||||||
|
Ok(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|
@ -282,4 +312,18 @@ fn main() {
|
||||||
}),
|
}),
|
||||||
Some(1)
|
Some(1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(vec.as_slice(), &[20, 40, 50]);
|
||||||
|
vec.insert(30, 1);
|
||||||
|
assert_eq!(vec.as_slice(), &[20, 30, 40, 50]);
|
||||||
|
|
||||||
|
let cmp = |a: &u32, b: &u32| match a.cmp(b) {
|
||||||
|
core::cmp::Ordering::Less => -1,
|
||||||
|
core::cmp::Ordering::Equal => 0,
|
||||||
|
core::cmp::Ordering::Greater => 1,
|
||||||
|
};
|
||||||
|
assert_eq!(vec.binary_search_by(&25, cmp), Err(1));
|
||||||
|
assert_eq!(vec.binary_search_by(&30, cmp), Ok(1));
|
||||||
|
assert_eq!(vec.binary_search_by(&5, cmp), Err(0));
|
||||||
|
assert_eq!(vec.binary_search_by(&55, cmp), Err(5));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue