luaur_code_gen/functions/
emit_interrupt_code_gen_a_64.rs1use crate::enums::address_kind_a_64::AddressKindA64;
2use crate::enums::kind_a_64::KindA64;
3use crate::functions::emit_exit_code_gen_a_64::emit_exit_assembly_builder_a_64_bool;
4use crate::functions::emit_update_base_emit_common_a_64::emit_update_base;
5use crate::records::address_a_64::AddressA64;
6use crate::records::assembly_builder_a_64::AssemblyBuilderA64;
7use crate::records::label::Label;
8use crate::records::register_a_64::RegisterA64;
9use luaur_vm::records::call_info::CallInfo;
10use luaur_vm::records::global_state::global_State;
11use luaur_vm::records::lua_callbacks::LuaCallbacks;
12use luaur_vm::records::lua_state::lua_State;
13
14const fn reg(kind: KindA64, index: u8) -> RegisterA64 {
15 RegisterA64 {
16 bits: kind as u8 | (index << 3),
17 }
18}
19
20const X0: RegisterA64 = reg(KindA64::x, 0);
21const X1: RegisterA64 = reg(KindA64::x, 1);
22const X2: RegisterA64 = reg(KindA64::x, 2);
23const W0: RegisterA64 = reg(KindA64::w, 0);
24const W1: RegisterA64 = reg(KindA64::w, 1);
25const R_STATE: RegisterA64 = reg(KindA64::x, 19);
26const R_BASE: RegisterA64 = reg(KindA64::x, 22);
27const R_CODE: RegisterA64 = reg(KindA64::x, 24);
28
29const SIZEOF_INSTRUCTION: u16 = 4;
30
31fn mem(base: RegisterA64, data: i32) -> AddressA64 {
32 AddressA64 {
33 kind: AddressKindA64::imm,
34 base,
35 offset: RegisterA64::noreg,
36 data,
37 }
38}
39
40pub fn emit_interrupt(build: &mut AssemblyBuilderA64) {
41 let mut skip = Label::default();
42
43 build.mov_register_a_64_register_a_64(R_BASE, X1);
44
45 build.ldr(
46 X2,
47 mem(R_STATE, core::mem::offset_of!(lua_State, global) as i32),
48 );
49 build.ldr(
50 X2,
51 mem(
52 X2,
53 (core::mem::offset_of!(global_State, cb)
54 + core::mem::offset_of!(LuaCallbacks, interrupt)) as i32,
55 ),
56 );
57 build.cbz(X2, &mut skip);
58
59 build.add_register_a_64_register_a_64_register_a_64_i32(X0, R_CODE, X0, 0);
60 build.ldr(
61 X1,
62 mem(R_STATE, core::mem::offset_of!(lua_State, ci) as i32),
63 );
64 build.str(X0, mem(X1, core::mem::offset_of!(CallInfo, savedpc) as i32));
65
66 build.mov_register_a_64_register_a_64(X0, R_STATE);
67 build.mov_register_a_64_i32(W1, -1);
68 build.blr(X2);
69
70 build.ldrb(
71 W0,
72 mem(R_STATE, core::mem::offset_of!(lua_State, status) as i32),
73 );
74 build.cbz(W0, &mut skip);
75
76 build.ldr(
77 X1,
78 mem(R_STATE, core::mem::offset_of!(lua_State, ci) as i32),
79 );
80 build.ldr(X0, mem(X1, core::mem::offset_of!(CallInfo, savedpc) as i32));
81 build.sub_register_a_64_register_a_64_u16(X0, X0, SIZEOF_INSTRUCTION);
82 build.str(X0, mem(X1, core::mem::offset_of!(CallInfo, savedpc) as i32));
83
84 emit_exit_assembly_builder_a_64_bool(build, false);
85
86 build.set_label_label(&mut skip);
87
88 build.mov_register_a_64_register_a_64(X0, R_BASE);
89 emit_update_base(build);
90 build.br(X0);
91}