Ignore:
Timestamp:
May 15, 2009, 2:11:10 PM (16 years ago)
Author:
[email protected]
Message:

2009-05-15 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Add FP support to the MacroAssembler, port JITArithmetic over to make use of this. Also add
API to determine whether FP support is available 'MacroAssembler::supportsFloatingPoint()',
FP is presently only supported on SSE2 platforms, not x87. On platforms where a suitable
hardware FPU is not available 'supportsFloatingPoint()' may simply return false, and all
other methods ASSERT_NOT_REACHED().

  • assembler/AbstractMacroAssembler.h:
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::MacroAssemblerX86): (JSC::MacroAssemblerX86::branch32): (JSC::MacroAssemblerX86::branchPtrWithPatch): (JSC::MacroAssemblerX86::supportsFloatingPoint):
  • assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::): (JSC::MacroAssemblerX86Common::loadDouble): (JSC::MacroAssemblerX86Common::storeDouble): (JSC::MacroAssemblerX86Common::addDouble): (JSC::MacroAssemblerX86Common::subDouble): (JSC::MacroAssemblerX86Common::mulDouble): (JSC::MacroAssemblerX86Common::convertInt32ToDouble): (JSC::MacroAssemblerX86Common::branchDouble): (JSC::MacroAssemblerX86Common::branchTruncateDoubleToInt32): (JSC::MacroAssemblerX86Common::branch32): (JSC::MacroAssemblerX86Common::branch16): (JSC::MacroAssemblerX86Common::branchTest32): (JSC::MacroAssemblerX86Common::branchAdd32): (JSC::MacroAssemblerX86Common::branchMul32): (JSC::MacroAssemblerX86Common::branchSub32): (JSC::MacroAssemblerX86Common::set32): (JSC::MacroAssemblerX86Common::setTest32): (JSC::MacroAssemblerX86Common::x86Condition): (JSC::MacroAssemblerX86Common::isSSE2Present):
  • assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::movePtrToDouble): (JSC::MacroAssemblerX86_64::moveDoubleToPtr): (JSC::MacroAssemblerX86_64::setPtr): (JSC::MacroAssemblerX86_64::branchPtr): (JSC::MacroAssemblerX86_64::branchTestPtr): (JSC::MacroAssemblerX86_64::branchAddPtr): (JSC::MacroAssemblerX86_64::branchSubPtr): (JSC::MacroAssemblerX86_64::supportsFloatingPoint):
  • assembler/X86Assembler.h:
  • jit/JIT.cpp: (JSC::JIT::JIT):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::emit_op_rshift): (JSC::JIT::emitSlow_op_rshift): (JSC::JIT::emitSlow_op_jnless): (JSC::JIT::emitSlow_op_jnlesseq): (JSC::JIT::compileBinaryArithOp): (JSC::JIT::compileBinaryArithOpSlowCase): (JSC::JIT::emit_op_add): (JSC::JIT::emitSlow_op_add): (JSC::JIT::emit_op_mul): (JSC::JIT::emitSlow_op_mul):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompilePutByIdTransition):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r43619 r43781  
    3939public:
    4040
    41     typedef X86Assembler::Condition Condition;
    42     static const Condition Equal = X86Assembler::ConditionE;
    43     static const Condition NotEqual = X86Assembler::ConditionNE;
    44     static const Condition Above = X86Assembler::ConditionA;
    45     static const Condition AboveOrEqual = X86Assembler::ConditionAE;
    46     static const Condition Below = X86Assembler::ConditionB;
    47     static const Condition BelowOrEqual = X86Assembler::ConditionBE;
    48     static const Condition GreaterThan = X86Assembler::ConditionG;
    49     static const Condition GreaterThanOrEqual = X86Assembler::ConditionGE;
    50     static const Condition LessThan = X86Assembler::ConditionL;
    51     static const Condition LessThanOrEqual = X86Assembler::ConditionLE;
    52     static const Condition Overflow = X86Assembler::ConditionO;
    53     static const Condition Zero = X86Assembler::ConditionE;
    54     static const Condition NonZero = X86Assembler::ConditionNE;
     41    enum Condition {
     42        Equal = X86Assembler::ConditionE,
     43        NotEqual = X86Assembler::ConditionNE,
     44        Above = X86Assembler::ConditionA,
     45        AboveOrEqual = X86Assembler::ConditionAE,
     46        Below = X86Assembler::ConditionB,
     47        BelowOrEqual = X86Assembler::ConditionBE,
     48        GreaterThan = X86Assembler::ConditionG,
     49        GreaterThanOrEqual = X86Assembler::ConditionGE,
     50        LessThan = X86Assembler::ConditionL,
     51        LessThanOrEqual = X86Assembler::ConditionLE,
     52        Overflow = X86Assembler::ConditionO,
     53        Signed = X86Assembler::ConditionS,
     54        Zero = X86Assembler::ConditionE,
     55        NonZero = X86Assembler::ConditionNE
     56    };
     57
     58    enum DoubleCondition {
     59        DoubleEqual = X86Assembler::ConditionE,
     60        DoubleNotEqual = X86Assembler::ConditionNE,
     61        DoubleGreaterThan = X86Assembler::ConditionA,
     62        DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
     63        DoubleLessThan = X86Assembler::ConditionB,
     64        DoubleLessThanOrEqual = X86Assembler::ConditionBE,
     65    };
    5566
    5667    static const RegisterID stackPointerRegister = X86::esp;
     
    261272        m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
    262273    }
    263    
     274
     275
     276    // Floating-point operation:
     277    //
     278    // Presently only supports SSE, not x87 floating point.
     279
     280    void loadDouble(ImplicitAddress address, FPRegisterID dest)
     281    {
     282        ASSERT(isSSE2Present());
     283        m_assembler.movsd_mr(address.offset, address.base, dest);
     284    }
     285
     286    void storeDouble(FPRegisterID src, ImplicitAddress address)
     287    {
     288        ASSERT(isSSE2Present());
     289        m_assembler.movsd_rm(src, address.offset, address.base);
     290    }
     291
     292    void addDouble(FPRegisterID src, FPRegisterID dest)
     293    {
     294        ASSERT(isSSE2Present());
     295        m_assembler.addsd_rr(src, dest);
     296    }
     297
     298    void addDouble(Address src, FPRegisterID dest)
     299    {
     300        ASSERT(isSSE2Present());
     301        m_assembler.addsd_mr(src.offset, src.base, dest);
     302    }
     303
     304    void subDouble(FPRegisterID src, FPRegisterID dest)
     305    {
     306        ASSERT(isSSE2Present());
     307        m_assembler.subsd_rr(src, dest);
     308    }
     309
     310    void subDouble(Address src, FPRegisterID dest)
     311    {
     312        ASSERT(isSSE2Present());
     313        m_assembler.subsd_mr(src.offset, src.base, dest);
     314    }
     315
     316    void mulDouble(FPRegisterID src, FPRegisterID dest)
     317    {
     318        ASSERT(isSSE2Present());
     319        m_assembler.mulsd_rr(src, dest);
     320    }
     321
     322    void mulDouble(Address src, FPRegisterID dest)
     323    {
     324        ASSERT(isSSE2Present());
     325        m_assembler.mulsd_mr(src.offset, src.base, dest);
     326    }
     327
     328    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     329    {
     330        m_assembler.cvtsi2sd_rr(src, dest);
     331    }
     332
     333    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     334    {
     335        m_assembler.ucomisd_rr(right, left);
     336        return Jump(m_assembler.jCC(x86Condition(cond)));
     337    }
     338
     339    // Truncates 'src' to an integer, and places the resulting 'dest'.
     340    // If the result is not representable as a 32 bit value, branch.
     341    // May also branch for some values that are representable in 32 bits
     342    // (specifically, in this case, INT_MIN).
     343    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     344    {
     345        m_assembler.cvttsd2si_rr(src, dest);
     346        return branch32(Equal, dest, Imm32(0x80000000));
     347    }
     348
    264349
    265350    // Stack manipulation operations:
     
    290375        m_assembler.push_i32(imm.m_value);
    291376    }
     377
    292378
    293379    // Register move operations:
     
    387473    {
    388474        m_assembler.cmpl_rr(right, left);
    389         return Jump(m_assembler.jCC(cond));
     475        return Jump(m_assembler.jCC(x86Condition(cond)));
    390476    }
    391477
     
    396482        else
    397483            m_assembler.cmpl_ir(right.m_value, left);
    398         return Jump(m_assembler.jCC(cond));
     484        return Jump(m_assembler.jCC(x86Condition(cond)));
    399485    }
    400486   
     
    402488    {
    403489        m_assembler.cmpl_mr(right.offset, right.base, left);
    404         return Jump(m_assembler.jCC(cond));
     490        return Jump(m_assembler.jCC(x86Condition(cond)));
    405491    }
    406492   
     
    408494    {
    409495        m_assembler.cmpl_rm(right, left.offset, left.base);
    410         return Jump(m_assembler.jCC(cond));
     496        return Jump(m_assembler.jCC(x86Condition(cond)));
    411497    }
    412498
     
    414500    {
    415501        m_assembler.cmpl_im(right.m_value, left.offset, left.base);
    416         return Jump(m_assembler.jCC(cond));
     502        return Jump(m_assembler.jCC(x86Condition(cond)));
    417503    }
    418504
     
    420506    {
    421507        m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
    422         return Jump(m_assembler.jCC(cond));
     508        return Jump(m_assembler.jCC(x86Condition(cond)));
    423509    }
    424510
     
    426512    {
    427513        m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
    428         return Jump(m_assembler.jCC(cond));
     514        return Jump(m_assembler.jCC(x86Condition(cond)));
    429515    }
    430516
     
    434520
    435521        m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
    436         return Jump(m_assembler.jCC(cond));
     522        return Jump(m_assembler.jCC(x86Condition(cond)));
    437523    }
    438524
     
    441527        ASSERT((cond == Zero) || (cond == NonZero));
    442528        m_assembler.testl_rr(reg, mask);
    443         return Jump(m_assembler.jCC(cond));
     529        return Jump(m_assembler.jCC(x86Condition(cond)));
    444530    }
    445531
     
    454540        else
    455541            m_assembler.testl_i32r(mask.m_value, reg);
    456         return Jump(m_assembler.jCC(cond));
     542        return Jump(m_assembler.jCC(x86Condition(cond)));
    457543    }
    458544
     
    464550        else
    465551            m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
    466         return Jump(m_assembler.jCC(cond));
     552        return Jump(m_assembler.jCC(x86Condition(cond)));
    467553    }
    468554
     
    474560        else
    475561            m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
    476         return Jump(m_assembler.jCC(cond));
     562        return Jump(m_assembler.jCC(x86Condition(cond)));
    477563    }
    478564
     
    506592    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
    507593    {
    508         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
     594        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
    509595        add32(src, dest);
    510         return Jump(m_assembler.jCC(cond));
    511     }
    512    
     596        return Jump(m_assembler.jCC(x86Condition(cond)));
     597    }
     598
    513599    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
    514600    {
    515601        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    516602        add32(imm, dest);
    517         return Jump(m_assembler.jCC(cond));
     603        return Jump(m_assembler.jCC(x86Condition(cond)));
    518604    }
    519605   
     
    522608        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    523609        mul32(src, dest);
    524         return Jump(m_assembler.jCC(cond));
     610        return Jump(m_assembler.jCC(x86Condition(cond)));
    525611    }
    526612   
     
    529615        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    530616        mul32(imm, src, dest);
    531         return Jump(m_assembler.jCC(cond));
     617        return Jump(m_assembler.jCC(x86Condition(cond)));
    532618    }
    533619   
     
    536622        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    537623        sub32(src, dest);
    538         return Jump(m_assembler.jCC(cond));
     624        return Jump(m_assembler.jCC(x86Condition(cond)));
    539625    }
    540626   
     
    543629        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
    544630        sub32(imm, dest);
    545         return Jump(m_assembler.jCC(cond));
     631        return Jump(m_assembler.jCC(x86Condition(cond)));
    546632    }
    547633   
     
    577663    {
    578664        m_assembler.cmpl_rr(right, left);
    579         m_assembler.setCC_r(cond, dest);
     665        m_assembler.setCC_r(x86Condition(cond), dest);
    580666        m_assembler.movzbl_rr(dest, dest);
    581667    }
     
    587673        else
    588674            m_assembler.cmpl_ir(right.m_value, left);
    589         m_assembler.setCC_r(cond, dest);
     675        m_assembler.setCC_r(x86Condition(cond), dest);
    590676        m_assembler.movzbl_rr(dest, dest);
    591677    }
     
    601687        else
    602688            m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
    603         m_assembler.setCC_r(cond, dest);
     689        m_assembler.setCC_r(x86Condition(cond), dest);
    604690        m_assembler.movzbl_rr(dest, dest);
    605691    }
     692
     693protected:
     694    X86Assembler::Condition x86Condition(Condition cond)
     695    {
     696        return static_cast<X86Assembler::Condition>(cond);
     697    }
     698
     699    X86Assembler::Condition x86Condition(DoubleCondition cond)
     700    {
     701        return static_cast<X86Assembler::Condition>(cond);
     702    }
     703
     704private:
     705    // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
     706    // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
     707    friend class MacroAssemblerX86;
     708
     709#if PLATFORM(X86_64)
     710#ifndef NDEBUG
     711    static bool isSSE2Present() { return true; }
     712#endif
     713#else
     714    static bool isSSE2Present()
     715    {
     716#if PLATFORM(MAC)
     717        // All X86 Macs are guaranteed to support at least SSE2
     718        return true;
     719#else
     720        static const int SSE2FeatureBit = 1 << 26;
     721        struct SSE2Check {
     722            SSE2Check()
     723            {
     724                int flags;
     725#if COMPILER(MSVC)
     726                _asm {
     727                    mov eax, 1 // cpuid function 1 gives us the standard feature set
     728                    cpuid;
     729                    mov flags, edx;
     730                }
     731#elif COMPILER(GCC)
     732                asm (
     733                     "movl $0x1, %%eax;"
     734                     "pushl %%ebx;"
     735                     "cpuid;"
     736                     "popl %%ebx;"
     737                     "movl %%edx, %0;"
     738                     : "=g" (flags)
     739                     :
     740                     : "%eax", "%ecx", "%edx"
     741                     );
     742#else
     743                flags = 0;
     744#endif
     745                present = (flags & SSE2FeatureBit) != 0;
     746            }
     747            bool present;
     748        };
     749        static SSE2Check check;
     750        return check.present;
     751#endif // !PLATFORM(MAC)
     752    }
     753#endif
    606754};
    607755
Note: See TracChangeset for help on using the changeset viewer.