Last active
April 24, 2023 03:13
-
-
Save pervognsen/bb71bb110c0829b448cbaae64cbe671c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.code | |
; struct Xeno_Win64CallContext { | |
; void *function_pointer; | |
; uint64_t integer_return_value; | |
; uint64_t floating_point_return_value; | |
; uint64_t register_arguments[4]; | |
; uint64_t *stack_arguments; | |
; size_t stack_arguments_count; | |
; }; | |
Xeno_Win64CallContext struct | |
function_pointer QWORD ? | |
integer_return_value QWORD ? | |
floating_point_return_value QWORD ? | |
register_argument0 QWORD ? | |
register_argument1 QWORD ? | |
register_argument2 QWORD ? | |
register_argument3 QWORD ? | |
stack_arguments QWORD ? | |
stack_arguments_count QWORD ? | |
Xeno_Win64CallContext ends | |
; extern "C" void Xeno_Win64Call(Xeno_Win64CallContext *context); | |
Xeno_Win64Call proc frame | |
mov qword ptr [rsp + 8], rbx | |
.savereg rbx, 8 | |
mov qword ptr [rsp + 16], rbp | |
.savereg rbp, 16 | |
mov rbp, rsp | |
.setframe rbp, 0 | |
.endprolog | |
mov rbx, rcx | |
mov rcx, (Xeno_Win64CallContext ptr [rbx]).register_argument0 | |
movd xmm0, rcx | |
mov rdx, (Xeno_Win64CallContext ptr [rbx]).register_argument1 | |
movd xmm1, rdx | |
mov r8, (Xeno_Win64CallContext ptr[rbx]).register_argument2 | |
movd xmm2, r8 | |
mov r9, (Xeno_Win64CallContext ptr [rbx]).register_argument3 | |
movd xmm3, r9 | |
mov r10, (Xeno_Win64CallContext ptr [rbx]).stack_arguments_count | |
lea r10, [8 * r10] | |
mov r11, (Xeno_Win64CallContext ptr [rbx]).stack_arguments | |
lea r11, [r11 + r10] | |
mov rax, rsp | |
sub rax, r10 | |
and rax, 0FFFFFFFFFFFFFFF0h | |
lea rsp, [rax + r10] | |
cmp r10, 0 | |
next: | |
jz done | |
sub r11, 8 | |
push qword ptr [r11] | |
sub r10, 8 | |
jmp next | |
done: | |
mov rax, (Xeno_Win64CallContext ptr [rbx]).function_pointer | |
sub rsp, 32 | |
call rax | |
mov (Xeno_Win64CallContext ptr [rbx]).integer_return_value, rax | |
movd (Xeno_Win64CallContext ptr [rbx]).floating_point_return_value, xmm0 | |
mov rsp, rbp | |
mov rbp, qword ptr [rsp + 16] | |
mov rbx, qword ptr [rsp + 8] | |
ret | |
Xeno_Win64Call endp | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Xeno_Win64CallContext { | |
void *function_pointer; | |
uint64_t integer_return_value; | |
uint64_t floating_point_return_value; | |
uint64_t register_arguments[4]; | |
uint64_t *stack_arguments; | |
size_t stack_arguments_count; | |
}; | |
extern "C" void Xeno_Win64Call(Xeno_Win64CallContext *context); | |
void Xeno_Call(Xeno_Data function, Xeno_Data return_value_destination, Xeno_Data *arguments, size_t arguments_count) { | |
Assert(function.type->kind == XENO_FUNCTION); | |
Xeno_Function *function_type = function.type->function; | |
Assert(function_type->arguments_count == arguments_count); | |
Xeno_Win64CallContext win64_call_context; | |
size_t temporaries_size = 0; | |
for (size_t index = 0; index < function_type->arguments_count; index++) { | |
size_t size = function_type->argument_types[index]->size; | |
if (size > 8) { | |
temporaries_size += (size + 15) & ~15; | |
} | |
} | |
uint64_t *temporaries = 0; | |
if (temporaries_size > 0) { | |
temporaries = (uint64_t *)_alloca(temporaries_size + 15); | |
temporaries = (uint64_t *)(((uintptr_t)temporaries + 15) & ~15); | |
} | |
uint64_t *temporaries_pointer = temporaries; | |
size_t argument_register = 0; | |
size_t actual_arguments_count = function_type->arguments_count; | |
if (function_type->return_type->size > 8) { | |
Assert(function_type->return_type == return_value_destination.type); | |
win64_call_context.register_arguments[0] = (uint64_t)return_value_destination.pointer; | |
argument_register = 1; | |
actual_arguments_count++; | |
} | |
uint64_t *stack_arguments = 0; | |
if (actual_arguments_count > 4) { | |
stack_arguments = (uint64_t *)_alloca((actual_arguments_count - 4) * sizeof(uint64_t)); | |
} | |
uint64_t *stack_argument = stack_arguments; | |
for (size_t i = 0; i < function_type->arguments_count; i++) { | |
Xeno_Type *argument_type = function_type->argument_types[i]; | |
uint64_t argument; | |
if (argument_type->size <= 8) { | |
if (Xeno_IsPrimitiveType(argument_type)) { | |
Xeno_Data argument_data = {&argument, argument_type}; | |
Xeno_Cast(argument_data, arguments[i]); | |
} else { | |
Assert(argument_type == arguments[i].type); | |
memcpy(&argument, arguments[i].pointer, argument_type->size); | |
} | |
} else { | |
Assert(argument_type == arguments[i].type); | |
memcpy(temporaries_pointer, arguments[i].pointer, argument_type->size); | |
argument = (uint64_t)temporaries_pointer; | |
temporaries_pointer += argument_type->size; | |
temporaries_pointer = (uint64_t *)(((uintptr_t)temporaries_pointer + 15) & ~15); | |
} | |
if (argument_register < 4) { | |
win64_call_context.register_arguments[argument_register] = argument; | |
argument_register++; | |
} else { | |
*stack_argument = argument; | |
stack_argument++; | |
} | |
} | |
win64_call_context.function_pointer = function.pointer; | |
win64_call_context.stack_arguments = stack_arguments; | |
win64_call_context.stack_arguments_count = stack_argument - stack_arguments; | |
Xeno_Win64Call(&win64_call_context); | |
if (function_type->return_type->size <= 8) { | |
uint64_t return_value; | |
if (function_type->return_type->kind == XENO_FLOAT || function_type->return_type->kind == XENO_DOUBLE) { | |
return_value = win64_call_context.floating_point_return_value; | |
} else { | |
return_value = win64_call_context.integer_return_value; | |
} | |
Xeno_Data return_value_data = {&return_value, function_type->return_type}; | |
Xeno_Cast(return_value_destination, return_value_data); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment