void reboxAccordingToFormat(
    ValueFormat format, AssemblyHelpers& jit, GPRReg value, GPRReg scratch1, GPRReg scratch2)
{
    switch (format) {
    case ValueFormatInt32: {
        jit.zeroExtend32ToPtr(value, value);
        jit.or64(GPRInfo::tagTypeNumberRegister, value);
        break;
    }
    
    case ValueFormatUInt32: {
        jit.zeroExtend32ToPtr(value, value);
        jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
        jit.boxInt52(value, value, scratch1, FPRInfo::fpRegT0);
        jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
        break;
    }
    
    case ValueFormatInt52: {
        jit.rshift64(AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), value);
        jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
        jit.boxInt52(value, value, scratch1, FPRInfo::fpRegT0);
        jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
        break;
    }
    
    case ValueFormatStrictInt52: {
        jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
        jit.boxInt52(value, value, scratch1, FPRInfo::fpRegT0);
        jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
        break;
    }
    
    case ValueFormatBoolean: {
        jit.zeroExtend32ToPtr(value, value);
        jit.or32(MacroAssembler::TrustedImm32(ValueFalse), value);
        break;
    }
    
    case ValueFormatJSValue: {
        // Done already!
        break;
    }
    
    case ValueFormatDouble: {
        jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch1);
        jit.move64ToDouble(value, FPRInfo::fpRegT0);
        jit.boxDouble(FPRInfo::fpRegT0, value);
        jit.move64ToDouble(scratch1, FPRInfo::fpRegT0);
        break;
    }
    
    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}
static void registerClobberCheck(AssemblyHelpers& jit, RegisterSet dontClobber)
{
    if (!Options::clobberAllRegsInFTLICSlowPath())
        return;
    
    RegisterSet clobber = RegisterSet::allRegisters();
    clobber.exclude(RegisterSet::reservedHardwareRegisters());
    clobber.exclude(RegisterSet::stackRegisters());
    clobber.exclude(RegisterSet::calleeSaveRegisters());
    clobber.exclude(dontClobber);
    
    GPRReg someGPR;
    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!clobber.get(reg) || !reg.isGPR())
            continue;
        
        jit.move(AssemblyHelpers::TrustedImm32(0x1337beef), reg.gpr());
        someGPR = reg.gpr();
    }
    
    for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
        if (!clobber.get(reg) || !reg.isFPR())
            continue;
        
        jit.move64ToDouble(someGPR, reg.fpr());
    }
}
void ValueRep::emitRestore(AssemblyHelpers& jit, Reg reg) const
{
    if (reg.isGPR()) {
        switch (kind()) {
        case LateRegister:
        case Register:
            if (isGPR())
                jit.move(gpr(), reg.gpr());
            else
                jit.moveDoubleTo64(fpr(), reg.gpr());
            break;
        case Stack:
            jit.load64(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.gpr());
            break;
        case Constant:
            jit.move(AssemblyHelpers::TrustedImm64(value()), reg.gpr());
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        return;
    }

    switch (kind()) {
    case LateRegister:
    case Register:
        if (isGPR())
            jit.move64ToDouble(gpr(), reg.fpr());
        else
            jit.moveDouble(fpr(), reg.fpr());
        break;
    case Stack:
        jit.loadDouble(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.fpr());
        break;
    case Constant:
        jit.move(AssemblyHelpers::TrustedImm64(value()), jit.scratchRegister());
        jit.move64ToDouble(jit.scratchRegister(), reg.fpr());
        break;
    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}