Skip to content

Instantly share code, notes, and snippets.

@feliwir
Created November 9, 2023 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save feliwir/f90ee4a62550657ef646df137f91e170 to your computer and use it in GitHub Desktop.
Save feliwir/f90ee4a62550657ef646df137f91e170 to your computer and use it in GitHub Desktop.
template<typename CodegenI32, typename CodegenDouble>
void Compiler::branch_if_both_numbers(Assembler::Reg lhs, Assembler::Reg rhs, CodegenI32 codegen_i32, CodegenDouble codegen_double)
{
Assembler::Label end {};
// The only case where we can take the int32 fastpath
branch_if_both_int32(lhs, rhs, [&] {
codegen_i32(lhs, rhs);
});
// check if lhs is int32
Assembler::Label rhs_check {};
Assembler::Label lhs_is_int32 {};
Assembler::Label double_check {};
jump_if_int32(lhs, lhs_is_int32);
// lhs is not int32, store it to GPR0
m_assembler.mov(
Assembler::Operand::Register(GPR0),
Assembler::Operand::Register(lhs));
m_assembler.jump(rhs_check);
// lhs is int32, convert lhs to double and store it to GPR0
lhs_is_int32.link(m_assembler);
m_assembler.convert_to_double(
Assembler::Operand::FloatRegister(FPR0),
Assembler::Operand::Register(lhs));
m_assembler.mov(
Assembler::Operand::Register(GPR0),
Assembler::Operand::FloatRegister(FPR0));
// check if rhs is int32
rhs_check.link(m_assembler);
Assembler::Label rhs_is_int32 {};
jump_if_int32(rhs, rhs_is_int32);
// rhs is not int32, store it to GPR1
m_assembler.mov(
Assembler::Operand::Register(GPR1),
Assembler::Operand::Register(rhs));
m_assembler.jump(double_check);
// rhs is int32, convert rhs to double and store it to GPR1
rhs_is_int32.link(m_assembler);
m_assembler.convert_to_double(
Assembler::Operand::FloatRegister(FPR1),
Assembler::Operand::Register(rhs));
m_assembler.mov(
Assembler::Operand::Register(GPR1),
Assembler::Operand::FloatRegister(FPR1));
// If we reach this point, both lhs and rhs should be doubles (if numbers)
// GPR2 = CANON_NAN_BITS
double_check.link(m_assembler);
m_assembler.mov(Assembler::Operand::Register(GPR2), Assembler::Operand::Imm(CANON_NAN_BITS));
jump_if_not_double(GPR0, GPR2, end);
jump_if_not_double(GPR1, GPR2, end);
m_assembler.trap();
// Both are doubles, call codegen_double
m_assembler.mov(
Assembler::Operand::FloatRegister(FPR0),
Assembler::Operand::Register(GPR0));
m_assembler.mov(
Assembler::Operand::FloatRegister(FPR1),
Assembler::Operand::Register(GPR1));
codegen_double(FPR0, FPR1);
end.link(m_assembler);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment