Skip to main content

luaur_code_gen/functions/
emit_builtin_math_modf.rs

1use crate::enums::size_x_64::SizeX64;
2use crate::functions::luau_reg_tag::luau_reg_tag;
3use crate::functions::luau_reg_value::luau_reg_value;
4use crate::records::assembly_builder_x_64::AssemblyBuilderX64;
5use crate::records::ir_call_wrapper_x_64::IrCallWrapperX64;
6use crate::records::ir_data::k_invalid_inst_idx;
7use crate::records::ir_op::IrOp;
8use crate::records::ir_reg_alloc_x_64::IrRegAllocX64;
9use crate::records::native_context::NativeContext;
10use crate::records::operand_x_64::OperandX64;
11use crate::records::register_x_64::RegisterX64;
12use luaur_vm::enums::lua_type::lua_Type;
13
14const fn reg(index: u8, size: SizeX64) -> RegisterX64 {
15    RegisterX64 {
16        bits: (index << RegisterX64::INDEX_SHIFT) | size as u8,
17    }
18}
19
20const R_NATIVE_CONTEXT: RegisterX64 = reg(13, SizeX64::qword);
21const XMM0: RegisterX64 = reg(0, SizeX64::xmmword);
22const XMM1: RegisterX64 = reg(1, SizeX64::xmmword);
23
24fn s_temporary_slot() -> OperandX64 {
25    OperandX64::mem(SizeX64::qword, RegisterX64::noreg, 1, RegisterX64::rsp, 0)
26}
27
28pub fn emit_builtin_math_modf(
29    regs: &mut IrRegAllocX64,
30    build: &mut AssemblyBuilderX64,
31    ra: i32,
32    arg: i32,
33    nresults: i32,
34) {
35    let mut call_wrap = IrCallWrapperX64::ir_call_wrapper_x_64_ir_call_wrapper_x_64(
36        regs,
37        build,
38        k_invalid_inst_idx,
39    );
40    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
41        SizeX64::xmmword,
42        luau_reg_value(arg),
43        IrOp::ir_op(),
44    );
45    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
46        SizeX64::qword,
47        s_temporary_slot(),
48        IrOp::ir_op(),
49    );
50    call_wrap.call(&OperandX64::mem(
51        SizeX64::qword,
52        RegisterX64::noreg,
53        1,
54        R_NATIVE_CONTEXT,
55        core::mem::offset_of!(NativeContext, libm_modf) as i32,
56    ));
57
58    build.vmovsd_operand_x_64_operand_x_64(
59        OperandX64::reg(XMM1),
60        OperandX64::mem(SizeX64::qword, RegisterX64::noreg, 1, RegisterX64::rsp, 0),
61    );
62    build.vmovsd_operand_x_64_operand_x_64(luau_reg_value(ra), OperandX64::reg(XMM1));
63    build.mov(
64        luau_reg_tag(ra),
65        OperandX64::imm(lua_Type::LUA_TNUMBER as i32),
66    );
67
68    if nresults > 1 {
69        build.vmovsd_operand_x_64_operand_x_64(luau_reg_value(ra + 1), OperandX64::reg(XMM0));
70        build.mov(
71            luau_reg_tag(ra + 1),
72            OperandX64::imm(lua_Type::LUA_TNUMBER as i32),
73        );
74    }
75}