Ignore:
Timestamp:
Dec 8, 2008, 6:10:41 PM (16 years ago)
Author:
[email protected]
Message:

2008-12-08 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

Expand MacroAssembler to support more operations, required by the JIT.

Generally adds more operations and permutations of operands to the existing
interface. Rename 'jset' to 'jnz' and 'jnset' to 'jz', which seem clearer,
and require that immediate pointer operands (though not pointer addresses to
load and store instructions) are wrapped in a ImmPtr() type, akin to Imm32().

No performance impact.

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::): (JSC::MacroAssembler::ImmPtr::ImmPtr): (JSC::MacroAssembler::add32): (JSC::MacroAssembler::and32): (JSC::MacroAssembler::or32): (JSC::MacroAssembler::sub32): (JSC::MacroAssembler::xor32): (JSC::MacroAssembler::loadPtr): (JSC::MacroAssembler::load32): (JSC::MacroAssembler::storePtr): (JSC::MacroAssembler::store32): (JSC::MacroAssembler::poke): (JSC::MacroAssembler::move): (JSC::MacroAssembler::testImm32): (JSC::MacroAssembler::jae32): (JSC::MacroAssembler::jb32): (JSC::MacroAssembler::jePtr): (JSC::MacroAssembler::je32): (JSC::MacroAssembler::jnePtr): (JSC::MacroAssembler::jne32): (JSC::MacroAssembler::jnzPtr): (JSC::MacroAssembler::jnz32): (JSC::MacroAssembler::jzPtr): (JSC::MacroAssembler::jz32): (JSC::MacroAssembler::joSub32): (JSC::MacroAssembler::jump): (JSC::MacroAssembler::sete32): (JSC::MacroAssembler::setne32): (JSC::MacroAssembler::setnz32): (JSC::MacroAssembler::setz32):
  • assembler/X86Assembler.h: (JSC::X86Assembler::addl_mr): (JSC::X86Assembler::andl_i8r): (JSC::X86Assembler::cmpl_rm): (JSC::X86Assembler::cmpl_mr): (JSC::X86Assembler::cmpl_i8m): (JSC::X86Assembler::subl_mr): (JSC::X86Assembler::testl_i32m): (JSC::X86Assembler::xorl_i32r): (JSC::X86Assembler::movl_rm): (JSC::X86Assembler::modRm_opmsib):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITInlineMethods.h: (JSC::JIT::emitGetVirtualRegister): (JSC::JIT::emitPutCTIArgConstant): (JSC::JIT::emitPutCTIParam): (JSC::JIT::emitPutImmediateToCallFrameHeader): (JSC::JIT::emitInitRegister): (JSC::JIT::checkStructure): (JSC::JIT::emitJumpIfJSCell): (JSC::JIT::emitJumpIfNotJSCell): (JSC::JIT::emitJumpSlowCaseIfNotImmNum):
File:
1 edited

