-
Notifications
You must be signed in to change notification settings - Fork 2
/
vm_mem.c
80 lines (64 loc) · 2.48 KB
/
vm_mem.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "shared/shared.h"
#include "vm.h"
static void QC_memcpy(qcvm_t *vm)
{
const qcvm_pointer_t dst = qcvm_argv_pointer(vm, 0);
const qcvm_pointer_t src = qcvm_argv_pointer(vm, 1);
const int32_t size = qcvm_argv_int32(vm, 2);
void *dst_address, *src_address;
if (size < 0 || !qcvm_resolve_pointer(vm, dst, false, size, &dst_address) || !qcvm_resolve_pointer(vm, src, false, size, &src_address))
qcvm_error(vm, "invalid pointer");
else if (!size)
return;
memcpy(dst_address, src_address, size);
const size_t span = size / sizeof(qcvm_global_t);
qcvm_string_list_mark_refs_copied(vm, src_address, dst_address, span);
qcvm_field_wrap_list_check_set(vm, dst_address, span);
}
static void QC_memmove(qcvm_t *vm)
{
const qcvm_pointer_t dst = qcvm_argv_pointer(vm, 0);
const qcvm_pointer_t src = qcvm_argv_pointer(vm, 1);
const int32_t size = qcvm_argv_int32(vm, 2);
void *dst_address, *src_address;
if (size < 0 || !qcvm_resolve_pointer(vm, dst, false, size, &dst_address) || !qcvm_resolve_pointer(vm, src, false, size, &src_address))
qcvm_error(vm, "invalid pointer");
else if (!size)
return;
memmove(dst_address, src_address, size);
const size_t span = size / sizeof(qcvm_global_t);
qcvm_string_list_mark_refs_copied(vm, src_address, dst_address, span);
qcvm_field_wrap_list_check_set(vm, dst_address, span);
}
static void QC_memset(qcvm_t *vm)
{
const qcvm_pointer_t dst = qcvm_argv_pointer(vm, 0);
const int32_t val = qcvm_argv_int32(vm, 1);
const int32_t size = qcvm_argv_int32(vm, 2);
void *dst_address;
if (size < 0 || !qcvm_resolve_pointer(vm, dst, false, size, &dst_address))
qcvm_error(vm, "invalid pointer");
else if (!size)
return;
memset(dst_address, val, size);
const size_t span = size / sizeof(qcvm_global_t);
qcvm_string_list_check_ref_unset(vm, dst_address, span, true);
qcvm_field_wrap_list_check_set(vm, dst_address, span);
}
static void QC_memcmp(qcvm_t *vm)
{
const qcvm_pointer_t dst = qcvm_argv_pointer(vm, 0);
const qcvm_pointer_t src = qcvm_argv_pointer(vm, 1);
const int32_t size = qcvm_argv_int32(vm, 2);
void *dst_address, *src_address;
if (size < 0 || !qcvm_resolve_pointer(vm, dst, false, size, &dst_address) || !qcvm_resolve_pointer(vm, src, false, size, &src_address))
qcvm_error(vm, "invalid pointer");
qcvm_return_int32(vm, memcmp(dst_address, src_address, size));
}
void qcvm_init_mem_builtins(qcvm_t *vm)
{
qcvm_register_builtin(memcpy);
qcvm_register_builtin(memmove);
qcvm_register_builtin(memset);
qcvm_register_builtin(memcmp);
}