diff --git a/crates/polkavm/src/interpreter.rs b/crates/polkavm/src/interpreter.rs index cf25a8c5..61af6efe 100644 --- a/crates/polkavm/src/interpreter.rs +++ b/crates/polkavm/src/interpreter.rs @@ -1851,6 +1851,25 @@ macro_rules! define_interpreter { $body }}; + (@define $handler_name:ident $body:block $self:ident, $a0:ident: Reg, $a1:ident: u32, $a2:ident: Target) => {{ + impl Args { + pub fn $handler_name(a0: impl Into, a1: u32, a2: Target) -> Args { + Args { + a0: a0.into().to_u32(), + a1, + a2, + ..Args::default() + } + } + } + + let args = $self.inner.compiled_args[cast($self.inner.compiled_offset).to_usize()]; + let $a0 = transmute_reg(args.a0); + let $a1 = args.a1; + let $a2 = args.a2; + $body + }}; + (@define $handler_name:ident $body:block $self:ident, $a0:ident: Reg, $a1:ident: Reg, $a2:ident: Target) => {{ impl Args { pub fn $handler_name(a0: impl Into, a1: impl Into, a2: Target) -> Args { @@ -3707,6 +3726,15 @@ define_interpreter! { visitor.jump_indirect_impl::(program_counter, dynamic_address) } + fn load_imm_and_jump(visitor: &mut Visitor, ra: Reg, value: u32, target: Target) -> Option { + if DEBUG { + log::trace!("[{}]: {}", visitor.inner.compiled_offset, asm::load_imm_and_jump(ra, value, target)); + } + + visitor.set32::(ra, value); + Some(target) + } + fn unresolved_branch_less_unsigned(visitor: &mut Visitor, s1: Reg, s2: Reg, tt: ProgramCounter, tf: ProgramCounter) -> Option { handle_unresolved_branch!("(visitor: &mut Visitor, program_counter: ProgramCounter, ra: Reg, value: u32, jump_to: u32) -> Option { + if DEBUG { + log::trace!("[{}]: unresolved {}", visitor.inner.compiled_offset, asm::load_imm_and_jump(ra, value, jump_to)); + } + + visitor.set32::(ra, value); + + let offset = visitor.inner.compiled_offset; + if let Some(target) = visitor.inner.resolve_jump::(ProgramCounter(jump_to)) { + if DEBUG { + log::trace!(" -> resolved to jump"); + } + visitor.inner.compiled_handlers[cast(offset).to_usize()] = cast_handler!(raw_handlers::load_imm_and_jump::); + visitor.inner.compiled_args[cast(offset).to_usize()] = Args::load_imm_and_jump(ra, value, target); + + Some(target) + } else { + if DEBUG { + log::trace!(" -> resolved to trap"); + } + trap_impl::(visitor, program_counter) + } + } + fn unresolved_fallthrough(visitor: &mut Visitor, jump_to: ProgramCounter) -> Option { if DEBUG { log::trace!("[{}]: unresolved fallthrough {jump_to}", visitor.inner.compiled_offset); @@ -4625,8 +4677,7 @@ impl<'a, const DEBUG: bool> InstructionVisitor for Compiler<'a, DEBUG> { } fn load_imm_and_jump(&mut self, dst: RawReg, imm: u32, target: u32) -> Self::ReturnTy { - emit!(self, load_imm(dst, imm)); - emit!(self, unresolved_jump(self.program_counter, ProgramCounter(target))); + emit!(self, unresolved_load_imm_and_jump(self.program_counter, dst, imm, target)); } fn load_imm_and_jump_indirect(&mut self, ra: RawReg, base: RawReg, value: u32, offset: u32) -> Self::ReturnTy {