Legend:

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

    r39083 r39121  
    4747        TimesTwo = 2,
    4848        TimesFour = 4,
    49         TimesEight = 8
     49        TimesEight = 8,
     50#if PLATFORM(X86)
     51        ScalePtr = TimesFour
     52#endif
     53#if PLATFORM(X86_64)
     54        ScalePtr = TimesEight
     55#endif
    5056    };
    5157
     
    249255
    250256
     257    // ImmPtr:
     258    //
     259    // A pointer sized immediate operand to an instruction - this is wrapped
     260    // in a class requiring explicit construction in order to differentiate
     261    // from pointers used as absolute addresses to memory operations
     262    struct ImmPtr {
     263        explicit ImmPtr(void* value)
     264            : m_value(value)
     265        {
     266        }
     267
     268        void* m_value;
     269    };
     270
     271
    251272    // Integer arithmetic operations:
    252273    //
     
    286307    void add32(Address src, RegisterID dest)
    287308    {
    288         m_assembler.addl_mr(src.offset, src.base, dest);
     309        if (src.offset)
     310            m_assembler.addl_mr(src.offset, src.base, dest);
     311        else
     312            m_assembler.addl_mr(src.base, dest);
    289313    }
    290314   
     
    294318    }
    295319
     320    void and32(Imm32 imm, RegisterID dest)
     321    {
     322        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
     323            m_assembler.andl_i8r(imm.m_value, dest);
     324        else
     325            m_assembler.andl_i32r(imm.m_value, dest);
     326    }
     327
    296328    void lshift32(Imm32 imm, RegisterID dest)
    297329    {
     
    304336    }
    305337   
     338    void or32(RegisterID src, RegisterID dest)
     339    {
     340        m_assembler.orl_rr(src, dest);
     341    }
     342
    306343    void or32(Imm32 imm, RegisterID dest)
    307344    {
     
    327364    void sub32(Address src, RegisterID dest)
    328365    {
    329         m_assembler.subl_mr(src.offset, src.base, dest);
    330     }
    331 
     366        if (src.offset)
     367            m_assembler.subl_mr(src.offset, src.base, dest);
     368        else
     369            m_assembler.subl_mr(src.base, dest);
     370    }
     371
     372    void xor32(RegisterID src, RegisterID dest)
     373    {
     374        m_assembler.xorl_rr(src, dest);
     375    }
     376
     377    void xor32(Imm32 imm, RegisterID dest)
     378    {
     379        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
     380            m_assembler.xorl_i8r(imm.m_value, dest);
     381        else
     382            m_assembler.xorl_i32r(imm.m_value, dest);
     383    }
     384   
    332385
    333386    // Memory access operations:
     
    346399            m_assembler.movq_mr(address.base, dest);
    347400#else
     401    load32(address, dest);
     402#endif
     403    }
     404
     405#if !PLATFORM(X86_64)
     406    void loadPtr(BaseIndex address, RegisterID dest)
     407    {
     408        load32(address, dest);
     409    }
     410
     411    void loadPtr(void* address, RegisterID dest)
     412    {
     413        load32(address, dest);
     414    }
     415#endif
     416
     417    void load32(ImplicitAddress address, RegisterID dest)
     418    {
    348419        if (address.offset)
    349420            m_assembler.movl_mr(address.offset, address.base, dest);
    350421        else
    351422            m_assembler.movl_mr(address.base, dest);
    352 #endif
    353     }
    354 
    355     void load32(ImplicitAddress address, RegisterID dest)
    356     {
    357         if (address.offset)
    358             m_assembler.movl_mr(address.offset, address.base, dest);
    359         else
    360             m_assembler.movl_mr(address.base, dest);
    361423    }
    362424
     
    368430            m_assembler.movl_mr(address.base, address.index, address.scale, dest);
    369431    }
     432
     433#if !PLATFORM(X86_64)
     434    void load32(void* address, RegisterID dest)
     435    {
     436        m_assembler.movl_mr(address, dest);
     437    }
     438#endif
    370439
    371440    void load16(BaseIndex address, RegisterID dest)
     
    393462   
    394463#if !PLATFORM(X86_64)
    395     void storePtr(void* value, ImplicitAddress address)
    396     {
    397         if (address.offset)
    398             m_assembler.movl_i32m(reinterpret_cast<unsigned>(value), address.offset, address.base);
    399         else
    400             m_assembler.movl_i32m(reinterpret_cast<unsigned>(value), address.base);
     464    void storePtr(ImmPtr imm, ImplicitAddress address)
     465    {
     466        if (address.offset)
     467            m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.offset, address.base);
     468        else
     469            m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.base);
     470    }
     471
     472    void storePtr(RegisterID src, BaseIndex address)
     473    {
     474        store32(src, address);
    401475    }
    402476#endif
     
    409483            m_assembler.movl_rm(src, address.base);
    410484    }
    411    
     485
     486    void store32(RegisterID src, BaseIndex address)
     487    {
     488        if (address.offset)
     489            m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
     490        else
     491            m_assembler.movl_rm(src, address.base, address.index, address.scale);
     492    }
     493
    412494    void store32(Imm32 imm, ImplicitAddress address)
    413495    {
     
    473555
    474556#if !PLATFORM(X86_64)
    475     void poke(void* value, int index = 0)
    476     {
    477         storePtr(value, Address(X86::esp, (index * sizeof(void *))));
     557    void poke(ImmPtr imm, int index = 0)
     558    {
     559        storePtr(imm, Address(X86::esp, (index * sizeof(void *))));
    478560    }
    479561#endif
     
    505587
    506588#if !PLATFORM(X86_64)
    507     void move(void* value, RegisterID dest)
    508     {
    509         m_assembler.movl_i32r(reinterpret_cast<int32_t>(value), dest);
     589    void move(ImmPtr imm, RegisterID dest)
     590    {
     591        m_assembler.movl_i32r(reinterpret_cast<int32_t>(imm.m_value), dest);
    510592    }
    511593#endif
     
    526608    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
    527609    // treated as a signed 32bit value, is less than or equal to 5.
     610    //
     611    // jz and jnz test whether the first operand is equal to zero, and take
     612    // an optional second operand of a mask under which to perform the test.
    528613
    529614private:
     
    561646    }
    562647
     648    void testImm32(RegisterID reg, Imm32 mask)
     649    {
     650        // if we are only interested in the low seven bits, this can be tested with a testb
     651        if (mask.m_value == -1)
     652            m_assembler.testl_rr(reg, reg);
     653        else if ((mask.m_value & ~0x7f) == 0)
     654            m_assembler.testb_i8r(mask.m_value, reg);
     655        else
     656            m_assembler.testl_i32r(mask.m_value, reg);
     657    }
     658
     659    void testImm32(Address address, Imm32 mask)
     660    {
     661        if (address.offset) {
     662            if (mask.m_value == -1)
     663                m_assembler.cmpl_i8m(0, address.offset, address.base);
     664            else
     665                m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
     666        } else {
     667            if (mask.m_value == -1)
     668                m_assembler.cmpl_i8m(0, address.base);
     669            else
     670                m_assembler.testl_i32m(mask.m_value, address.base);
     671        }
     672    }
     673
     674    void testImm32(BaseIndex address, Imm32 mask)
     675    {
     676        if (address.offset) {
     677            if (mask.m_value == -1)
     678                m_assembler.cmpl_i8m(0, address.offset, address.base, address.index, address.scale);
     679            else
     680                m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
     681        } else {
     682            if (mask.m_value == -1)
     683                m_assembler.cmpl_i8m(0, address.base, address.index, address.scale);
     684            else
     685                m_assembler.testl_i32m(mask.m_value, address.base, address.index, address.scale);
     686        }
     687    }
     688
    563689public:
    564690    Jump jae32(RegisterID left, Imm32 right)
     
    568694    }
    569695   
     696    Jump jae32(RegisterID left, Address right)
     697    {
     698        if (right.offset)
     699            m_assembler.cmpl_mr(right.offset, right.base, left);
     700        else
     701            m_assembler.cmpl_mr(right.base, left);
     702        return Jump(m_assembler.jae());
     703    }
     704   
     705    Jump jb32(RegisterID left, Address right)
     706    {
     707        if (right.offset)
     708            m_assembler.cmpl_mr(right.offset, right.base, left);
     709        else
     710            m_assembler.cmpl_mr(right.base, left);
     711        return Jump(m_assembler.jb());
     712    }
     713   
     714#if !PLATFORM(X86_64)
     715    Jump jePtr(RegisterID op1, RegisterID op2)
     716    {
     717        return je32(op1, op2);
     718    }
     719#endif
     720
    570721    Jump je32(RegisterID op1, RegisterID op2)
    571722    {
     
    585736        return Jump(m_assembler.je());
    586737    }
     738
     739    Jump je32(Address address, Imm32 imm)
     740    {
     741        compareImm32ForBranchEquality(address, imm.m_value);
     742        return Jump(m_assembler.je());
     743    }
    587744   
    588745    Jump je16(RegisterID op1, BaseIndex op2)
     
    639796
    640797#if !PLATFORM(X86_64)
    641     Jump jnePtr(void* ptr, Address address)
    642     {
    643         compareImm32ForBranchEquality(address, reinterpret_cast<uint32_t>(ptr));
     798    Jump jnePtr(RegisterID reg, Address address)
     799    {
     800        if (address.offset)
     801            m_assembler.cmpl_rm(reg, address.offset, address.base);
     802        else
     803            m_assembler.cmpl_rm(reg, address.base);
    644804        return Jump(m_assembler.jne());
     805    }
     806
     807    Jump jnePtr(Address address, ImmPtr imm)
     808    {
     809        return jne32(address, Imm32(reinterpret_cast<int32_t>(imm.m_value)));
    645810    }
    646811#endif
     
    658823    }
    659824
    660     Jump jnset32(Imm32 imm, RegisterID reg)
    661     {
    662         // if we are only interested in the low seven bits, this can be tested with a testb
    663         if ((imm.m_value & ~0x7f) == 0)
    664             m_assembler.testb_i8r(imm.m_value, reg);
    665         else
    666             m_assembler.testl_i32r(imm.m_value, reg);
     825    Jump jne32(Address address, Imm32 imm)
     826    {
     827        compareImm32ForBranchEquality(address, imm.m_value);
     828        return Jump(m_assembler.jne());
     829    }
     830   
     831    Jump jne32(Address address, RegisterID reg)
     832    {
     833        if (address.offset)
     834            m_assembler.cmpl_rm(reg, address.offset, address.base);
     835        else
     836            m_assembler.cmpl_rm(reg, address.base);
     837        return Jump(m_assembler.jne());
     838    }
     839   
     840#if !PLATFORM(X86_64)
     841    Jump jnzPtr(RegisterID reg, Imm32 mask = Imm32(-1))
     842    {
     843        return jnz32(reg, mask);
     844    }
     845#endif
     846
     847    Jump jnz32(RegisterID reg, Imm32 mask = Imm32(-1))
     848    {
     849        testImm32(reg, mask);
     850        return Jump(m_assembler.jne());
     851    }
     852
     853    Jump jnz32(Address address, Imm32 mask = Imm32(-1))
     854    {
     855        testImm32(address, mask);
     856        return Jump(m_assembler.jne());
     857    }
     858
     859#if !PLATFORM(X86_64)
     860    Jump jzPtr(RegisterID reg, Imm32 mask = Imm32(-1))
     861    {
     862        return jz32(reg, mask);
     863    }
     864
     865    Jump jzPtr(BaseIndex address, Imm32 mask = Imm32(-1))
     866    {
     867        return jz32(address, mask);
     868    }
     869#endif
     870
     871    Jump jz32(RegisterID reg, Imm32 mask = Imm32(-1))
     872    {
     873        testImm32(reg, mask);
    667874        return Jump(m_assembler.je());
    668875    }
    669876
    670     Jump jset32(Imm32 imm, RegisterID reg)
    671     {
    672         // if we are only interested in the low seven bits, this can be tested with a testb
    673         if ((imm.m_value & ~0x7f) == 0)
    674             m_assembler.testb_i8r(imm.m_value, reg);
    675         else
    676             m_assembler.testl_i32r(imm.m_value, reg);
    677         return Jump(m_assembler.jne());
     877    Jump jz32(Address address, Imm32 mask = Imm32(-1))
     878    {
     879        testImm32(address, mask);
     880        return Jump(m_assembler.je());
     881    }
     882
     883    Jump jz32(BaseIndex address, Imm32 mask = Imm32(-1))
     884    {
     885        testImm32(address, mask);
     886        return Jump(m_assembler.je());
    678887    }
    679888
     
    774983    }
    775984   
     985    Jump joSub32(Imm32 imm, RegisterID dest)
     986    {
     987        sub32(imm, dest);
     988        return Jump(m_assembler.jo());
     989    }
     990   
    776991    Jump jzSub32(Imm32 imm, RegisterID dest)
    777992    {
     
    7931008    }
    7941009
     1010    // FIXME: why does this return a Jump object? - it can't be linked.
     1011    // This may be to get a reference to the return address of the call.
     1012    //
     1013    // This should probably be handled by a separate label type to a regular
     1014    // jump.  Todo: add a CallLabel type, for the regular call - can be linked
     1015    // like a jump (possibly a subclass of jump?, or possibly casts to a Jump).
     1016    // Also add a CallReturnLabel type for this to return (just a more JmpDsty
     1017    // form of label, can get the void* after the code has been linked, but can't
     1018    // try to link it like a Jump object), and let the CallLabel be cast into a
     1019    // CallReturnLabel.
    7951020    Jump call(RegisterID target)
    7961021    {
     
    7981023    }
    7991024
     1025    void jump(RegisterID target)
     1026    {
     1027        m_assembler.jmp_r(target);
     1028    }
     1029
    8001030    void ret()
    8011031    {
    8021032        m_assembler.ret();
    8031033    }
     1034
     1035    void sete32(RegisterID src, RegisterID srcDest)
     1036    {
     1037        m_assembler.cmpl_rr(srcDest, src);
     1038        m_assembler.sete_r(srcDest);
     1039        m_assembler.movzbl_rr(srcDest, srcDest);
     1040    }
     1041
     1042    void sete32(Imm32 imm, RegisterID srcDest)
     1043    {
     1044        compareImm32ForBranchEquality(srcDest, imm.m_value);
     1045        m_assembler.sete_r(srcDest);
     1046        m_assembler.movzbl_rr(srcDest, srcDest);
     1047    }
     1048
     1049    void setne32(RegisterID src, RegisterID srcDest)
     1050    {
     1051        m_assembler.cmpl_rr(srcDest, src);
     1052        m_assembler.setne_r(srcDest);
     1053        m_assembler.movzbl_rr(srcDest, srcDest);
     1054    }
     1055
     1056    void setne32(Imm32 imm, RegisterID srcDest)
     1057    {
     1058        compareImm32ForBranchEquality(srcDest, imm.m_value);
     1059        m_assembler.setne_r(srcDest);
     1060        m_assembler.movzbl_rr(srcDest, srcDest);
     1061    }
     1062
     1063    // FIXME:
     1064    // The mask should be optional... paerhaps the argument order should be
     1065    // dest-src, operations always have a dest? ... possibly not true, considering
     1066    // asm ops like test, or pseudo ops like pop().
     1067    void setnz32(Address address, Imm32 mask, RegisterID dest)
     1068    {
     1069        testImm32(address, mask);
     1070        m_assembler.setnz_r(dest);
     1071        m_assembler.movzbl_rr(dest, dest);
     1072    }
     1073
     1074    void setz32(Address address, Imm32 mask, RegisterID dest)
     1075    {
     1076        testImm32(address, mask);
     1077        m_assembler.setz_r(dest);
     1078        m_assembler.movzbl_rr(dest, dest);
     1079    }
    8041080};
    8051081
Note: See TracChangeset for help on using the changeset viewer.