Skip to main content

luaur_code_gen/functions/
emit_invoke_libm_1_p.rs

1use crate::enums::address_kind_a_64::AddressKindA64;
2use crate::enums::kind_a_64::KindA64;
3use crate::macros::codegen_assert::CODEGEN_ASSERT;
4use crate::records::address_a_64::AddressA64;
5use crate::records::assembly_builder_a_64::AssemblyBuilderA64;
6use crate::records::register_a_64::RegisterA64;
7use luaur_vm::type_aliases::t_value::TValue;
8
9const K_MAX_IMMEDIATE: usize = (1 << 12) - 1;
10const K_TEMP_SLOTS: u32 = 1;
11const S_TEMPORARY_DATA: i32 = 9 * 8;
12
13const fn reg(kind: KindA64, index: u8) -> RegisterA64 {
14    RegisterA64 {
15        bits: kind as u8 | (index << 3),
16    }
17}
18
19const X0: RegisterA64 = reg(KindA64::x, 0);
20const X1: RegisterA64 = reg(KindA64::x, 1);
21const X20: RegisterA64 = reg(KindA64::x, 20);
22const X25: RegisterA64 = reg(KindA64::x, 25);
23const SP: RegisterA64 = reg(KindA64::none, 31);
24const D0: RegisterA64 = reg(KindA64::d, 0);
25
26fn mem(base: RegisterA64, data: i32) -> AddressA64 {
27    AddressA64 {
28        kind: AddressKindA64::imm,
29        base,
30        offset: RegisterA64::noreg,
31        data,
32    }
33}
34
35pub fn emit_invoke_libm_1_p(build: &mut AssemblyBuilderA64, func: usize, arg: i32) {
36    CODEGEN_ASSERT!(K_TEMP_SLOTS >= 1);
37    CODEGEN_ASSERT!(S_TEMPORARY_DATA as usize <= K_MAX_IMMEDIATE);
38
39    let tvalue_size = core::mem::size_of::<TValue>() as i32;
40    let value_offset = core::mem::offset_of!(TValue, value) as i32;
41
42    build.ldr(D0, mem(X25, arg * tvalue_size + value_offset));
43    build.add_register_a_64_register_a_64_u16(X0, SP, S_TEMPORARY_DATA as u16);
44    build.ldr(X1, mem(X20, func as i32));
45    build.blr(X1);
46}