Example #1
0
void
CodeGeneratorX86::visitDivOrModI64(LDivOrModI64* lir)
{
    Register64 lhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Lhs));
    Register64 rhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Rhs));
    Register temp = ToRegister(lir->temp());
    Register64 output = ToOutRegister64(lir);

    MOZ_ASSERT(output == ReturnReg64);

    Label done;

    // Handle divide by zero.
    if (lir->canBeDivideByZero())
        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));

    MDefinition* mir = lir->mir();

    // Handle an integer overflow exception from INT64_MIN / -1.
    if (lir->canBeNegativeOverflow()) {
        Label notmin;
        masm.branch64(Assembler::NotEqual, lhs, Imm64(INT64_MIN), &notmin);
        masm.branch64(Assembler::NotEqual, rhs, Imm64(-1), &notmin);
        if (mir->isMod())
            masm.xor64(output, output);
        else
            masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
        masm.jump(&done);
        masm.bind(&notmin);
    }

    masm.setupWasmABICall();
    masm.passABIArg(lhs.high);
    masm.passABIArg(lhs.low);
    masm.passABIArg(rhs.high);
    masm.passABIArg(rhs.low);

    MOZ_ASSERT(gen->compilingWasm());
    if (mir->isMod())
        masm.callWithABI(lir->bytecodeOffset(), wasm::SymbolicAddress::ModI64);
    else
        masm.callWithABI(lir->bytecodeOffset(), wasm::SymbolicAddress::DivI64);

    // output in edx:eax, move to output register.
    masm.movl(edx, output.high);
    MOZ_ASSERT(eax == output.low);

    masm.bind(&done);
}
Example #2
0
void
CodeGeneratorX86::visitUDivOrModI64(LUDivOrModI64* lir)
{
    Register64 lhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Lhs));
    Register64 rhs = ToRegister64(lir->getInt64Operand(LDivOrModI64::Rhs));
    Register temp = ToRegister(lir->temp());
    Register64 output = ToOutRegister64(lir);

    MOZ_ASSERT(output == ReturnReg64);

    // Prevent divide by zero.
    if (lir->canBeDivideByZero())
        masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));

    masm.setupWasmABICall();
    masm.passABIArg(lhs.high);
    masm.passABIArg(lhs.low);
    masm.passABIArg(rhs.high);
    masm.passABIArg(rhs.low);

    MOZ_ASSERT(gen->compilingWasm());
    MDefinition* mir = lir->mir();
    if (mir->isMod())
        masm.callWithABI(lir->bytecodeOffset(), wasm::SymbolicAddress::UModI64);
    else
        masm.callWithABI(lir->bytecodeOffset(), wasm::SymbolicAddress::UDivI64);

    // output in edx:eax, move to output register.
    masm.movl(edx, output.high);
    MOZ_ASSERT(eax == output.low);
}