Changeset 189293 in webkit


Ignore:
Timestamp:
Sep 3, 2015, 3:16:23 PM (10 years ago)
Author:
msaboff@apple.com
Message:

Clean up register naming
https://bugs.webkit.org/show_bug.cgi?id=148658

Reviewed by Geoffrey Garen.

This changes register naming conventions in the llint and baseline JIT
in order to use as few (native) callee-save registers as possible on
64-bits platforms. It also introduces significant changes in the way
registers names are defined in the LLint and baseline JIT in order to
enable a simpler convention about which registers can be aliased. That
convention is valid across all architecture, and described in
llint/LowLevelInterpreter.asm.

Callee save registers are now called out regCS<n> (in the JIT) or
csr<n> (in the LLInt) with a common numbering across all tiers. Some
registers are unused in some tiers.

As a part of this change, rdi was removed from the list of temporary
registers for X86-64 Windows as it is a callee saves register. This
reduced the number of temporary registers for X86-64 Windows.

This is in preparation for properly handling callee save register
preservation and restoration.

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compileFunction):

  • ftl/FTLLink.cpp:

(JSC::FTL::link):

  • jit/FPRInfo.h:

(JSC::FPRInfo::toRegister):
(JSC::FPRInfo::toIndex):

  • jit/GPRInfo.h:

(JSC::GPRInfo::toIndex):
(JSC::GPRInfo::toRegister):
(JSC::GPRInfo::debugName): Deleted.

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_op_mod):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emitSlow_op_loop_hint):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_end):
(JSC::JIT::emit_op_new_object):

  • jit/RegisterPreservationWrapperGenerator.cpp:

(JSC::generateRegisterPreservationWrapper):
(JSC::generateRegisterRestoration):

  • jit/ThunkGenerators.cpp:

(JSC::arityFixupGenerator):
(JSC::nativeForGenerator): Deleted.

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • offlineasm/arm.rb:
  • offlineasm/arm64.rb:
  • offlineasm/cloop.rb:
  • offlineasm/mips.rb:
  • offlineasm/registers.rb:
  • offlineasm/sh4.rb:
  • offlineasm/x86.rb:
Location:
trunk/Source/JavaScriptCore
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r189288 r189293  
     12015-09-03  Basile Clement  <basile_clement@apple.com> and Michael Saboff  <msaboff@apple.com>
     2
     3        Clean up register naming
     4        https://bugs.webkit.org/show_bug.cgi?id=148658
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This changes register naming conventions in the llint and baseline JIT
     9        in order to use as few (native) callee-save registers as possible on
     10        64-bits platforms. It also introduces significant changes in the way
     11        registers names are defined in the LLint and baseline JIT in order to
     12        enable a simpler convention about which registers can be aliased. That
     13        convention is valid across all architecture, and described in
     14        llint/LowLevelInterpreter.asm.
     15
     16        Callee save registers are now called out regCS<n> (in the JIT) or
     17        csr<n> (in the LLInt) with a common numbering across all tiers. Some
     18        registers are unused in some tiers.
     19
     20        As a part of this change, rdi was removed from the list of temporary
     21        registers for X86-64 Windows as it is a callee saves register. This
     22        reduced the number of temporary registers for X86-64 Windows.
     23
     24        This is in preparation for properly handling callee save register
     25        preservation and restoration.
     26
     27        * dfg/DFGJITCompiler.cpp:
     28        (JSC::DFG::JITCompiler::compileFunction):
     29        * ftl/FTLLink.cpp:
     30        (JSC::FTL::link):
     31        * jit/FPRInfo.h:
     32        (JSC::FPRInfo::toRegister):
     33        (JSC::FPRInfo::toIndex):
     34        * jit/GPRInfo.h:
     35        (JSC::GPRInfo::toIndex):
     36        (JSC::GPRInfo::toRegister):
     37        (JSC::GPRInfo::debugName): Deleted.
     38        * jit/JIT.cpp:
     39        (JSC::JIT::privateCompile):
     40        * jit/JITArithmetic.cpp:
     41        (JSC::JIT::emit_op_mod):
     42        * jit/JITOpcodes.cpp:
     43        (JSC::JIT::emitSlow_op_loop_hint):
     44        * jit/JITOpcodes32_64.cpp:
     45        (JSC::JIT::emit_op_end):
     46        (JSC::JIT::emit_op_new_object):
     47        * jit/RegisterPreservationWrapperGenerator.cpp:
     48        (JSC::generateRegisterPreservationWrapper):
     49        (JSC::generateRegisterRestoration):
     50        * jit/ThunkGenerators.cpp:
     51        (JSC::arityFixupGenerator):
     52        (JSC::nativeForGenerator): Deleted.
     53        * llint/LowLevelInterpreter.asm:
     54        * llint/LowLevelInterpreter32_64.asm:
     55        * llint/LowLevelInterpreter64.asm:
     56        * offlineasm/arm.rb:
     57        * offlineasm/arm64.rb:
     58        * offlineasm/cloop.rb:
     59        * offlineasm/mips.rb:
     60        * offlineasm/registers.rb:
     61        * offlineasm/sh4.rb:
     62        * offlineasm/x86.rb:
     63
    1642015-09-03  Filip Pizlo  <fpizlo@apple.com>
    265
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r187505 r189293  
    396396    if (maxFrameExtentForSlowPathCall)
    397397        addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
    398     branchTest32(Zero, GPRInfo::regT0).linkTo(fromArityCheck, this);
     398    branchTest32(Zero, GPRInfo::returnValueGPR).linkTo(fromArityCheck, this);
    399399    emitStoreCodeOrigin(CodeOrigin(0));
    400     GPRReg thunkReg;
    401 #if USE(JSVALUE64)
    402     thunkReg = GPRInfo::regT7;
    403 #else
    404     thunkReg = GPRInfo::regT5;
    405 #endif
     400    GPRReg thunkReg = GPRInfo::argumentGPR1;
    406401    CodeLocationLabel* arityThunkLabels =
    407402        m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters());
    408403    move(TrustedImmPtr(arityThunkLabels), thunkReg);
    409     loadPtr(BaseIndex(thunkReg, GPRInfo::regT0, timesPtr()), thunkReg);
     404    loadPtr(BaseIndex(thunkReg, GPRInfo::returnValueGPR, timesPtr()), thunkReg);
     405    move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
    410406    m_callArityFixup = call();
    411407    jump(fromArityCheck);
  • trunk/Source/JavaScriptCore/ftl/FTLLink.cpp

    r188932 r189293  
    166166        jit.jitAssertIsNull(GPRInfo::regT1);
    167167#endif
    168         jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0);
     168        jit.move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
    169169        jit.emitFunctionEpilogue();
    170         mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0));
     170        mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0));
    171171        jit.emitFunctionPrologue();
    172172        CodeLocationLabel* arityThunkLabels =
    173173            vm.arityCheckFailReturnThunks->returnPCsFor(vm, codeBlock->numParameters());
    174         jit.move(CCallHelpers::TrustedImmPtr(arityThunkLabels), GPRInfo::regT7);
    175         jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::regT7, GPRInfo::regT0, CCallHelpers::timesPtr()), GPRInfo::regT7);
     174        jit.move(CCallHelpers::TrustedImmPtr(arityThunkLabels), GPRInfo::argumentGPR1);
     175        jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::argumentGPR1, GPRInfo::argumentGPR0, CCallHelpers::timesPtr()), GPRInfo::argumentGPR1);
    176176        CCallHelpers::Call callArityFixup = jit.call();
    177177        jit.emitFunctionEpilogue();
  • trunk/Source/JavaScriptCore/jit/FPRInfo.h

    r165431 r189293  
    269269public:
    270270    typedef FPRReg RegisterType;
    271     static const unsigned numberOfRegisters = 6;
     271    static const unsigned numberOfRegisters = 7;
    272272
    273273    // Temporary registers.
    274274    static const FPRReg fpRegT0 = MIPSRegisters::f0;
    275     static const FPRReg fpRegT1 = MIPSRegisters::f4;
    276     static const FPRReg fpRegT2 = MIPSRegisters::f6;
    277     static const FPRReg fpRegT3 = MIPSRegisters::f8;
    278     static const FPRReg fpRegT4 = MIPSRegisters::f10;
    279     static const FPRReg fpRegT5 = MIPSRegisters::f18;
     275    static const FPRReg fpRegT1 = MIPSRegisters::f2;
     276    static const FPRReg fpRegT2 = MIPSRegisters::f4;
     277    static const FPRReg fpRegT3 = MIPSRegisters::f6;
     278    static const FPRReg fpRegT4 = MIPSRegisters::f8;
     279    static const FPRReg fpRegT5 = MIPSRegisters::f10;
     280    static const FPRReg fpRegT6 = MIPSRegisters::f18;
    280281
    281282    static const FPRReg returnValueFPR = MIPSRegisters::f0;
     
    287288    {
    288289        static const FPRReg registerForIndex[numberOfRegisters] = {
    289             fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 };
     290            fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5, fpRegT6 };
    290291
    291292        ASSERT(index < numberOfRegisters);
     
    298299        ASSERT(reg < 20);
    299300        static const unsigned indexForRegister[20] = {
    300             0, InvalidIndex, InvalidIndex, InvalidIndex,
    301             1, InvalidIndex, 2, InvalidIndex,
    302             3, InvalidIndex, 4, InvalidIndex,
     301            0, InvalidIndex, 1, InvalidIndex,
     302            2, InvalidIndex, 3, InvalidIndex,
     303            4, InvalidIndex, 5, InvalidIndex,
    303304            InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
    304             InvalidIndex, InvalidIndex, 5, InvalidIndex,
     305            InvalidIndex, InvalidIndex, 6, InvalidIndex,
    305306        };
    306307        unsigned result = indexForRegister[reg];
  • trunk/Source/JavaScriptCore/jit/GPRInfo.h

    r181993 r189293  
    3232namespace JSC {
    3333
     34// We use the same conventions in the basline JIT as in the LLint. If you
     35// change mappings in the GPRInfo, you should change them in the offlineasm
     36// compiler adequately. The register naming conventions are described at the
     37// top of the LowLevelInterpreter.asm file.
     38
    3439typedef MacroAssembler::RegisterID GPRReg;
    3540#define InvalidGPRReg ((::JSC::GPRReg)-1)
     
    295300#endif // USE(JSVALUE32_64)
    296301
    297 // The baseline JIT requires that regT3 be callee-preserved.
    298 
    299302#if CPU(X86)
    300303#define NUMBER_OF_ARGUMENT_REGISTERS 0u
     
    305308    static const unsigned numberOfRegisters = 6;
    306309    static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
    307 
    308     // Note: regT3 is required to be callee-preserved.
    309310
    310311    // Temporary registers.
     
    312313    static const GPRReg regT1 = X86Registers::edx;
    313314    static const GPRReg regT2 = X86Registers::ecx;
    314     static const GPRReg regT3 = X86Registers::ebx;
    315     static const GPRReg regT4 = X86Registers::edi;
    316     static const GPRReg regT5 = X86Registers::esi;
    317     // These registers match the baseline JIT.
    318     static const GPRReg cachedResultRegister = regT0;
    319     static const GPRReg cachedResultRegister2 = regT1;
     315    static const GPRReg regT3 = X86Registers::ebx; // Callee-save
     316    static const GPRReg regT4 = X86Registers::esi; // Callee-save
     317    static const GPRReg regT5 = X86Registers::edi; // Callee-save
    320318    static const GPRReg callFrameRegister = X86Registers::ebp;
    321319    // These constants provide the names for the general purpose argument & return value registers.
    322320    static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
    323321    static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
     322    static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
     323    static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
    324324    static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
    325     static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
    326     static const GPRReg nonArgGPR2 = X86Registers::ebx; // regT3
     325    static const GPRReg nonArgGPR1 = X86Registers::edi; // regT5
    327326    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
    328327    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
     
    346345        ASSERT(reg != InvalidGPRReg);
    347346        ASSERT(static_cast<int>(reg) < 8);
    348         static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4 };
     347        static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
    349348        unsigned result = indexForRegister[reg];
    350349        return result;
     
    380379    static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
    381380
    382     // Note: regT3 is required to be callee-preserved.
    383 
    384381    // These registers match the baseline JIT.
    385     static const GPRReg cachedResultRegister = X86Registers::eax;
    386382    static const GPRReg callFrameRegister = X86Registers::ebp;
    387383    static const GPRReg tagTypeNumberRegister = X86Registers::r14;
     
    389385    // Temporary registers.
    390386    static const GPRReg regT0 = X86Registers::eax;
     387#if !OS(WINDOWS)
     388    static const GPRReg regT1 = X86Registers::esi;
     389    static const GPRReg regT2 = X86Registers::edx;
     390    static const GPRReg regT3 = X86Registers::ecx;
     391    static const GPRReg regT4 = X86Registers::r8;
     392    static const GPRReg regT5 = X86Registers::r10;
     393    static const GPRReg regT6 = X86Registers::edi;
     394    static const GPRReg regT7 = X86Registers::r9;
     395#else
    391396    static const GPRReg regT1 = X86Registers::edx;
    392     static const GPRReg regT2 = X86Registers::ecx;
    393     static const GPRReg regT3 = X86Registers::ebx;
    394     static const GPRReg regT4 = X86Registers::edi;
    395     static const GPRReg regT5 = X86Registers::esi;
    396     static const GPRReg regT6 = X86Registers::r8;
    397     static const GPRReg regT7 = X86Registers::r9;
    398     static const GPRReg regT8 = X86Registers::r10;
    399     static const GPRReg regT9 = X86Registers::r12;
    400     static const GPRReg regT10 = X86Registers::r13;
     397    static const GPRReg regT2 = X86Registers::r8;
     398    static const GPRReg regT3 = X86Registers::r9;
     399    static const GPRReg regT4 = X86Registers::r10;
     400    static const GPRReg regT5 = X86Registers::ecx;
     401#endif
     402
     403    static const GPRReg regCS0 = X86Registers::ebx;
     404
     405#if !OS(WINDOWS)
     406    static const GPRReg regCS1 = X86Registers::r12;
     407    static const GPRReg regCS2 = X86Registers::r13;
     408    static const GPRReg regCS3 = X86Registers::r14;
     409    static const GPRReg regCS4 = X86Registers::r15;
     410#else
     411    static const GPRReg regCS1 = X86Registers::esi;
     412    static const GPRReg regCS2 = X86Registers::edi;
     413    static const GPRReg regCS3 = X86Registers::r12;
     414    static const GPRReg regCS4 = X86Registers::r13;
     415    static const GPRReg regCS5 = X86Registers::r14;
     416    static const GPRReg regCS6 = X86Registers::r15;
     417#endif
     418
    401419    // These constants provide the names for the general purpose argument & return value registers.
    402420#if !OS(WINDOWS)
    403     static const GPRReg argumentGPR0 = X86Registers::edi; // regT4
    404     static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
    405     static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
    406     static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
    407     static const GPRReg argumentGPR4 = X86Registers::r8;  // regT6
    408     static const GPRReg argumentGPR5 = X86Registers::r9;  // regT7
     421    static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
     422    static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
     423    static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
     424    static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
     425    static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
     426    static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
    409427#else
    410     static const GPRReg argumentGPR0 = X86Registers::ecx;
    411     static const GPRReg argumentGPR1 = X86Registers::edx;
    412     static const GPRReg argumentGPR2 = X86Registers::r8; // regT6
    413     static const GPRReg argumentGPR3 = X86Registers::r9; // regT7
    414 #endif
    415     static const GPRReg nonArgGPR0 = X86Registers::r10; // regT8
    416     static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
    417     static const GPRReg nonArgGPR2 = X86Registers::r12; // regT9
     428    static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
     429    static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
     430    static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
     431    static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
     432#endif
     433    static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
     434    static const GPRReg nonArgGPR1 = X86Registers::ebx; // Callee save
    418435    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
    419     static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
    420     static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
    421     static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10;
     436    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
     437    static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
     438    static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
    422439    static const GPRReg patchpointScratchRegister = MacroAssembler::scratchRegister;
    423440
     
    425442    {
    426443        ASSERT(index < numberOfRegisters);
    427         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9, regT10 };
     444#if !OS(WINDOWS)
     445        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
     446#else
     447        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
     448#endif
    428449        return registerForIndex[index];
    429450    }
     
    444465        ASSERT(reg != InvalidGPRReg);
    445466        ASSERT(static_cast<int>(reg) < 16);
    446         static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
     467#if !OS(WINDOWS)
     468        static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
     469#else
     470        static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
     471#endif
    447472        return indexForRegister[reg];
    448473    }
     
    475500    static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
    476501
    477     // Note: regT3 is required to be callee-preserved.
    478 
    479502    // Temporary registers.
    480503    static const GPRReg regT0 = ARMRegisters::r0;
    481504    static const GPRReg regT1 = ARMRegisters::r1;
    482505    static const GPRReg regT2 = ARMRegisters::r2;
    483     static const GPRReg regT3 = ARMRegisters::r4;
     506    static const GPRReg regT3 = ARMRegisters::r3;
    484507    static const GPRReg regT4 = ARMRegisters::r8;
    485508    static const GPRReg regT5 = ARMRegisters::r9;
     
    490513    static const GPRReg regT7 = ARMRegisters::r7;
    491514#endif
    492     static const GPRReg regT8 = ARMRegisters::r3;
     515    static const GPRReg regT8 = ARMRegisters::r4;
    493516    // These registers match the baseline JIT.
    494     static const GPRReg cachedResultRegister = regT0;
    495     static const GPRReg cachedResultRegister2 = regT1;
    496517    static const GPRReg callFrameRegister = ARMRegisters::fp;
    497518    // These constants provide the names for the general purpose argument & return value registers.
     
    499520    static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
    500521    static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
    501     static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT8
    502     static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT3
     522    static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
     523    static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
    503524    static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
    504525    static const GPRReg nonArgGPR2 = ARMRegisters::r9; // regT5
    505526    static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
    506527    static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
    507     static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5; // regT7
     528    static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
    508529
    509530    static GPRReg toRegister(unsigned index)
     
    527548        static const unsigned indexForRegister[16] =
    528549#if CPU(ARM_THUMB2)
    529             { 0, 1, 2, 8, 3, 9, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
     550            { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
    530551#else
    531             { 0, 1, 2, 8, 3, 9, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
     552            { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
    532553#endif
    533554        unsigned result = indexForRegister[reg];
     
    562583    static const unsigned numberOfArgumentRegisters = 8;
    563584
    564     // Note: regT3 is required to be callee-preserved.
    565 
    566585    // These registers match the baseline JIT.
    567     static const GPRReg cachedResultRegister = ARM64Registers::x0;
    568     static const GPRReg timeoutCheckRegister = ARM64Registers::x26;
    569586    static const GPRReg callFrameRegister = ARM64Registers::fp;
    570587    static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
     
    574591    static const GPRReg regT1 = ARM64Registers::x1;
    575592    static const GPRReg regT2 = ARM64Registers::x2;
    576     static const GPRReg regT3 = ARM64Registers::x23;
    577     static const GPRReg regT4 = ARM64Registers::x5;
    578     static const GPRReg regT5 = ARM64Registers::x24;
     593    static const GPRReg regT3 = ARM64Registers::x3;
     594    static const GPRReg regT4 = ARM64Registers::x4;
     595    static const GPRReg regT5 = ARM64Registers::x5;
    579596    static const GPRReg regT6 = ARM64Registers::x6;
    580597    static const GPRReg regT7 = ARM64Registers::x7;
     
    587604    static const GPRReg regT14 = ARM64Registers::x14;
    588605    static const GPRReg regT15 = ARM64Registers::x15;
     606    static const GPRReg regCS0 = ARM64Registers::x26; // Used by LLInt only
     607    static const GPRReg regCS1 = ARM64Registers::x27; // tagTypeNumber
     608    static const GPRReg regCS2 = ARM64Registers::x28; // tagMask
    589609    // These constants provide the names for the general purpose argument & return value registers.
    590610    static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
    591611    static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
    592612    static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
    593     static const GPRReg argumentGPR3 = ARM64Registers::x3;
    594     static const GPRReg argumentGPR4 = ARM64Registers::x4;
    595     static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT4
     613    static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
     614    static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
     615    static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
    596616    static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
    597617    static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
    598618    static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
    599619    static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
    600     static const GPRReg nonArgGPR2 = ARM64Registers::x10; // regT10
    601620    static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
    602621    static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
     
    664683public:
    665684    typedef GPRReg RegisterType;
    666     static const unsigned numberOfRegisters = 7;
     685    static const unsigned numberOfRegisters = 8;
    667686    static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
    668687
    669688    // regT0 must be v0 for returning a 32-bit value.
    670689    // regT1 must be v1 for returning a pair of 32-bit value.
    671     // regT3 must be saved in the callee, so use an S register.
    672690
    673691    // Temporary registers.
    674692    static const GPRReg regT0 = MIPSRegisters::v0;
    675693    static const GPRReg regT1 = MIPSRegisters::v1;
    676     static const GPRReg regT2 = MIPSRegisters::t4;
    677     static const GPRReg regT3 = MIPSRegisters::s2;
    678     static const GPRReg regT4 = MIPSRegisters::t5;
    679     static const GPRReg regT5 = MIPSRegisters::t6;
    680     static const GPRReg regT6 = MIPSRegisters::s0;
     694    static const GPRReg regT2 = MIPSRegisters::t2;
     695    static const GPRReg regT3 = MIPSRegisters::t3;
     696    static const GPRReg regT4 = MIPSRegisters::t4;
     697    static const GPRReg regT5 = MIPSRegisters::t5;
     698    static const GPRReg regT6 = MIPSRegisters::t0;
     699    static const GPRReg regT7 = MIPSRegisters::t1;
    681700    // These registers match the baseline JIT.
    682     static const GPRReg cachedResultRegister = regT0;
    683     static const GPRReg cachedResultRegister2 = regT1;
    684701    static const GPRReg callFrameRegister = MIPSRegisters::fp;
    685702    // These constants provide the names for the general purpose argument & return value registers.
     
    688705    static const GPRReg argumentGPR2 = MIPSRegisters::a2;
    689706    static const GPRReg argumentGPR3 = MIPSRegisters::a3;
    690     static const GPRReg nonArgGPR0 = regT2;
    691     static const GPRReg nonArgGPR1 = regT3;
    692     static const GPRReg nonArgGPR2 = regT4;
     707    static const GPRReg nonArgGPR0 = regT0;
     708    static const GPRReg nonArgGPR1 = regT1;
    693709    static const GPRReg returnValueGPR = regT0;
    694710    static const GPRReg returnValueGPR2 = regT1;
    695     static const GPRReg nonPreservedNonReturnGPR = regT5;
     711    static const GPRReg nonPreservedNonReturnGPR = regT2;
    696712
    697713    static GPRReg toRegister(unsigned index)
    698714    {
    699715        ASSERT(index < numberOfRegisters);
    700         static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
     716        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 };
    701717        return registerForIndex[index];
    702718    }
     
    708724        static const unsigned indexForRegister[24] = {
    709725            InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
    710             InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 4, 5, InvalidIndex,
    711             6, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
     726            6, 7, 2, 3, 4, 5, InvalidIndex, InvalidIndex,
     727            InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
    712728        };
    713729        unsigned result = indexForRegister[reg];
     
    746762    static const GPRReg regT0 = SH4Registers::r0;
    747763    static const GPRReg regT1 = SH4Registers::r1;
    748     static const GPRReg regT2 = SH4Registers::r2;
    749     static const GPRReg regT3 = SH4Registers::r10;
    750     static const GPRReg regT4 = SH4Registers::r4;
    751     static const GPRReg regT5 = SH4Registers::r5;
    752     static const GPRReg regT6 = SH4Registers::r6;
    753     static const GPRReg regT7 = SH4Registers::r7;
     764    static const GPRReg regT2 = SH4Registers::r6;
     765    static const GPRReg regT3 = SH4Registers::r7;
     766    static const GPRReg regT4 = SH4Registers::r2;
     767    static const GPRReg regT5 = SH4Registers::r3;
     768    static const GPRReg regT6 = SH4Registers::r4;
     769    static const GPRReg regT7 = SH4Registers::r5;
    754770    static const GPRReg regT8 = SH4Registers::r8;
    755771    static const GPRReg regT9 = SH4Registers::r9;
     
    759775    static const GPRReg callFrameRegister = SH4Registers::fp;
    760776    // These constants provide the names for the general purpose argument & return value registers.
    761     static const GPRReg argumentGPR0 = regT4;
    762     static const GPRReg argumentGPR1 = regT5;
    763     static const GPRReg argumentGPR2 = regT6;
    764     static const GPRReg argumentGPR3 = regT7;
    765     static const GPRReg nonArgGPR0 = regT3;
    766     static const GPRReg nonArgGPR1 = regT8;
    767     static const GPRReg nonArgGPR2 = regT9;
     777    static const GPRReg argumentGPR0 = SH4Registers::r4; // regT6
     778    static const GPRReg argumentGPR1 = SH4Registers::r5; // regT7
     779    static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
     780    static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
     781    static const GPRReg nonArgGPR0 = regT4;
     782    static const GPRReg nonArgGPR1 = regT5;
    768783    static const GPRReg returnValueGPR = regT0;
    769784    static const GPRReg returnValueGPR2 = regT1;
     
    781796        ASSERT(reg != InvalidGPRReg);
    782797        ASSERT(reg < 14);
    783         static const unsigned indexForRegister[14] = { 0, 1, 2, InvalidIndex, 4, 5, 6, 7, 8, 9, 3, InvalidIndex, InvalidIndex, InvalidIndex };
     798        static const unsigned indexForRegister[14] = { 0, 1, 4, 5, 6, 7, 2, 3, 8, 9, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
    784799        unsigned result = indexForRegister[reg];
    785800        return result;
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r189288 r189293  
    573573        if (maxFrameExtentForSlowPathCall)
    574574            addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
    575         if (returnValueGPR != regT0)
    576             move(returnValueGPR, regT0);
    577         branchTest32(Zero, regT0).linkTo(beginLabel, this);
    578         GPRReg thunkReg;
    579 #if USE(JSVALUE64)
    580         thunkReg = GPRInfo::regT7;
    581 #else
    582         thunkReg = GPRInfo::regT5;
    583 #endif
     575        branchTest32(Zero, returnValueGPR).linkTo(beginLabel, this);
     576        GPRReg thunkReg = GPRInfo::argumentGPR1;
    584577        CodeLocationLabel* failThunkLabels =
    585578            m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters());
    586579        move(TrustedImmPtr(failThunkLabels), thunkReg);
    587         loadPtr(BaseIndex(thunkReg, regT0, timesPtr()), thunkReg);
     580        loadPtr(BaseIndex(thunkReg, returnValueGPR, timesPtr()), thunkReg);
     581        move(returnValueGPR, GPRInfo::argumentGPR0);
    588582        emitNakedCall(m_vm->getCTIStub(arityFixupGenerator).code());
    589583
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r168776 r189293  
    612612
    613613    // Make sure registers are correct for x86 IDIV instructions.
     614#if CPU(X86)
     615    auto edx = regT1;
     616    auto ecx = regT2;
     617#elif OS(WINDOWS)
     618    auto edx = regT1;
     619    auto ecx = regT5;
     620#else
     621    auto edx = regT2;
     622    auto ecx = regT3;
     623#endif
    614624    ASSERT(regT0 == X86Registers::eax);
    615     ASSERT(regT1 == X86Registers::edx);
    616     ASSERT(regT2 == X86Registers::ecx);
    617 
    618     emitGetVirtualRegisters(op1, regT3, op2, regT2);
    619     emitJumpSlowCaseIfNotImmediateInteger(regT3);
    620     emitJumpSlowCaseIfNotImmediateInteger(regT2);
    621 
    622     move(regT3, regT0);
    623     addSlowCase(branchTest32(Zero, regT2));
    624     Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1));
     625    ASSERT(edx == X86Registers::edx);
     626    ASSERT(ecx == X86Registers::ecx);
     627
     628    emitGetVirtualRegisters(op1, regT4, op2, ecx);
     629    emitJumpSlowCaseIfNotImmediateInteger(regT4);
     630    emitJumpSlowCaseIfNotImmediateInteger(ecx);
     631
     632    move(regT4, regT0);
     633    addSlowCase(branchTest32(Zero, ecx));
     634    Jump denominatorNotNeg1 = branch32(NotEqual, ecx, TrustedImm32(-1));
    625635    addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1)));
    626636    denominatorNotNeg1.link(this);
    627637    m_assembler.cdq();
    628     m_assembler.idivl_r(regT2);
    629     Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
    630     addSlowCase(branchTest32(Zero, regT1));
     638    m_assembler.idivl_r(ecx);
     639    Jump numeratorPositive = branch32(GreaterThanOrEqual, regT4, TrustedImm32(0));
     640    addSlowCase(branchTest32(Zero, edx));
    631641    numeratorPositive.link(this);
    632     emitFastArithReTagImmediate(regT1, regT0);
     642    emitFastArithReTagImmediate(edx, regT0);
    633643    emitPutVirtualRegister(result);
    634644}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r189288 r189293  
    929929        Jump noOptimizedEntry = branchTestPtr(Zero, returnValueGPR);
    930930        if (!ASSERT_DISABLED) {
    931             Jump ok = branchPtr(MacroAssembler::Above, regT0, TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000))));
     931            Jump ok = branchPtr(MacroAssembler::Above, returnValueGPR, TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000))));
    932932            abortWithReason(JITUnreasonableLoopHintJumpTarget);
    933933            ok.link(this);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r189288 r189293  
    148148{
    149149    ASSERT(returnValueGPR != callFrameRegister);
    150     emitLoad(currentInstruction[1].u.operand, regT1, regT0);
     150    emitLoad(currentInstruction[1].u.operand, regT1, returnValueGPR);
    151151    emitFunctionEpilogue();
    152152    ret();
     
    165165    MarkedAllocator* allocator = &m_vm->heap.allocatorForObjectWithoutDestructor(allocationSize);
    166166
    167     RegisterID resultReg = regT0;
     167    RegisterID resultReg = returnValueGPR;
    168168    RegisterID allocatorReg = regT1;
    169     RegisterID scratchReg = regT2;
     169    RegisterID scratchReg = regT3;
    170170
    171171    move(TrustedImmPtr(allocator), allocatorReg);
  • trunk/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp

    r170876 r189293  
    6666    RegisterSet toSave = registersToPreserve();
    6767    ptrdiff_t offset = registerPreservationOffset();
     68
     69    ASSERT(!toSave.get(GPRInfo::regT1));
     70    ASSERT(!toSave.get(GPRInfo::regT2));
     71    ASSERT(!toSave.get(GPRInfo::regT3));
    6872   
    6973    AssemblyHelpers jit(&vm, 0);
     
    8589        GPRInfo::regT2);
    8690
    87     ASSERT(!toSave.get(GPRInfo::regT4));
    88     jit.move(AssemblyHelpers::stackPointerRegister, GPRInfo::regT4);
     91    jit.move(AssemblyHelpers::stackPointerRegister, GPRInfo::regT3);
    8992   
    9093    AssemblyHelpers::Label loop = jit.label();
    9194    jit.sub32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
    92     jit.load64(AssemblyHelpers::Address(GPRInfo::regT4, offset), GPRInfo::regT0);
    93     jit.store64(GPRInfo::regT0, GPRInfo::regT4);
    94     jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(Register)), GPRInfo::regT4);
     95    jit.load64(AssemblyHelpers::Address(GPRInfo::regT3, offset), GPRInfo::regT0);
     96    jit.store64(GPRInfo::regT0, GPRInfo::regT3);
     97    jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(Register)), GPRInfo::regT3);
    9598    jit.branchTest32(AssemblyHelpers::NonZero, GPRInfo::regT2).linkTo(loop, &jit);
    9699
    97     // At this point regT4 + offset points to where we save things.
     100    // At this point regT3 + offset points to where we save things.
    98101    ptrdiff_t currentOffset = 0;
    99     jit.storePtr(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
     102    jit.storePtr(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
    100103   
    101104    for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr <= AssemblyHelpers::lastRegister(); gpr = static_cast<GPRReg>(gpr + 1)) {
     
    103106            continue;
    104107        currentOffset += sizeof(Register);
    105         jit.store64(gpr, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
     108        jit.store64(gpr, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
    106109    }
    107110    for (FPRReg fpr = AssemblyHelpers::firstFPRegister(); fpr <= AssemblyHelpers::lastFPRegister(); fpr = static_cast<FPRReg>(fpr + 1)) {
     
    109112            continue;
    110113        currentOffset += sizeof(Register);
    111         jit.storeDouble(fpr, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
     114        jit.storeDouble(fpr, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
    112115    }
    113116   
     
    152155    ptrdiff_t offset = registerPreservationOffset();
    153156   
    154     ASSERT(!toSave.get(GPRInfo::regT4));
     157    ASSERT(!toSave.get(GPRInfo::regT1));
     158    ASSERT(!toSave.get(GPRInfo::regT2));
     159    ASSERT(!toSave.get(GPRInfo::regT3));
    155160
    156161    // We need to place the stack pointer back to where the caller thought they left it.
     
    162167            AssemblyHelpers::stackPointerRegister,
    163168            (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset),
    164         GPRInfo::regT4);
    165    
    166     jit.move(GPRInfo::regT4, GPRInfo::regT2);
     169        GPRInfo::regT3);
     170   
     171    jit.move(GPRInfo::regT3, GPRInfo::regT2);
    167172    jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
    168173   
     
    204209    // Thunks like this rely on the ArgumentCount being intact. Pay it forward.
    205210    jit.store32(
    206         GPRInfo::regT4,
     211        GPRInfo::regT3,
    207212        AssemblyHelpers::Address(
    208213            AssemblyHelpers::stackPointerRegister,
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r187819 r189293  
    256256
    257257#elif CPU(ARM64)
    258     COMPILE_ASSERT(ARM64Registers::x3 != JSInterfaceJIT::regT1, prev_callframe_not_trampled_by_T1);
    259     COMPILE_ASSERT(ARM64Registers::x3 != JSInterfaceJIT::regT3, prev_callframe_not_trampled_by_T3);
    260258    COMPILE_ASSERT(ARM64Registers::x0 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_0);
    261259    COMPILE_ASSERT(ARM64Registers::x1 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_1);
     
    356354    JSInterfaceJIT jit(vm);
    357355
    358     // We enter with fixup count, in aligned stack units, in regT0 and the return thunk in
    359     // regT5 on 32-bit and regT7 on 64-bit.
     356    // We enter with fixup count, in aligned stack units, in argumentGPR0 and the return thunk in argumentGPR1
     357    // We have the guarantee that a0, a1, a2, t3, t4 and t5 (or t0 for Windows) are all distinct :-)
    360358#if USE(JSVALUE64)
     359#if OS(WINDOWS)
     360    const GPRReg extraTemp = JSInterfaceJIT::regT0;
     361#else
     362    const GPRReg extraTemp = JSInterfaceJIT::regT5;
     363#endif
    361364#  if CPU(X86_64)
    362365    jit.pop(JSInterfaceJIT::regT4);
    363366#  endif
    364     jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::regT0);
    365     jit.neg64(JSInterfaceJIT::regT0);
    366     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT6);
    367     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::regT2);
    368     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2);
    369 
    370     // Move current frame down regT0 number of slots
     367    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
     368    jit.neg64(JSInterfaceJIT::argumentGPR0);
     369    jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
     370    jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
     371    jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
     372
     373    // Move current frame down argumentGPR0 number of slots
    371374    JSInterfaceJIT::Label copyLoop(jit.label());
    372     jit.load64(JSInterfaceJIT::regT6, JSInterfaceJIT::regT1);
    373     jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
    374     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT6);
    375     jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit);
    376 
    377     // Fill in regT0 - 1 missing arg slots with undefined
    378     jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2);
    379     jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT1);
    380     jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2);
     375    jit.load64(JSInterfaceJIT::regT3, extraTemp);
     376    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     377    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
     378    jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
     379
     380    // Fill in argumentGPR0 - 1 missing arg slots with undefined
     381    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
     382    jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
     383    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
    381384    JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
    382     jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
    383     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT6);
    384     jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit);
     385    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     386    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
     387    jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &jit);
    385388   
    386389    // Adjust call frame register and stack pointer to account for missing args
    387     jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1);
    388     jit.lshift64(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT1);
    389     jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister);
    390     jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::stackPointerRegister);
     390    jit.move(JSInterfaceJIT::argumentGPR0, extraTemp);
     391    jit.lshift64(JSInterfaceJIT::TrustedImm32(3), extraTemp);
     392    jit.addPtr(extraTemp, JSInterfaceJIT::callFrameRegister);
     393    jit.addPtr(extraTemp, JSInterfaceJIT::stackPointerRegister);
    391394
    392395    // Save the original return PC.
    393     jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT1);
    394     jit.storePtr(GPRInfo::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
    395    
     396    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), extraTemp);
     397    jit.storePtr(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     398
    396399    // Install the new return PC.
    397     jit.storePtr(GPRInfo::regT7, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
     400    jit.storePtr(GPRInfo::argumentGPR1, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
    398401
    399402#  if CPU(X86_64)
     
    405408    jit.pop(JSInterfaceJIT::regT4);
    406409#  endif
    407     jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::regT0);
    408     jit.neg32(JSInterfaceJIT::regT0);
     410    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
     411    jit.neg32(JSInterfaceJIT::argumentGPR0);
    409412    jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
    410     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::regT2);
    411     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2);
    412 
    413     // Move current frame down regT0 number of slots
     413    jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
     414    jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
     415
     416    // Move current frame down argumentGPR0 number of slots
    414417    JSInterfaceJIT::Label copyLoop(jit.label());
    415     jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT1);
    416     jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
    417     jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT1);
    418     jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4));
     418    jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT5);
     419    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     420    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT5);
     421    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
    419422    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
    420     jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit);
    421 
    422     // Fill in regT0 - 1 missing arg slots with undefined
    423     jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2);
    424     jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2);
     423    jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
     424
     425    // Fill in argumentGPR0 - 1 missing arg slots with undefined
     426    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
     427    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
    425428    JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
    426     jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT1);
    427     jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
    428     jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT1);
    429     jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4));
     429    jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
     430    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
     431    jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
     432    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
    430433
    431434    jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
    432     jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit);
     435    jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &jit);
    433436
    434437    // Adjust call frame register and stack pointer to account for missing args
    435     jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1);
    436     jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT1);
    437     jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister);
    438     jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::stackPointerRegister);
     438    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::regT5);
     439    jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT5);
     440    jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::callFrameRegister);
     441    jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::stackPointerRegister);
    439442
    440443    // Save the original return PC.
    441     jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT1);
    442     jit.storePtr(GPRInfo::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
     444    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT5);
     445    jit.storePtr(GPRInfo::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
    443446   
    444447    // Install the new return PC.
    445     jit.storePtr(GPRInfo::regT5, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
     448    jit.storePtr(GPRInfo::argumentGPR1, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
    446449   
    447450#  if CPU(X86)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r189279 r189293  
    2121# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    2222# THE POSSIBILITY OF SUCH DAMAGE.
     23
     24# Crash course on the language that this is written in (which I just call
     25# "assembly" even though it's more than that):
     26#
     27# - Mostly gas-style operand ordering. The last operand tends to be the
     28#   destination. So "a := b" is written as "mov b, a". But unlike gas,
     29#   comparisons are in-order, so "if (a < b)" is written as
     30#   "bilt a, b, ...".
     31#
     32# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
     33#   For 32-bit, "i" and "p" are interchangeable except when an op supports one
     34#   but not the other.
     35#
     36# - In general, valid operands for macro invocations and instructions are
     37#   registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
     38#   (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
     39#   (eg "_foo" or ".foo"). Macro invocations can also take anonymous
     40#   macros as operands. Instructions cannot take anonymous macros.
     41#
     42# - Labels must have names that begin with either "_" or ".".  A "." label
     43#   is local and gets renamed before code gen to minimize namespace
     44#   pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
     45#   may or may not be removed during code gen depending on whether the asm
     46#   conventions for C name mangling on the target platform mandate a "_"
     47#   prefix.
     48#
     49# - A "macro" is a lambda expression, which may be either anonymous or
     50#   named. But this has caveats. "macro" can take zero or more arguments,
     51#   which may be macros or any valid operands, but it can only return
     52#   code. But you can do Turing-complete things via continuation passing
     53#   style: "macro foo (a, b) b(a, a) end foo(foo, foo)". Actually, don't do
     54#   that, since you'll just crash the assembler.
     55#
     56# - An "if" is a conditional on settings. Any identifier supplied in the
     57#   predicate of an "if" is assumed to be a #define that is available
     58#   during code gen. So you can't use "if" for computation in a macro, but
     59#   you can use it to select different pieces of code for different
     60#   platforms.
     61#
     62# - Arguments to macros follow lexical scoping rather than dynamic scoping.
     63#   Const's also follow lexical scoping and may override (hide) arguments
     64#   or other consts. All variables (arguments and constants) can be bound
     65#   to operands. Additionally, arguments (but not constants) can be bound
     66#   to macros.
     67
     68# The following general-purpose registers are available:
     69#
     70#  - cfr and sp hold the call frame and (native) stack pointer respectively.
     71#  They are callee-save registers, and guaranteed to be distinct from all other
     72#  registers on all architectures.
     73#
     74#  - lr is defined on non-X86 architectures (ARM64, ARMv7, ARM,
     75#  ARMv7_TRADITIONAL, MIPS, SH4 and CLOOP) and holds the return PC
     76#
     77#  - pc holds the (native) program counter on 32-bits ARM architectures (ARM,
     78#  ARMv7, ARMv7_TRADITIONAL)
     79#
     80#  - t0, t1, t2, t3, t4 and optionally t5 are temporary registers that can get trashed on
     81#  calls, and are pairwise distinct registers. t4 holds the JS program counter, so use
     82#  with caution in opcodes (actually, don't use it in opcodes at all, except as PC).
     83#
     84#  - r0 and r1 are the platform's customary return registers, and thus are
     85#  two distinct registers
     86#
     87#  - a0, a1, a2 and a3 are the platform's customary argument registers, and
     88#  thus are pairwise distinct registers. Be mindful that:
     89#    + On X86, there are no argument registers. a0 and a1 are edx and
     90#    ecx following the fastcall convention, but you should still use the stack
     91#    to pass your arguments. The cCall2 and cCall4 macros do this for you.
     92#    + On X86_64_WIN, you should allocate space on the stack for the arguments,
     93#    and the return convention is weird for > 8 bytes types. The only place we
     94#    use > 8 bytes return values is on a cCall, and cCall2 and cCall4 handle
     95#    this for you.
     96#
     97#  - The only registers guaranteed to be caller-saved are r0, r1, a0, a1 and a2, and
     98#  you should be mindful of that in functions that are called directly from C.
     99#  If you need more registers, you should push and pop them like a good
     100#  assembly citizen, because any other register will be callee-saved on X86.
     101#
     102# You can additionally assume:
     103#
     104#  - a3, t2, t3, t4 and t5 are never return registers; t0, t1, a0, a1 and a2
     105#  can be return registers.
     106#
     107#  - t4 and t5 are never argument registers, t3 can only be a3, t1 can only be
     108#  a1; but t0 and t2 can be either a0 or a2.
     109#
     110#  - On 64 bits, csr0, csr1, csr2 and optionally csr3, csr4, csr5 and csr6
     111#  are available as callee-save registers.
     112#  csr0 is used to store the PC base, while the last two csr registers are used
     113#  to store special tag values. Don't use them for anything else.
     114#
     115# Additional platform-specific details (you shouldn't rely on this remaining
     116# true):
     117#
     118#  - For consistency with the baseline JIT, t0 is always r0 (and t1 is always
     119#  r1 on 32 bits platforms). You should use the r version when you need return
     120#  registers, and the t version otherwise: code using t0 (or t1) should still
     121#  work if swapped with e.g. t3, while code using r0 (or r1) should not. There
     122#  *may* be legacy code relying on this.
     123#
     124#  - On all platforms other than X86, t0 can only be a0 and t2 can only be a2.
     125#
     126#  - On all platforms other than X86 and X86_64, a2 is not a return register.
     127#  a2 is r0 on X86 (because we have so few registers) and r1 on X86_64 (because
     128#  the ABI enforces it).
     129#
     130# The following floating-point registers are available:
     131#
     132#  - ft0-ft5 are temporary floating-point registers that get trashed on calls,
     133#  and are pairwise distinct.
     134#
     135#  - fa0 and fa1 are the platform's customary floating-point argument
     136#  registers, and are both distinct. On 64-bits platforms, fa2 and fa3 are
     137#  additional floating-point argument registers.
     138#
     139#  - fr is the platform's customary floating-point return register
     140#
     141# You can assume that ft1-ft5 or fa1-fa3 are never fr, and that ftX is never
     142# faY if X != Y.
    23143
    24144# First come the common protocols that both interpreters use. Note that each
     
    108228    # - Use a pair of registers to represent the PC: one register for the
    109229    #   base of the bytecodes, and one register for the index.
    110     # - The PC base (or PB for short) should be stored in the csr. It will
    111     #   get clobbered on calls to other JS code, but will get saved on calls
    112     #   to C functions.
     230    # - The PC base (or PB for short) must be stored in a callee-save register.
    113231    # - C calls are still given the Instruction* rather than the PC index.
    114232    #   This requires an add before the call, and a sub after.
    115     const PC = t5
    116     const PB = t6
    117     const tagTypeNumber = csr1
    118     const tagMask = csr2
    119    
     233    const PC = t4
     234    const PB = csr0
     235    if ARM64
     236        const tagTypeNumber = csr1
     237        const tagMask = csr2
     238    elsif X86_64
     239        const tagTypeNumber = csr3
     240        const tagMask = csr4
     241    elsif X86_64_WIN
     242        const tagTypeNumber = csr5
     243        const tagMask = csr6
     244    elsif C_LOOP
     245        const tagTypeNumber = csr1
     246        const tagMask = csr2
     247    end
     248
    120249    macro loadisFromInstruction(offset, dest)
    121250        loadis offset * 8[PB, PC, 8], dest
     
    131260
    132261else
    133     const PC = t5
     262    const PC = t4
    134263    macro loadisFromInstruction(offset, dest)
    135264        loadis offset * 4[PC], dest
     
    139268        loadp offset * 4[PC], dest
    140269    end
     270end
     271
     272if X86_64_WIN
     273    const extraTempReg = t0
     274else
     275    const extraTempReg = t5
    141276end
    142277
     
    466601macro restoreStackPointerAfterCall()
    467602    loadp CodeBlock[cfr], t2
    468     getFrameRegisterSizeForCodeBlock(t2, t4)
     603    getFrameRegisterSizeForCodeBlock(t2, t2)
    469604    if ARMv7
    470         subp cfr, t4, t4
    471         move t4, sp
     605        subp cfr, t2, t2
     606        move t2, sp
    472607    else
    473         subp cfr, t4, sp
     608        subp cfr, t2, sp
    474609    end
    475610end
     
    495630    callCallSlowPath(
    496631        slowPath,
    497         macro (callee)
    498             btpz t1, .dontUpdateSP
     632        macro (callee, calleeFrame)
     633            btpz calleeFrame, .dontUpdateSP
    499634            if ARMv7
    500                 addp CallerFrameAndPCSize, t1, t1
    501                 move t1, sp
     635                addp CallerFrameAndPCSize, calleeFrame, calleeFrame
     636                move calleeFrame, sp
    502637            else
    503                 addp CallerFrameAndPCSize, t1, sp
     638                addp CallerFrameAndPCSize, calleeFrame, sp
    504639            end
    505640        .dontUpdateSP:
     
    597732        baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
    598733        if JSVALUE64
    599             cCall2(osrSlowPath, cfr, PC)
     734            move cfr, a0
     735            move PC, a1
     736            cCall2(osrSlowPath)
    600737        else
    601738            # We are after the function prologue, but before we have set up sp from the CodeBlock.
    602739            # Temporarily align stack pointer for this call.
    603740            subp 8, sp
    604             cCall2(osrSlowPath, cfr, PC)
     741            move cfr, a0
     742            move PC, a1
     743            cCall2(osrSlowPath)
    605744            addp 8, sp
    606745        end
    607         btpz t0, .recover
     746        btpz r0, .recover
    608747        move cfr, sp # restore the previous sp
    609748        # pop the callerFrame since we will jump to a function that wants to save it
     
    616755            pop cfr
    617756        end
    618         jmp t0
     757        jmp r0
    619758    .recover:
    620759        codeBlockGetter(t1)
     
    641780    subp maxFrameExtentForSlowPathCall, sp # Set up temporary stack pointer for call
    642781    callSlowPath(_llint_stack_check)
    643     bpeq t1, 0, .stackHeightOKGetCodeBlock
    644     move t1, cfr
     782    bpeq r1, 0, .stackHeightOKGetCodeBlock
     783    move r1, cfr
    645784    dispatch(0) # Go to exception handler in PC
    646785
     
    739878    global _sanitizeStackForVMImpl
    740879    _sanitizeStackForVMImpl:
    741         if X86_64
    742             const vm = t4
    743             const address = t1
    744             const zeroValue = t0
    745         elsif X86_64_WIN
    746             const vm = t2
    747             const address = t1
    748             const zeroValue = t0
    749         elsif X86 or X86_WIN
    750             const vm = t2
    751             const address = t1
    752             const zeroValue = t0
    753         else
    754             const vm = a0
    755             const address = t1
    756             const zeroValue = t2
     880        # We need three non-aliased caller-save registers. We are guaranteed
     881        # this for a0, a1 and a2 on all architectures.
     882        if X86 or X86_WIN
     883            loadp 4[sp], a0
    757884        end
    758    
    759         if X86 or X86_WIN
    760             loadp 4[sp], vm
    761         end
     885        const vm = a0
     886        const address = a1
     887        const zeroValue = a2
    762888   
    763889        loadp VM::m_lastStackTop[vm], address
     
    778904    global _vmEntryRecord
    779905    _vmEntryRecord:
    780         if X86_64
    781             const entryFrame = t4
    782             const result = t0
    783         elsif X86 or X86_WIN or X86_64_WIN
    784             const entryFrame = t2
    785             const result = t0
    786         else
    787             const entryFrame = a0
    788             const result = t0
     906        if X86 or X86_WIN
     907            loadp 4[sp], a0
    789908        end
    790    
    791         if X86 or X86_WIN
    792             loadp 4[sp], entryFrame
    793         end
    794    
    795         vmEntryRecord(entryFrame, result)
     909
     910        vmEntryRecord(a0, r0)
    796911        ret
    797912end
     
    801916    _llint_entry:
    802917        crash()
    803     else
     918else
    804919    macro initPCRelative(pcBase)
    805         if X86_64 or X86_64_WIN
     920        if X86_64 or X86_64_WIN or X86 or X86_WIN
    806921            call _relativePCBase
    807922        _relativePCBase:
    808923            pop pcBase
    809         elsif X86 or X86_WIN
    810             call _relativePCBase
    811         _relativePCBase:
    812             pop pcBase
    813             loadp 20[sp], t4
    814924        elsif ARM64
    815925        elsif ARMv7
     
    832942end
    833943
     944# The PC base is in t1, as this is what _llint_entry leaves behind through
     945# initPCRelative(t1)
    834946macro setEntryAddress(index, label)
    835     if X86_64
    836         leap (label - _relativePCBase)[t1], t0
    837         move index, t2
    838         storep t0, [t4, t2, 8]
    839     elsif X86_64_WIN
    840         leap (label - _relativePCBase)[t1], t0
     947    if X86_64 or X86_64_WIN
     948        leap (label - _relativePCBase)[t1], t3
    841949        move index, t4
    842         storep t0, [t2, t4, 8]
     950        storep t3, [a0, t4, 8]
    843951    elsif X86 or X86_WIN
    844         leap (label - _relativePCBase)[t1], t0
    845         move index, t2
    846         storep t0, [t4, t2, 4]
     952        leap (label - _relativePCBase)[t1], t3
     953        move index, t4
     954        storep t3, [a0, t4, 4]
    847955    elsif ARM64
    848956        pcrtoaddr label, t1
    849         move index, t2
    850         storep t1, [a0, t2, 8]
     957        move index, t4
     958        storep t1, [a0, t4, 8]
    851959    elsif ARM or ARMv7 or ARMv7_TRADITIONAL
    852         mvlbl (label - _relativePCBase), t2
    853         addp t2, t1, t2
     960        mvlbl (label - _relativePCBase), t4
     961        addp t4, t1, t4
    854962        move index, t3
    855         storep t2, [a0, t3, 4]
     963        storep t4, [a0, t3, 4]
    856964    elsif SH4
    857         move (label - _relativePCBase), t2
    858         addp t2, t1, t2
     965        move (label - _relativePCBase), t4
     966        addp t4, t1, t4
    859967        move index, t3
    860         storep t2, [a0, t3, 4]
     968        storep t4, [a0, t3, 4]
    861969        flushcp # Force constant pool flush to avoid "pcrel too far" link error.
    862970    elsif MIPS
    863         la label, t2
     971        la label, t4
    864972        la _relativePCBase, t3
    865         subp t3, t2
    866         addp t2, t1, t2
     973        subp t3, t4
     974        addp t4, t1, t4
    867975        move index, t3
    868         storep t2, [a0, t3, 4]
     976        storep t4, [a0, t3, 4]
    869977    end
    870978end
     
    875983    functionPrologue()
    876984    pushCalleeSaves()
     985    if X86 or X86_WIN
     986        loadp 20[sp], a0
     987    end
    877988    initPCRelative(t1)
    878989
     
    12141325    callSlowPath(_llint_slow_path_size_frame_for_varargs)
    12151326    branchIfException(_llint_throw_from_slow_path_trampoline)
    1216     # calleeFrame in t1
     1327    # calleeFrame in r1
    12171328    if JSVALUE64
    1218         move t1, sp
     1329        move r1, sp
    12191330    else
    12201331        # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
    12211332        if ARMv7
    1222             subp t1, CallerFrameAndPCSize, t2
     1333            subp r1, CallerFrameAndPCSize, t2
    12231334            move t2, sp
    12241335        else
    1225             subp t1, CallerFrameAndPCSize, sp
     1336            subp r1, CallerFrameAndPCSize, sp
    12261337        end
    12271338    end
     
    12321343    callSlowPath(_llint_slow_path_size_frame_for_varargs)
    12331344    branchIfException(_llint_throw_from_slow_path_trampoline)
    1234     # calleeFrame in t1
     1345    # calleeFrame in r1
    12351346    if JSVALUE64
    1236         move t1, sp
     1347        move r1, sp
    12371348    else
    12381349        # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
    12391350        if ARMv7
    1240             subp t1, CallerFrameAndPCSize, t2
     1351            subp r1, CallerFrameAndPCSize, t2
    12411352            move t2, sp
    12421353        else
    1243             subp t1, CallerFrameAndPCSize, sp
     1354            subp r1, CallerFrameAndPCSize, sp
    12441355        end
    12451356    end
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r189279 r189293  
    2323
    2424
    25 # Crash course on the language that this is written in (which I just call
    26 # "assembly" even though it's more than that):
    27 #
    28 # - Mostly gas-style operand ordering. The last operand tends to be the
    29 #   destination. So "a := b" is written as "mov b, a". But unlike gas,
    30 #   comparisons are in-order, so "if (a < b)" is written as
    31 #   "bilt a, b, ...".
    32 #
    33 # - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
    34 #   Currently this is just 32-bit so "i" and "p" are interchangeable
    35 #   except when an op supports one but not the other.
    36 #
    37 # - In general, valid operands for macro invocations and instructions are
    38 #   registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
    39 #   (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
    40 #   (eg "_foo" or ".foo"). Macro invocations can also take anonymous
    41 #   macros as operands. Instructions cannot take anonymous macros.
    42 #
    43 # - Labels must have names that begin with either "_" or ".".  A "." label
    44 #   is local and gets renamed before code gen to minimize namespace
    45 #   pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
    46 #   may or may not be removed during code gen depending on whether the asm
    47 #   conventions for C name mangling on the target platform mandate a "_"
    48 #   prefix.
    49 #
    50 # - A "macro" is a lambda expression, which may be either anonymous or
    51 #   named. But this has caveats. "macro" can take zero or more arguments,
    52 #   which may be macros or any valid operands, but it can only return
    53 #   code. But you can do Turing-complete things via continuation passing
    54 #   style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
    55 #   that, since you'll just crash the assembler.
    56 #
    57 # - An "if" is a conditional on settings. Any identifier supplied in the
    58 #   predicate of an "if" is assumed to be a #define that is available
    59 #   during code gen. So you can't use "if" for computation in a macro, but
    60 #   you can use it to select different pieces of code for different
    61 #   platforms.
    62 #
    63 # - Arguments to macros follow lexical scoping rather than dynamic scoping.
    64 #   Const's also follow lexical scoping and may override (hide) arguments
    65 #   or other consts. All variables (arguments and constants) can be bound
    66 #   to operands. Additionally, arguments (but not constants) can be bound
    67 #   to macros.
    68 
    69 
    70 # Below we have a bunch of constant declarations. Each constant must have
    71 # a corresponding ASSERT() in LLIntData.cpp.
    72 
    7325# Utilities
    7426macro dispatch(advance)
     
    9042macro dispatchAfterCall()
    9143    loadi ArgumentCount + TagOffset[cfr], PC
    92     loadi 4[PC], t2
    93     storei t1, TagOffset[cfr, t2, 8]
    94     storei t0, PayloadOffset[cfr, t2, 8]
    95     valueProfile(t1, t0, 4 * (CallOpCodeSize - 1), t3)
     44    loadi 4[PC], t3
     45    storei r1, TagOffset[cfr, t3, 8]
     46    storei r0, PayloadOffset[cfr, t3, 8]
     47    valueProfile(r1, r0, 4 * (CallOpCodeSize - 1), t3)
    9648    dispatch(CallOpCodeSize)
    9749end
    9850
    99 macro cCall2(function, arg1, arg2)
    100     if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
    101         move arg1, a0
    102         move arg2, a1
     51macro cCall2(function)
     52    if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
    10353        call function
    10454    elsif X86 or X86_WIN
    10555        subp 8, sp
    106         push arg2
    107         push arg1
     56        push a1
     57        push a0
    10858        call function
    10959        addp 16, sp
    110     elsif SH4
    111         setargs arg1, arg2
    112         call function
    11360    elsif C_LOOP
    114         cloopCallSlowPath function, arg1, arg2
     61        cloopCallSlowPath function, a0, a1
    11562    else
    11663        error
     
    11865end
    11966
    120 macro cCall2Void(function, arg1, arg2)
     67macro cCall2Void(function)
    12168    if C_LOOP
    122         cloopCallSlowPathVoid function, arg1, arg2
     69        cloopCallSlowPathVoid function, a0, a1
    12370    else
    124         cCall2(function, arg1, arg2)
     71        cCall2(function)
    12572    end
    12673end
    12774
    128 # This barely works. arg3 and arg4 should probably be immediates.
    129 macro cCall4(function, arg1, arg2, arg3, arg4)
    130     if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
    131         move arg1, a0
    132         move arg2, a1
    133         move arg3, a2
    134         move arg4, a3
     75macro cCall4(function)
     76    if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
    13577        call function
    13678    elsif X86 or X86_WIN
    137         push arg4
    138         push arg3
    139         push arg2
    140         push arg1
     79        push a3
     80        push a2
     81        push a1
     82        push a0
    14183        call function
    14284        addp 16, sp
    143     elsif SH4
    144         setargs arg1, arg2, arg3, arg4
    145         call function
    14685    elsif C_LOOP
    14786        error
     
    15291
    15392macro callSlowPath(slowPath)
    154     cCall2(slowPath, cfr, PC)
    155     move t0, PC
     93    move cfr, a0
     94    move PC, a1
     95    cCall2(slowPath)
     96    move r0, PC
    15697end
    15798
    15899macro doVMEntry(makeCall)
    159     if X86 or X86_WIN
    160         const entry = t4
    161         const vm = t3
    162         const protoCallFrame = t5
    163 
    164         const temp1 = t0
    165         const temp2 = t1
    166         const temp3 = t2
    167         const temp4 = t3 # same as vm
    168     elsif ARM or ARMv7 or ARMv7_TRADITIONAL or C_LOOP
    169         const entry = a0
    170         const vm = a1
    171         const protoCallFrame = a2
    172 
    173         const temp1 = t3
    174         const temp2 = t4
    175         const temp3 = t5
    176         const temp4 = t4 # Same as temp2
    177     elsif MIPS
    178         const entry = a0
    179         const vm = a1
    180         const protoCallFrame = a2
    181 
    182         const temp1 = t3
    183         const temp2 = t5
    184         const temp3 = t4
    185         const temp4 = t6
    186     elsif SH4
    187         const entry = a0
    188         const vm = a1
    189         const protoCallFrame = a2
    190 
    191         const temp1 = t3
    192         const temp2 = a3
    193         const temp3 = t8
    194         const temp4 = t9
    195     end
    196 
    197100    functionPrologue()
    198101    pushCalleeSaves()
    199102
     103    # x86 needs to load arguments from the stack
    200104    if X86 or X86_WIN
    201         loadp 12[cfr], vm
    202         loadp 8[cfr], entry
     105        loadp 16[cfr], a2
     106        loadp 12[cfr], a1
     107        loadp 8[cfr], a0
    203108    end
    204109
     110    const entry = a0
     111    const vm = a1
     112    const protoCallFrame = a2
     113
     114    # We are using t3, t4 and t5 as temporaries through the function.
     115    # Since we have the guarantee that tX != aY when X != Y, we are safe from
     116    # aliasing problems with our arguments.
     117
    205118    if ARMv7
    206         vmEntryRecord(cfr, temp1)
    207         move temp1, sp
     119        vmEntryRecord(cfr, t3)
     120        move t3, sp
    208121    else
    209122        vmEntryRecord(cfr, sp)
     
    211124
    212125    storep vm, VMEntryRecord::m_vm[sp]
    213     loadp VM::topCallFrame[vm], temp2
    214     storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
    215     loadp VM::topVMEntryFrame[vm], temp2
    216     storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
     126    loadp VM::topCallFrame[vm], t4
     127    storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
     128    loadp VM::topVMEntryFrame[vm], t4
     129    storep t4, VMEntryRecord::m_prevTopVMEntryFrame[sp]
    217130
    218131    # Align stack pointer
    219132    if X86_WIN
    220         addp CallFrameAlignSlots * SlotSize, sp, temp1
    221         andp ~StackAlignmentMask, temp1
    222         subp temp1, CallFrameAlignSlots * SlotSize, sp
     133        addp CallFrameAlignSlots * SlotSize, sp, t3
     134        andp ~StackAlignmentMask, t3
     135        subp t3, CallFrameAlignSlots * SlotSize, sp
    223136    elsif ARM or ARMv7 or ARMv7_TRADITIONAL
    224         addp CallFrameAlignSlots * SlotSize, sp, temp1
    225         clrbp temp1, StackAlignmentMask, temp1
     137        addp CallFrameAlignSlots * SlotSize, sp, t3
     138        clrbp t3, StackAlignmentMask, t3
    226139        if ARMv7
    227             subp temp1, CallFrameAlignSlots * SlotSize, temp1
    228             move temp1, sp
     140            subp t3, CallFrameAlignSlots * SlotSize, t3
     141            move t3, sp
    229142        else
    230             subp temp1, CallFrameAlignSlots * SlotSize, sp
     143            subp t3, CallFrameAlignSlots * SlotSize, sp
    231144        end
    232145    end
    233146
    234     if X86 or X86_WIN
    235         loadp 16[cfr], protoCallFrame
    236     end
    237 
    238     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
    239     addp CallFrameHeaderSlots, temp2, temp2
    240     lshiftp 3, temp2
    241     subp sp, temp2, temp1
     147    loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
     148    addp CallFrameHeaderSlots, t4, t4
     149    lshiftp 3, t4
     150    subp sp, t4, t3
    242151
    243152    # Ensure that we have enough additional stack capacity for the incoming args,
    244153    # and the frame for the JS code we're executing. We need to do this check
    245154    # before we start copying the args from the protoCallFrame below.
    246     bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
     155    bpaeq t3, VM::m_jsStackLimit[vm], .stackHeightOK
    247156
    248157    if C_LOOP
    249         move entry, temp2
    250         move vm, temp3
    251         cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
     158        move entry, t4
     159        move vm, t5
     160        cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
    252161        bpeq t0, 0, .stackCheckFailed
    253         move temp2, entry
    254         move temp3, vm
     162        move t4, entry
     163        move t5, vm
    255164        jmp .stackHeightOK
    256165
    257166.stackCheckFailed:
    258         move temp2, entry
    259         move temp3, vm
     167        move t4, entry
     168        move t5, vm
    260169    end
    261170
    262171    subp 8, sp # Align stack for cCall2() to make a call.
    263     cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
     172    move vm, a0
     173    move protoCallFrame, a1
     174    cCall2(_llint_throw_stack_overflow_error)
    264175
    265176    if ARMv7
    266         vmEntryRecord(cfr, temp1)
    267         move temp1, sp
     177        vmEntryRecord(cfr, t3)
     178        move t3, sp
    268179    else
    269180        vmEntryRecord(cfr, sp)
    270181    end
    271182
    272     loadp VMEntryRecord::m_vm[sp], temp3
    273     loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
    274     storep temp4, VM::topCallFrame[temp3]
    275     loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
    276     storep temp4, VM::topVMEntryFrame[temp3]
     183    loadp VMEntryRecord::m_vm[sp], t5
     184    loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
     185    storep t4, VM::topCallFrame[t5]
     186    loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], t4
     187    storep t4, VM::topVMEntryFrame[t5]
    277188
    278189    if ARMv7
    279         subp cfr, CalleeRegisterSaveSize, temp3
    280         move temp3, sp
     190        subp cfr, CalleeRegisterSaveSize, t5
     191        move t5, sp
    281192    else
    282193        subp cfr, CalleeRegisterSaveSize, sp
     
    288199
    289200.stackHeightOK:
    290     move temp1, sp
    291     move 4, temp1
     201    move t3, sp
     202    move 4, t3
    292203
    293204.copyHeaderLoop:
    294     subi 1, temp1
    295     loadi TagOffset[protoCallFrame, temp1, 8], temp3
    296     storei temp3, TagOffset + CodeBlock[sp, temp1, 8]
    297     loadi PayloadOffset[protoCallFrame, temp1, 8], temp3
    298     storei temp3, PayloadOffset + CodeBlock[sp, temp1, 8]
    299     btinz temp1, .copyHeaderLoop
    300 
    301     loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
    302     subi 1, temp2
    303     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
    304     subi 1, temp3
    305 
    306     bieq temp2, temp3, .copyArgs
     205    subi 1, t3
     206    loadi TagOffset[protoCallFrame, t3, 8], t5
     207    storei t5, TagOffset + CodeBlock[sp, t3, 8]
     208    loadi PayloadOffset[protoCallFrame, t3, 8], t5
     209    storei t5, PayloadOffset + CodeBlock[sp, t3, 8]
     210    btinz t3, .copyHeaderLoop
     211
     212    loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
     213    subi 1, t4
     214    loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t5
     215    subi 1, t5
     216
     217    bieq t4, t5, .copyArgs
    307218.fillExtraArgsLoop:
    308     subi 1, temp3
    309     storei UndefinedTag, ThisArgumentOffset + 8 + TagOffset[sp, temp3, 8]
    310     storei 0, ThisArgumentOffset + 8 + PayloadOffset[sp, temp3, 8]
    311     bineq temp2, temp3, .fillExtraArgsLoop
     219    subi 1, t5
     220    storei UndefinedTag, ThisArgumentOffset + 8 + TagOffset[sp, t5, 8]
     221    storei 0, ThisArgumentOffset + 8 + PayloadOffset[sp, t5, 8]
     222    bineq t4, t5, .fillExtraArgsLoop
    312223
    313224.copyArgs:
    314     loadp ProtoCallFrame::args[protoCallFrame], temp1
     225    loadp ProtoCallFrame::args[protoCallFrame], t3
    315226
    316227.copyArgsLoop:
    317     btiz temp2, .copyArgsDone
    318     subi 1, temp2
    319     loadi TagOffset[temp1, temp2, 8], temp3
    320     storei temp3, ThisArgumentOffset + 8 + TagOffset[sp, temp2, 8]
    321     loadi PayloadOffset[temp1, temp2, 8], temp3
    322     storei temp3, ThisArgumentOffset + 8 + PayloadOffset[sp, temp2, 8]
     228    btiz t4, .copyArgsDone
     229    subi 1, t4
     230    loadi TagOffset[t3, t4, 8], t5
     231    storei t5, ThisArgumentOffset + 8 + TagOffset[sp, t4, 8]
     232    loadi PayloadOffset[t3, t4, 8], t5
     233    storei t5, ThisArgumentOffset + 8 + PayloadOffset[sp, t4, 8]
    323234    jmp .copyArgsLoop
    324235
     
    327238    storep cfr, VM::topVMEntryFrame[vm]
    328239
    329     makeCall(entry, temp1, temp2)
     240    makeCall(entry, t3, t4)
    330241
    331242    if ARMv7
    332         vmEntryRecord(cfr, temp1)
    333         move temp1, sp
     243        vmEntryRecord(cfr, t3)
     244        move t3, sp
    334245    else
    335246        vmEntryRecord(cfr, sp)
    336247    end
    337248
    338     loadp VMEntryRecord::m_vm[sp], temp3
    339     loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
    340     storep temp4, VM::topCallFrame[temp3]
    341     loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
    342     storep temp4, VM::topVMEntryFrame[temp3]
     249    loadp VMEntryRecord::m_vm[sp], t5
     250    loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
     251    storep t4, VM::topCallFrame[t5]
     252    loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], t4
     253    storep t4, VM::topVMEntryFrame[t5]
    343254
    344255    if ARMv7
    345         subp cfr, CalleeRegisterSaveSize, temp3
    346         move temp3, sp
     256        subp cfr, CalleeRegisterSaveSize, t5
     257        move t5, sp
    347258    else
    348259        subp cfr, CalleeRegisterSaveSize, sp
     
    356267macro makeJavaScriptCall(entry, temp, unused)
    357268    addp CallerFrameAndPCSize, sp
    358     checkStackPointerAlignment(t2, 0xbad0dc02)
     269    checkStackPointerAlignment(temp, 0xbad0dc02)
    359270    if C_LOOP
    360271        cloopCallJSFunction entry
     
    362273        call entry
    363274    end
    364     checkStackPointerAlignment(t2, 0xbad0dc03)
     275    checkStackPointerAlignment(temp, 0xbad0dc03)
    365276    subp CallerFrameAndPCSize, sp
    366277end
     
    377288        move 0, temp2
    378289        move temp2, 4[sp] # put 0 in ReturnPC
    379         move sp, t2 # t2 is ecx
     290        move sp, a0 # a0 is ecx
    380291        push temp2 # Push dummy arg1
    381         push t2
     292        push a0
    382293        call temp1
    383294        addp 8, sp
     
    430341# in the instruction stream you'd like to print out.
    431342macro traceOperand(fromWhere, operand)
    432     cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
    433     move t0, PC
    434     move t1, cfr
     343    move fromWhere, a2
     344    move operand, a3
     345    move cfr, a0
     346    move PC, a1
     347    cCall4(_llint_trace_operand)
     348    move r0, PC
     349    move r1, cfr
    435350end
    436351
     
    439354# value.
    440355macro traceValue(fromWhere, operand)
    441     cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
    442     move t0, PC
    443     move t1, cfr
     356    move fromWhere, a2
     357    move operand, a3
     358    move cfr, a0
     359    move PC, a1
     360    cCall4(_llint_trace_value)
     361    move r0, PC
     362    move r1, cfr
    444363end
    445364
     
    447366macro callCallSlowPath(slowPath, action)
    448367    storep PC, ArgumentCount + TagOffset[cfr]
    449     cCall2(slowPath, cfr, PC)
    450     action(t0)
     368    move cfr, a0
     369    move PC, a1
     370    cCall2(slowPath)
     371    action(r0, r1)
    451372end
    452373
    453374macro callWatchdogTimerHandler(throwHandler)
    454375    storei PC, ArgumentCount + TagOffset[cfr]
    455     cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
    456     btpnz t0, throwHandler
     376    move cfr, a0
     377    move PC, a1
     378    cCall2(_llint_slow_path_handle_watchdog_timer)
     379    btpnz r0, throwHandler
    457380    loadi ArgumentCount + TagOffset[cfr], PC
    458381end
     
    463386        macro ()
    464387            storei PC, ArgumentCount + TagOffset[cfr]
    465             cCall2(_llint_loop_osr, cfr, PC)
    466             btpz t0, .recover
    467             move t1, sp
    468             jmp t0
     388            move cfr, a0
     389            move PC, a1
     390            cCall2(_llint_loop_osr)
     391            btpz r0, .recover
     392            move r1, sp
     393            jmp r0
    469394        .recover:
    470395            loadi ArgumentCount + TagOffset[cfr], PC
     
    577502                # We make two extra slots because cCall2 will poke.
    578503                subp 8, sp
    579                 cCall2Void(_llint_write_barrier_slow, cfr, t2)
     504                move t2, a1 # t2 can be a0 on x86
     505                move cfr, a0
     506                cCall2Void(_llint_write_barrier_slow)
    580507                addp 8, sp
    581508                pop PC, cfr
     
    611538                # We make two extra slots because cCall2 will poke.
    612539                subp 8, sp
    613                 cCall2Void(_llint_write_barrier_slow, cfr, t3)
     540                move cfr, a0
     541                move t3, a1
     542                cCall2Void(_llint_write_barrier_slow)
    614543                addp 8, sp
    615544                pop PC, cfr
     
    650579    loadi PayloadOffset + ArgumentCount[cfr], t0
    651580    biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
    652     cCall2(slowPath, cfr, PC)   # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error
    653     btiz t0, .noError
    654     move t1, cfr   # t1 contains caller frame
     581    move cfr, a0
     582    move PC, a1
     583    cCall2(slowPath)   # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error
     584    btiz r0, .noError
     585    move r1, cfr   # r1 contains caller frame
    655586    jmp _llint_throw_from_slow_path_trampoline
    656587
    657588.noError:
    658     # t1 points to ArityCheckData.
    659     loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
    660     btpz t2, .proceedInline
     589    # r1 points to ArityCheckData.
     590    loadp CommonSlowPaths::ArityCheckData::thunkToCall[r1], t3
     591    btpz t3, .proceedInline
    661592   
    662     loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t5
    663     loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
    664     call t2
     593    loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], a0
     594    loadp CommonSlowPaths::ArityCheckData::returnPC[r1], a1
     595    call t3
    665596    if ASSERT_ENABLED
    666597        loadp ReturnPC[cfr], t0
     
    670601
    671602.proceedInline:
    672     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
     603    loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
    673604    btiz t1, .continue
    674605
     
    752683    loadi 8[PC], t0
    753684    loadp PayloadOffset[cfr, t0, 8], t0
    754     loadp JSFunction::m_rareData[t0], t4
    755     btpz t4, .opCreateThisSlow
    756     loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
    757     loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
     685    loadp JSFunction::m_rareData[t0], t5
     686    btpz t5, .opCreateThisSlow
     687    loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t5], t1
     688    loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t5], t2
    758689    btpz t1, .opCreateThisSlow
    759     loadpFromInstruction(4, t4)
    760     bpeq t4, 1, .hasSeenMultipleCallee
    761     bpneq t4, t0, .opCreateThisSlow
     690    loadpFromInstruction(4, t5)
     691    bpeq t5, 1, .hasSeenMultipleCallee
     692    bpneq t5, t0, .opCreateThisSlow
    762693.hasSeenMultipleCallee:
    763694    allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
     
    20071938        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t3
    20081939        storep cfr, VM::topCallFrame[t3]
    2009         move cfr, t2  # t2 = ecx
    2010         storep t2, [sp]
     1940        move cfr, a0  # a0 = ecx
     1941        storep a0, [sp]
    20111942        loadi Callee + PayloadOffset[cfr], t1
    20121943        loadp JSFunction::m_executable[t1], t1
     
    20231954        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
    20241955        storep cfr, VM::topCallFrame[t1]
    2025         if MIPS or SH4
    2026             move cfr, a0
    2027         else
    2028             move cfr, t0
    2029         end
     1956        move cfr, a0
    20301957        loadi Callee + PayloadOffset[cfr], t1
    20311958        loadp JSFunction::m_executable[t1], t1
     
    22702197    loadisFromInstruction(3, t1)
    22712198    loadConstantOrVariable(t1, t2, t3)
    2272     loadpFromInstruction(5, t4)
    2273     btpz t4, .noVariableWatchpointSet
    2274     notifyWrite(t4, .pDynamic)
     2199    loadpFromInstruction(5, t5)
     2200    btpz t5, .noVariableWatchpointSet
     2201    notifyWrite(t5, .pDynamic)
    22752202.noVariableWatchpointSet:
    22762203    loadisFromInstruction(6, t1)
     
    23972324    loadp VM::m_typeProfilerLog[t1], t1
    23982325
    2399     # t0 is holding the payload, t4 is holding the tag.
     2326    # t0 is holding the payload, t5 is holding the tag.
    24002327    loadisFromInstruction(1, t2)
    2401     loadConstantOrVariable(t2, t4, t0)
     2328    loadConstantOrVariable(t2, t5, t0)
    24022329
    24032330    bieq t4, EmptyValueTag, .opProfileTypeDone
     
    24072334
    24082335    # Store the JSValue onto the log entry.
    2409     storei t4, TypeProfilerLog::LogEntry::value + TagOffset[t2]
     2336    storei t5, TypeProfilerLog::LogEntry::value + TagOffset[t2]
    24102337    storei t0, TypeProfilerLog::LogEntry::value + PayloadOffset[t2]
    24112338
     
    24142341    storep t3, TypeProfilerLog::LogEntry::location[t2]
    24152342
    2416     bieq t4, CellTag, .opProfileTypeIsCell
     2343    bieq t5, CellTag, .opProfileTypeIsCell
    24172344    storei 0, TypeProfilerLog::LogEntry::structureID[t2]
    24182345    jmp .opProfileTypeSkipIsCell
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r189279 r189293  
    4747    loadp CodeBlock::m_instructions[PB], PB
    4848    loadisFromInstruction(1, t1)
    49     storeq t0, [cfr, t1, 8]
    50     valueProfile(t0, (CallOpCodeSize - 1), t2)
     49    storeq r0, [cfr, t1, 8]
     50    valueProfile(r0, (CallOpCodeSize - 1), t3)
    5151    dispatch(CallOpCodeSize)
    5252end
    5353
    54 macro cCall2(function, arg1, arg2)
     54macro cCall2(function)
    5555    checkStackPointerAlignment(t4, 0xbad0c002)
    56     if X86_64
    57         move arg1, t4
    58         move arg2, t5
     56    if X86_64 or ARM64
    5957        call function
    6058    elsif X86_64_WIN
     
    6260        # See macro cCall2Void for an implementation when the return type <= 8 bytes.
    6361        # On Win64, when the return type is larger than 8 bytes, we need to allocate space on the stack for the return value.
    64         # On entry rcx (t2), should contain a pointer to this stack space. The other parameters are shifted to the right,
    65         # rdx (t1) should contain the first argument, and r8 (t6) should contain the second argument.
    66         # On return, rax contains a pointer to this stack value, and we then need to copy the 16 byte return value into rax (t0) and rdx (t1)
     62        # On entry rcx (a0), should contain a pointer to this stack space. The other parameters are shifted to the right,
     63        # rdx (a1) should contain the first argument, and r8 (a2) should contain the second argument.
     64        # On return, rax contains a pointer to this stack value, and we then need to copy the 16 byte return value into rax (r0) and rdx (r1)
    6765        # since the return value is expected to be split between the two.
    6866        # See http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
    69         move arg1, t1
    70         move arg2, t6
     67        move a1, a2
     68        move a0, a1
    7169        subp 48, sp
    72         move sp, t2
    73         addp 32, t2
     70        move sp, a0
     71        addp 32, a0
    7472        call function
    7573        addp 48, sp
    76         move 8[t0], t1
    77         move [t0], t0
    78     elsif ARM64
    79         move arg1, t0
    80         move arg2, t1
    81         call function
     74        move 8[r0], r1
     75        move [r0], r0
    8276    elsif C_LOOP
    83         cloopCallSlowPath function, arg1, arg2
     77        cloopCallSlowPath function, a0, a1
    8478    else
    8579        error
     
    8781end
    8882
    89 macro cCall2Void(function, arg1, arg2)
     83macro cCall2Void(function)
    9084    if C_LOOP
    91         cloopCallSlowPathVoid function, arg1, arg2
     85        cloopCallSlowPathVoid function, a0, a1
    9286    elsif X86_64_WIN
    9387        # Note: we cannot use the cCall2 macro for Win64 in this case,
     
    9690        # We also need to make room on the stack for all four parameter registers.
    9791        # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
    98         move arg2, t1
    99         move arg1, t2
    10092        subp 32, sp
    10193        call function
    10294        addp 32, sp
    10395    else
    104         cCall2(function, arg1, arg2)
     96        cCall2(function)
    10597    end
    10698end
    10799
    108100# This barely works. arg3 and arg4 should probably be immediates.
    109 macro cCall4(function, arg1, arg2, arg3, arg4)
     101macro cCall4(function)
    110102    checkStackPointerAlignment(t4, 0xbad0c004)
    111     if X86_64
    112         move arg1, t4
    113         move arg2, t5
    114         move arg3, t1
    115         move arg4, t2
     103    if X86_64 or ARM64
    116104        call function
    117105    elsif X86_64_WIN
     
    119107        # We also need to make room on the stack for all four parameter registers.
    120108        # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
    121         move arg1, t2
    122         move arg2, t1
    123         move arg3, t6
    124         move arg4, t7
    125         subp 32, sp
     109        subp 64, sp
    126110        call function
    127         addp 32, sp
    128     elsif ARM64
    129         move arg1, t0
    130         move arg2, t1
    131         move arg3, t2
    132         move arg4, t3
    133         call function
    134     elsif C_LOOP
    135         error
     111        addp 64, sp
    136112    else
    137113        error
     
    140116
    141117macro doVMEntry(makeCall)
    142     if X86_64
    143         const entry = t4
    144         const vm = t5
    145         const protoCallFrame = t1
    146 
    147         const previousCFR = t0
    148         const previousPC = t6
    149         const temp1 = t0
    150         const temp2 = t3
    151         const temp3 = t6
    152     elsif X86_64_WIN
    153         const entry = t2
    154         const vm = t1
    155         const protoCallFrame = t6
    156 
    157         const previousCFR = t0
    158         const previousPC = t4
    159         const temp1 = t0
    160         const temp2 = t3
    161         const temp3 = t7
    162     elsif ARM64 or C_LOOP
    163         const entry = a0
    164         const vm = a1
    165         const protoCallFrame = a2
    166 
    167         const previousCFR = t5
    168         const previousPC = lr
    169         const temp1 = t3
    170         const temp2 = t4
    171         const temp3 = t6
    172     end
    173 
    174118    functionPrologue()
    175119    pushCalleeSaves()
    176120
     121    const entry = a0
     122    const vm = a1
     123    const protoCallFrame = a2
     124
    177125    vmEntryRecord(cfr, sp)
    178126
    179     checkStackPointerAlignment(temp2, 0xbad0dc01)
     127    checkStackPointerAlignment(t4, 0xbad0dc01)
    180128
    181129    storep vm, VMEntryRecord::m_vm[sp]
    182     loadp VM::topCallFrame[vm], temp2
    183     storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
    184     loadp VM::topVMEntryFrame[vm], temp2
    185     storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
    186 
    187     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
    188     addp CallFrameHeaderSlots, temp2, temp2
    189     lshiftp 3, temp2
    190     subp sp, temp2, temp1
     130    loadp VM::topCallFrame[vm], t4
     131    storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
     132    loadp VM::topVMEntryFrame[vm], t4
     133    storep t4, VMEntryRecord::m_prevTopVMEntryFrame[sp]
     134
     135    loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
     136    addp CallFrameHeaderSlots, t4, t4
     137    lshiftp 3, t4
     138    subp sp, t4, t3
    191139
    192140    # Ensure that we have enough additional stack capacity for the incoming args,
    193141    # and the frame for the JS code we're executing. We need to do this check
    194142    # before we start copying the args from the protoCallFrame below.
    195     bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
     143    bpaeq t3, VM::m_jsStackLimit[vm], .stackHeightOK
    196144
    197145    if C_LOOP
    198         move entry, temp2
    199         move vm, temp3
    200         cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
     146        move entry, t4
     147        move vm, t5
     148        cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
    201149        bpeq t0, 0, .stackCheckFailed
    202         move temp2, entry
    203         move temp3, vm
     150        move t4, entry
     151        move t5, vm
    204152        jmp .stackHeightOK
    205153
    206154.stackCheckFailed:
    207         move temp2, entry
    208         move temp3, vm
     155        move t4, entry
     156        move t5, vm
    209157    end
    210158
    211     cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
    212 
    213     vmEntryRecord(cfr, temp2)
    214 
    215     loadp VMEntryRecord::m_vm[temp2], vm
    216     loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
    217     storep temp3, VM::topCallFrame[vm]
    218     loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
    219     storep temp3, VM::topVMEntryFrame[vm]
     159    move vm, a0
     160    move protoCallFrame, a1
     161    cCall2(_llint_throw_stack_overflow_error)
     162
     163    vmEntryRecord(cfr, t4)
     164
     165    loadp VMEntryRecord::m_vm[t4], vm
     166    loadp VMEntryRecord::m_prevTopCallFrame[t4], extraTempReg
     167    storep extraTempReg, VM::topCallFrame[vm]
     168    loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], extraTempReg
     169    storep extraTempReg, VM::topVMEntryFrame[vm]
    220170
    221171    subp cfr, CalleeRegisterSaveSize, sp
     
    226176
    227177.stackHeightOK:
    228     move temp1, sp
    229     move 4, temp1
     178    move t3, sp
     179    move 4, t3
    230180
    231181.copyHeaderLoop:
    232     subi 1, temp1
    233     loadq [protoCallFrame, temp1, 8], temp3
    234     storeq temp3, CodeBlock[sp, temp1, 8]
    235     btinz temp1, .copyHeaderLoop
    236 
    237     loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
    238     subi 1, temp2
    239     loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
    240     subi 1, temp3
    241 
    242     bieq temp2, temp3, .copyArgs
    243     move ValueUndefined, temp1
     182    subi 1, t3
     183    loadq [protoCallFrame, t3, 8], extraTempReg
     184    storeq extraTempReg, CodeBlock[sp, t3, 8]
     185    btinz t3, .copyHeaderLoop
     186
     187    loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
     188    subi 1, t4
     189    loadi ProtoCallFrame::paddedArgCount[protoCallFrame], extraTempReg
     190    subi 1, extraTempReg
     191
     192    bieq t4, extraTempReg, .copyArgs
     193    move ValueUndefined, t3
    244194.fillExtraArgsLoop:
    245     subi 1, temp3
    246     storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
    247     bineq temp2, temp3, .fillExtraArgsLoop
     195    subi 1, extraTempReg
     196    storeq t3, ThisArgumentOffset + 8[sp, extraTempReg, 8]
     197    bineq t4, extraTempReg, .fillExtraArgsLoop
    248198
    249199.copyArgs:
    250     loadp ProtoCallFrame::args[protoCallFrame], temp1
     200    loadp ProtoCallFrame::args[protoCallFrame], t3
    251201
    252202.copyArgsLoop:
    253     btiz temp2, .copyArgsDone
    254     subi 1, temp2
    255     loadq [temp1, temp2, 8], temp3
    256     storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
     203    btiz t4, .copyArgsDone
     204    subi 1, t4
     205    loadq [t3, t4, 8], extraTempReg
     206    storeq extraTempReg, ThisArgumentOffset + 8[sp, t4, 8]
    257207    jmp .copyArgsLoop
    258208
    259209.copyArgsDone:
    260210    if ARM64
    261         move sp, temp2
    262         storep temp2, VM::topCallFrame[vm]
     211        move sp, t4
     212        storep t4, VM::topCallFrame[vm]
    263213    else
    264214        storep sp, VM::topCallFrame[vm]
     
    266216    storep cfr, VM::topVMEntryFrame[vm]
    267217
    268     move 0xffff000000000000, csr1
    269     addp 2, csr1, csr2
    270 
    271     checkStackPointerAlignment(temp3, 0xbad0dc02)
    272 
    273     makeCall(entry, temp1)
    274 
    275     checkStackPointerAlignment(temp3, 0xbad0dc03)
    276 
    277     vmEntryRecord(cfr, temp2)
    278 
    279     loadp VMEntryRecord::m_vm[temp2], vm
    280     loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
    281     storep temp3, VM::topCallFrame[vm]
    282     loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
    283     storep temp3, VM::topVMEntryFrame[vm]
     218    move TagTypeNumber, tagTypeNumber
     219    addp TagBitTypeOther, tagTypeNumber, tagMask
     220
     221    checkStackPointerAlignment(extraTempReg, 0xbad0dc02)
     222
     223    makeCall(entry, t3)
     224
     225    # We may have just made a call into a JS function, so we can't rely on sp
     226    # for anything but the fact that our own locals (ie the VMEntryRecord) are
     227    # not below it. It also still has to be aligned, though.
     228    checkStackPointerAlignment(t2, 0xbad0dc03)
     229
     230    vmEntryRecord(cfr, t4)
     231
     232    loadp VMEntryRecord::m_vm[t4], vm
     233    loadp VMEntryRecord::m_prevTopCallFrame[t4], t2
     234    storep t2, VM::topCallFrame[vm]
     235    loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], t2
     236    storep t2, VM::topVMEntryFrame[vm]
    284237
    285238    subp cfr, CalleeRegisterSaveSize, sp
     
    306259    move entry, temp
    307260    storep cfr, [sp]
    308     if X86_64
    309         move sp, t4
    310     elsif X86_64_WIN
    311         move sp, t2
    312     elsif ARM64 or C_LOOP
    313         move sp, a0
    314     end
     261    move sp, a0
    315262    if C_LOOP
    316263        storep lr, 8[sp]
     
    337284
    338285    loadp VMEntryRecord::m_vm[t2], t3
    339     loadp VMEntryRecord::m_prevTopCallFrame[t2], t5
    340     storep t5, VM::topCallFrame[t3]
    341     loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], t5
    342     storep t5, VM::topVMEntryFrame[t3]
     286    loadp VMEntryRecord::m_prevTopCallFrame[t2], extraTempReg
     287    storep extraTempReg, VM::topCallFrame[t3]
     288    loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], extraTempReg
     289    storep extraTempReg, VM::topVMEntryFrame[t3]
    343290
    344291    subp cfr, CalleeRegisterSaveSize, sp
     
    351298macro prepareStateForCCall()
    352299    leap [PB, PC, 8], PC
    353     move PB, t3
    354300end
    355301
    356302macro restoreStateAfterCCall()
    357     move t0, PC
    358     move t3, PB
     303    move r0, PC
    359304    subp PB, PC
    360305    rshiftp 3, PC
     
    363308macro callSlowPath(slowPath)
    364309    prepareStateForCCall()
    365     cCall2(slowPath, cfr, PC)
     310    move cfr, a0
     311    move PC, a1
     312    cCall2(slowPath)
    366313    restoreStateAfterCCall()
    367314end
     
    369316macro traceOperand(fromWhere, operand)
    370317    prepareStateForCCall()
    371     cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
     318    move fromWhere, a2
     319    move operand, a3
     320    move cfr, a0
     321    move PC, a1
     322    cCall4(_llint_trace_operand)
    372323    restoreStateAfterCCall()
    373324end
     
    375326macro traceValue(fromWhere, operand)
    376327    prepareStateForCCall()
    377     cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
     328    move fromWhere, a2
     329    move operand, a3
     330    move cfr, a0
     331    move PC, a1
     332    cCall4(_llint_trace_value)
    378333    restoreStateAfterCCall()
    379334end
     
    383338    storei PC, ArgumentCount + TagOffset[cfr]
    384339    prepareStateForCCall()
    385     cCall2(slowPath, cfr, PC)
    386     action(t0)
     340    move cfr, a0
     341    move PC, a1
     342    cCall2(slowPath)
     343    action(r0, r1)
    387344end
    388345
     
    390347    storei PC, ArgumentCount + TagOffset[cfr]
    391348    prepareStateForCCall()
    392     cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
    393     btpnz t0, throwHandler
    394     move t3, PB
     349    move cfr, a0
     350    move PC, a1
     351    cCall2(_llint_slow_path_handle_watchdog_timer)
     352    btpnz r0, throwHandler
    395353    loadi ArgumentCount + TagOffset[cfr], PC
    396354end
     
    402360            storei PC, ArgumentCount + TagOffset[cfr]
    403361            prepareStateForCCall()
    404             cCall2(_llint_loop_osr, cfr, PC)
    405             btpz t0, .recover
    406             move t1, sp
    407             jmp t0
     362            move cfr, a0
     363            move PC, a1
     364            cCall2(_llint_loop_osr)
     365            btpz r0, .recover
     366            move r1, sp
     367            jmp r0
    408368        .recover:
    409             move t3, PB
    410369            loadi ArgumentCount + TagOffset[cfr], PC
    411370        end)
     
    448407                btbnz gcData, .writeBarrierDone
    449408                push PB, PC
    450                 cCall2Void(_llint_write_barrier_slow, cfr, t2)
     409                move t2, a1 # t2 can be a0 (not on 64 bits, but better safe than sorry)
     410                move cfr, a0
     411                cCall2Void(_llint_write_barrier_slow)
    451412                pop PC, PB
    452413            end
     
    478439                btbnz gcData, .writeBarrierDone
    479440                push PB, PC
    480                 cCall2Void(_llint_write_barrier_slow, cfr, t3)
     441                move cfr, a0
     442                move t3, a1
     443                cCall2Void(_llint_write_barrier_slow)
    481444                pop PC, PB
    482445            end
     
    539502    biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
    540503    prepareStateForCCall()
    541     cCall2(slowPath, cfr, PC)   # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
    542     btiz t0, .noError
    543     move t1, cfr   # t1 contains caller frame
     504    move cfr, a0
     505    move PC, a1
     506    cCall2(slowPath)   # This slowPath has the protocol: r0 = 0 => no error, r0 != 0 => error
     507    btiz r0, .noError
     508    move r1, cfr   # r1 contains caller frame
    544509    jmp _llint_throw_from_slow_path_trampoline
    545510
    546511.noError:
    547     # t1 points to ArityCheckData.
    548     loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
    549     btpz t2, .proceedInline
     512    # r1 points to ArityCheckData.
     513    loadp CommonSlowPaths::ArityCheckData::thunkToCall[r1], t3
     514    btpz t3, .proceedInline
    550515   
    551     loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
    552     loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
    553     call t2
     516    loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], a0
     517    loadp CommonSlowPaths::ArityCheckData::returnPC[r1], a1
     518    call t3
    554519    if ASSERT_ENABLED
    555520        loadp ReturnPC[cfr], t0
     
    559524
    560525.proceedInline:
    561     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
     526    loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
    562527    btiz t1, .continue
    563528
     
    605570
    606571# Instruction implementations
    607 
    608572_llint_op_enter:
    609573    traceExecution()
     
    637601    loadisFromInstruction(2, t0)
    638602    loadp [cfr, t0, 8], t0
    639     loadp JSFunction::m_rareData[t0], t4
    640     btpz t4, .opCreateThisSlow
    641     loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
    642     loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
     603    loadp JSFunction::m_rareData[t0], t3
     604    btpz t3, .opCreateThisSlow
     605    loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t3], t1
     606    loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t3], t2
    643607    btpz t1, .opCreateThisSlow
    644     loadpFromInstruction(4, t4)
    645     bpeq t4, 1, .hasSeenMultipleCallee
    646     bpneq t4, t0, .opCreateThisSlow
     608    loadpFromInstruction(4, t3)
     609    bpeq t3, 1, .hasSeenMultipleCallee
     610    bpneq t3, t0, .opCreateThisSlow
    647611.hasSeenMultipleCallee:
    648612    allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
     
    17771741    checkSwitchToJITForEpilogue()
    17781742    loadisFromInstruction(1, t2)
    1779     loadConstantOrVariable(t2, t0)
     1743    loadConstantOrVariable(t2, r0)
    17801744    doReturn()
    17811745
     
    18401804    loadisFromInstruction(1, t0)
    18411805    assertNotConstant(t0)
    1842     loadq [cfr, t0, 8], t0
     1806    loadq [cfr, t0, 8], r0
    18431807    doReturn()
    18441808
     
    18651829    functionPrologue()
    18661830    storep 0, CodeBlock[cfr]
    1867     if X86_64 or X86_64_WIN
    1868         if X86_64
    1869             const arg1 = t4  # t4 = rdi
    1870             const arg2 = t5  # t5 = rsi
    1871             const temp = t1
    1872         elsif X86_64_WIN
    1873             const arg1 = t2  # t2 = rcx
    1874             const arg2 = t1  # t1 = rdx
    1875             const temp = t0
    1876         end
    1877         loadp Callee[cfr], t0
    1878         andp MarkedBlockMask, t0, t1
    1879         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
    1880         storep cfr, VM::topCallFrame[t1]
    1881         move cfr, arg1
    1882         loadp Callee[cfr], arg2
    1883         loadp JSFunction::m_executable[arg2], temp
    1884         checkStackPointerAlignment(t3, 0xdead0001)
     1831    loadp Callee[cfr], t0
     1832    andp MarkedBlockMask, t0, t1
     1833    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
     1834    storep cfr, VM::topCallFrame[t1]
     1835    if ARM64 or C_LOOP
     1836        storep lr, ReturnPC[cfr]
     1837    end
     1838    move cfr, a0
     1839    loadp Callee[cfr], t1
     1840    loadp JSFunction::m_executable[t1], t1
     1841    checkStackPointerAlignment(t3, 0xdead0001)
     1842    if C_LOOP
     1843        cloopCallNative executableOffsetToFunction[t1]
     1844    else
    18851845        if X86_64_WIN
    18861846            subp 32, sp
    18871847        end
    1888         call executableOffsetToFunction[temp]
     1848        call executableOffsetToFunction[t1]
    18891849        if X86_64_WIN
    18901850            addp 32, sp
    18911851        end
    1892         loadp Callee[cfr], t3
    1893         andp MarkedBlockMask, t3
    1894         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    1895     elsif ARM64 or C_LOOP
    1896         loadp Callee[cfr], t0
    1897         andp MarkedBlockMask, t0, t1
    1898         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
    1899         storep cfr, VM::topCallFrame[t1]
    1900         preserveReturnAddressAfterCall(t3)
    1901         storep t3, ReturnPC[cfr]
    1902         move cfr, t0
    1903         loadp Callee[cfr], t1
    1904         loadp JSFunction::m_executable[t1], t1
    1905         if C_LOOP
    1906             cloopCallNative executableOffsetToFunction[t1]
    1907         else
    1908             call executableOffsetToFunction[t1]
    1909         end
    1910         restoreReturnAddressBeforeReturn(t3)
    1911         loadp Callee[cfr], t3
    1912         andp MarkedBlockMask, t3
    1913         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    1914     else
    1915         error
    19161852    end
     1853    loadp Callee[cfr], t3
     1854    andp MarkedBlockMask, t3
     1855    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    19171856
    19181857    functionEpilogue()
  • trunk/Source/JavaScriptCore/offlineasm/arm.rb

    r172429 r189293  
    2727require "opt"
    2828require "risc"
     29
     30# GPR conventions, to match the baseline JIT
     31#
     32#  x0 => t0, a0, r0
     33#  x1 => t1, a1, r1
     34#  x2 => t2, a2, r2
     35#  x3 => t3, a3, r3
     36#  x6 =>            (callee-save scratch)
     37#  x7 => cfr        (ARMv7 only)
     38#  x8 => t4         (callee-save)
     39#  x9 => t5         (callee-save)
     40# x10 =>            (callee-save scratch)
     41# x11 => cfr        (ARM and ARMv7 traditional)
     42# x12 =>            (callee-save scratch)
     43#  lr => lr
     44#  sp => sp
     45#  pc => pc
     46#
     47# FPR conventions, to match the baseline JIT
     48#
     49# d0 => ft0, fa0, fr
     50# d1 => ft1, fa1
     51# d2 => ft2
     52# d3 => ft3
     53# d4 => ft4
     54# d5 => ft5
     55# d6 =>              (scratch)
     56# d7 =>              (scratch)
    2957
    3058def isARMv7
     
    120148    def armOperand
    121149        case name
    122         when "ft0", "fr"
     150        when "ft0", "fr", "fa0"
    123151            "d0"
    124         when "ft1"
     152        when "ft1", "fa1"
    125153            "d1"
    126154        when "ft2"
  • trunk/Source/JavaScriptCore/offlineasm/arm64.rb

    r175514 r189293  
    3838# GPR conventions, to match the baseline JIT:
    3939#
    40 #  x0  => return value, cached result, first argument, t0, a0, r0
     40#  x0  => t0, a0, r0
    4141#  x1  => t1, a1, r1
    4242#  x2  => t2, a2
    43 #  x3  => a3
    44 #  x5  => t4
    45 #  x6  => t6
    46 #  x9  => (nonArgGPR1 in baseline)
    47 # x13  => scratch (unused in baseline)
    48 # x16  => scratch
    49 # x17  => scratch
    50 # x23  => t3
    51 # x24  => t5
    52 # x27  => csr1 (tagTypeNumber)
    53 # x28  => csr2 (tagMask)
     43#  x3  => t3, a3
     44#  x4  => t4
     45#  x5  => t5
     46# x13  =>                  (scratch)
     47# x16  =>                  (scratch)
     48# x17  =>                  (scratch)
     49# x26  =>             csr0 (PB)
     50# x27  =>             csr1 (tagTypeNumber)
     51# x28  =>             csr2 (tagMask)
    5452# x29  => cfr
    5553#  sp  => sp
    5654#  lr  => lr
    5755#
    58 # FPR conentions, to match the baseline JIT:
     56# FPR conventions, to match the baseline JIT:
    5957#
    60 #  q0  => ft0
    61 #  q1  => ft1
    62 #  q2  => ft2
    63 #  q3  => ft3
    64 #  q4  => ft4 (unused in baseline)
    65 #  q5  => ft5 (unused in baseline)
     58#  q0  => ft0, fa0, fr
     59#  q1  => ft1, fa1
     60#  q2  => ft2, fa2
     61#  q3  => ft3, fa3
     62#  q4  => ft4          (unused in baseline)
     63#  q5  => ft5          (unused in baseline)
    6664# q31  => scratch
    6765
     
    110108        when 't2', 'a2'
    111109            arm64GPRName('x2', kind)
    112         when 'a3'
     110        when 't3', 'a3'
    113111            arm64GPRName('x3', kind)
    114         when 't3'
    115             arm64GPRName('x23', kind)
    116112        when 't4'
     113            arm64GPRName('x4', kind)
     114        when 't5'
    117115            arm64GPRName('x5', kind)
    118         when 't5'
    119             arm64GPRName('x24', kind)
    120         when 't6'
    121             arm64GPRName('x6', kind)
    122         when 't7'
    123             arm64GPRName('x7', kind)
    124116        when 'cfr'
    125117            arm64GPRName('x29', kind)
     118        when 'csr0'
     119            arm64GPRName('x26', kind)
    126120        when 'csr1'
    127121            arm64GPRName('x27', kind)
     
    141135    def arm64Operand(kind)
    142136        case @name
    143         when 'ft0'
     137        when 'ft0', 'fr', 'fa0'
    144138            arm64FPRName('q0', kind)
    145         when 'ft1'
     139        when 'ft1', 'fa1'
    146140            arm64FPRName('q1', kind)
    147         when 'ft2'
     141        when 'ft2', 'fa2'
    148142            arm64FPRName('q2', kind)
    149         when 'ft3'
     143        when 'ft3', 'fa3'
    150144            arm64FPRName('q3', kind)
    151145        when 'ft4'
  • trunk/Source/JavaScriptCore/offlineasm/cloop.rb

    r172429 r189293  
    7171        # The cloop is modelled on the ARM implementation. Hence, the a0-a3
    7272        # registers are aliases for r0-r3 i.e. t0-t3 in our case.
    73         when "t0", "a0"
     73        when "t0", "a0", "r0"
    7474            "t0"
    75         when "t1", "a1"
     75        when "t1", "a1", "r1"
    7676            "t1"
    7777        when "t2", "a2"
     
    8383        when "t5"
    8484            "t5"
    85         when "t6"
     85        when "csr0"
    8686            "pcBase"
    87         when "t7"
    88             "t7"
    8987        when "csr1"
    9088            "tagTypeNumber"
  • trunk/Source/JavaScriptCore/offlineasm/mips.rb

    r173232 r189293  
    2525require 'risc'
    2626
     27# GPR conventions, to match the baseline JIT
     28#
     29# $a0 => a0
     30# $a1 => a1
     31# $a2 => a2
     32# $a3 => a3
     33# $v0 => t0, r0
     34# $v1 => t1, r1
     35# $t2 =>         t2
     36# $t3 =>         t3
     37# $t4 =>         t4
     38# $t5 =>         t5
     39# $t6 =>            (scratch)
     40# $t7 =>            (scratch)
     41# $t8 =>            (scratch)
     42# $t9 =>            (stores the callee of a call opcode)
     43# $gp =>            (globals)
     44# $s4 =>            (callee-save used to preserve $gp across calls)
     45# $ra => lr
     46# $sp => sp
     47# $fp => cfr
     48#
     49# FPR conventions, to match the baseline JIT
     50# We don't have fa2 or fa3!
     51#  $f0 => ft0, fr
     52#  $f2 => ft1
     53#  $f4 => ft2
     54#  $f6 => ft3
     55#  $f8 => ft4
     56# $f10 => ft5
     57# $f12 =>        fa0
     58# $f14 =>        fa1
     59# $f16 =>            (scratch)
     60# $f18 =>            (scratch)
     61
    2762class Assembler
    2863    def putStr(str)
     
    5893end
    5994
    60 MIPS_TEMP_GPRS = [SpecialRegister.new("$t5"), SpecialRegister.new("$t6"), SpecialRegister.new("$t7"),
    61                     SpecialRegister.new("$t8")]
     95MIPS_TEMP_GPRS = [SpecialRegister.new("$t6"), SpecialRegister.new("$t7"), SpecialRegister.new("$t8")]
    6296MIPS_ZERO_REG = SpecialRegister.new("$zero")
    6397MIPS_GP_REG = SpecialRegister.new("$gp")
     
    86120        when "a3"
    87121            "$a3"
    88         when "r0", "t0"
     122        when "t0", "r0"
    89123            "$v0"
    90         when "r1", "t1"
     124        when "t1", "r1"
    91125            "$v1"
    92126        when "t2"
    93127            "$t2"
    94128        when "t3"
    95             "$s3"
    96         when "t4"   # PC reg in llint
    97             "$s2"
     129            "$t3"
     130        when "t4"
     131            "$t4"
    98132        when "t5"
    99133            "$t5"
    100         when "t6"
    101             "$t6"
    102         when "t7"
    103             "$t7"
    104         when "t8"
    105             "$t8"
    106134        when "cfr"
    107135            "$fp"
  • trunk/Source/JavaScriptCore/offlineasm/registers.rb

    r167094 r189293  
    3232     "t4",
    3333     "t5",
    34      "t6",
    35      "t7",
    36      "t8",
    37      "t9",
    3834     "cfr",
    3935     "a0",
     
    4743     "pc",
    4844     # 64-bit only registers:
    49      "csr1",  # tag type number register
    50      "csr2"   # tag mask register
     45     "csr0",
     46     "csr1",
     47     "csr2",
     48     "csr3",
     49     "csr4",
     50     "csr5",
     51     "csr6"
    5152    ]
    5253
  • trunk/Source/JavaScriptCore/offlineasm/sh4.rb

    r172429 r189293  
    2525require 'risc'
    2626
     27# GPR conventions, to match the baseline JIT
     28#
     29#  r0 => t0, r0
     30#  r1 => t1, r1
     31#  r2 => t4
     32#  r3 => t5
     33#  r4 =>         a0
     34#  r5 =>         a1
     35#  r6 => t2,     a2
     36#  r7 => t3,     a3
     37# r10 =>            (scratch)
     38# r11 =>            (scratch)
     39# r13 =>            (scratch)
     40# r14 => cfr
     41# r15 => sp
     42#  pr => lr
     43
     44# FPR conventions, to match the baseline JIT
     45# We don't have fa2 or fa3!
     46#  dr0 => ft0, fr
     47#  dr2 => ft1
     48#  dr4 => ft2,   fa0
     49#  dr6 => ft3,   fa1
     50#  dr8 => ft4
     51# dr10 => ft5
     52# dr12 =>             (scratch)
     53
    2754class Node
    2855    def sh4SingleHi
     
    5279end
    5380
    54 SH4_TMP_GPRS = [ SpecialRegister.new("r3"), SpecialRegister.new("r11"), SpecialRegister.new("r13") ]
    55 SH4_TMP_FPRS = [ SpecialRegister.new("dr10") ]
     81SH4_TMP_GPRS = [ SpecialRegister.new("r10"), SpecialRegister.new("r11"), SpecialRegister.new("r13") ]
     82SH4_TMP_FPRS = [ SpecialRegister.new("dr12") ]
    5683
    5784class RegisterID
    5885    def sh4Operand
    5986        case name
    60         when "t0"
     87        when "a0"
     88            "r4"
     89        when "a1"
     90            "r5"
     91        when "r0", "t0"
    6192            "r0"
    62         when "t1"
     93        when "r1", "t1"
    6394            "r1"
    64         when "t2"
     95        when "a2", "t2"
     96            "r6"
     97        when "a3", "t3"
     98            "r7"
     99        when "t4"
    65100            "r2"
    66         when "t3"
    67             "r10"
    68         when "t4", "a0"
    69             "r4"
    70         when "t5", "a1"
    71             "r5"
    72         when "t6", "a2"
    73             "r6"
    74         when "t7", "a3"
    75             "r7"
    76         when "t8"
    77             "r8"
    78         when "t9"
    79             "r9"
     101        when "t5"
     102            "r3"
    80103        when "cfr"
    81104            "r14"
     
    97120        when "ft1"
    98121            "dr2"
    99         when "ft2"
     122        when "ft2", "fa0"
    100123            "dr4"
    101         when "ft3"
     124        when "ft3", "fa1"
    102125            "dr6"
    103126        when "ft4"
    104127            "dr8"
    105         when "fa0"
    106             "dr12"
     128        when "ft5"
     129            "dr10"
    107130        else
    108131            raise "Bad register #{name} for SH4 at #{codeOriginString}"
  • trunk/Source/JavaScriptCore/offlineasm/x86.rb

    r172754 r189293  
    2525require "config"
    2626
     27# GPR conventions, to match the baseline JIT:
     28#
     29#
     30# On x86-32 bits (windows and non-windows)
     31# a0, a1, a2, a3 are only there for ease-of-use of offlineasm; they are not
     32# actually considered as such by the ABI and we need to push/pop our arguments
     33# on the stack. a0 and a1 are ecx and edx to follow fastcall.
     34#
     35# eax => t0, a2, r0
     36# edx => t1, a1, r1
     37# ecx => t2, a0
     38# ebx => t3, a3     (callee-save)
     39# esi => t4         (callee-save)
     40# edi => t5         (callee-save)
     41# ebp => cfr
     42# esp => sp
     43#
     44# On x86-64 non-windows
     45#
     46# rax => t0,     r0
     47# rdi =>     a0
     48# rsi => t1, a1
     49# rdx => t2, a2, r1
     50# rcx => t3, a3
     51#  r8 => t4
     52# r10 => t5
     53# rbx =>             csr0 (callee-save, PB, unused in baseline)
     54# r12 =>             csr1 (callee-save)
     55# r13 =>             csr2 (callee-save)
     56# r14 =>             csr3 (callee-save, tagTypeNumber)
     57# r15 =>             csr4 (callee-save, tagMask)
     58# rsp => sp
     59# rbp => cfr
     60# r11 =>                  (scratch)
     61#
     62# On x86-64 windows
     63# Arguments need to be push/pop'd on the stack in addition to being stored in
     64# the registers. Also, >8 return types are returned in a weird way.
     65#
     66# rax => t0,     r0
     67# rcx =>     a0
     68# rdx => t1, a1, r1
     69#  r8 => t2, a2
     70#  r9 => t3, a3
     71# r10 => t4
     72# rbx =>             csr0 (callee-save, PB, unused in baseline)
     73# rsi =>             csr1 (callee-save)
     74# rdi =>             csr2 (callee-save)
     75# r12 =>             csr3 (callee-save)
     76# r13 =>             csr4 (callee-save)
     77# r14 =>             csr5 (callee-save, tagTypeNumber)
     78# r15 =>             csr6 (callee-save, tagMask)
     79# rsp => sp
     80# rbp => cfr
     81# r11 =>                  (scratch)
     82
    2783def isX64
    2884    case $activeBackend
     
    4096end
    4197
     98def isWin
     99    case $activeBackend
     100    when "X86"
     101        false
     102    when "X86_WIN"
     103        true
     104    when "X86_64"
     105        false
     106    when "X86_64_WIN"
     107        true
     108    else
     109        raise "bad value for $activeBackend: #{$activeBackend}"
     110    end
     111end
     112
    42113def useX87
    43114    case $activeBackend
     
    55126end
    56127
    57 def isWindows
     128def isCompilingOnWindows
    58129    ENV['OS'] == 'Windows_NT'
    59130end
    60131
    61132def isGCC
    62     !isWindows
     133    !isCompilingOnWindows
    63134end
    64135
    65136def isMSVC
    66     isWindows
     137    isCompilingOnWindows
    67138end
    68139
    69140def isIntelSyntax
    70     isWindows
     141    isCompilingOnWindows
    71142end
    72143
     
    142213X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
    143214
     215def x86GPRName(name, kind)
     216    case name
     217    when "eax", "ebx", "ecx", "edx"
     218        name8 = name[1] + 'l'
     219        name16 = name[1..2]
     220    when "esi", "edi", "ebp", "esp"
     221        name16 = name[1..2]
     222        name8 = name16 + 'l'
     223    when "rax", "rbx", "rcx", "rdx"
     224        raise "bad GPR name #{name} in 32-bit X86" unless isX64
     225        name8 = name[1] + 'l'
     226        name16 = name[1..2]
     227    when "r8", "r9", "r10", "r12", "r13", "r14", "r15"
     228        raise "bad GPR name #{name} in 32-bit X86" unless isX64
     229        case kind
     230        when :half
     231            return register(name + "w")
     232        when :int
     233            return register(name + "d")
     234        when :ptr
     235            return register(name)
     236        when :quad
     237            return register(name)
     238        end
     239    else
     240        raise "bad GPR name #{name}"
     241    end
     242    case kind
     243    when :byte
     244        register(name8)
     245    when :half
     246        register(name16)
     247    when :int
     248        register("e" + name16)
     249    when :ptr
     250        register((isX64 ? "r" : "e") + name16)
     251    when :quad
     252        isX64 ? register("r" + name16) : raise
     253    else
     254        raise "invalid kind #{kind} for GPR #{name} in X86"
     255    end
     256end
     257
    144258class RegisterID
    145259    def supports8BitOnX86
    146         case name
    147         when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3", "t4", "t5"
     260        case x86GPR
     261        when "eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp"
    148262            true
    149         when "cfr", "ttnr", "tmr"
     263        when "r8", "r9", "r10", "r12", "r13", "r14", "r15"
    150264            false
    151         when "t6"
    152             isX64
    153265        else
    154266            raise
    155267        end
    156268    end
    157    
     269
     270    def x86GPR
     271        if isX64
     272            case name
     273            when "t0", "r0"
     274                "eax"
     275            when "r1"
     276                "edx" # t1 = a1 when isWin, t2 = a2 otherwise
     277            when "a0"
     278                isWin ? "ecx" : "edi"
     279            when "t1", "a1"
     280                isWin ? "edx" : "esi"
     281            when "t2", "a2"
     282                isWin ? "r8" : "edx"
     283            when "t3", "a3"
     284                isWin ? "r9" : "ecx"
     285            when "t4"
     286                isWin ? "r10" : "r8"
     287            when "t5"
     288                raise "cannot use register #{name} on X86-64 Windows" unless not isWin
     289                "r10"
     290            when "csr0"
     291                "ebx"
     292            when "csr1"
     293                "r12"
     294            when "csr2"
     295                "r13"
     296            when "csr3"
     297                isWin ? "esi" : "r14"
     298            when "csr4"
     299                isWin ? "edi" : "r15"
     300                "r15"
     301            when "csr5"
     302                raise "cannot use register #{name} on X86-64" unless isWin
     303                "r14"
     304            when "csr6"
     305                raise "cannot use register #{name} on X86-64" unless isWin
     306                "r15"
     307            when "cfr"
     308                "ebp"
     309            when "sp"
     310                "esp"
     311            else
     312                raise "cannot use register #{name} on X86"
     313            end
     314        else
     315            case name
     316            when "t0", "r0", "a2"
     317                "eax"
     318            when "t1", "r1", "a1"
     319                "edx"
     320            when "t2", "a0"
     321                "ecx"
     322            when "t3", "a3"
     323                "ebx"
     324            when "t4"
     325                "esi"
     326            when "t5"
     327                "edi"
     328            when "cfr"
     329                "ebp"
     330            when "sp"
     331                "esp"
     332            end
     333        end
     334    end
     335
    158336    def x86Operand(kind)
    159         case name
    160         when "t0", "a0", "r0"
    161             case kind
    162             when :byte
    163                 register("al")
    164             when :half
    165                 register("ax")
    166             when :int
    167                 register("eax")
    168             when :ptr
    169                 isX64 ? register("rax") : register("eax")
    170             when :quad
    171                 isX64 ? register("rax") : raise
    172             else
    173                 raise "Invalid kind #{kind} for name #{name}"
    174             end
    175         when "t1", "a1", "r1"
    176             case kind
    177             when :byte
    178                 register("dl")
    179             when :half
    180                 register("dx")
    181             when :int
    182                 register("edx")
    183             when :ptr
    184                 isX64 ? register("rdx") : register("edx")
    185             when :quad
    186                 isX64 ? register("rdx") : raise
    187             else
    188                 raise
    189             end
    190         when "t2"
    191             case kind
    192             when :byte
    193                 register("cl")
    194             when :half
    195                 register("cx")
    196             when :int
    197                 register("ecx")
    198             when :ptr
    199                 isX64 ? register("rcx") : register("ecx")
    200             when :quad
    201                 isX64 ? register("rcx") : raise
    202             else
    203                 raise
    204             end
    205         when "t3"
    206             case kind
    207             when :byte
    208                 register("bl")
    209             when :half
    210                 register("bx")
    211             when :int
    212                 register("ebx")
    213             when :ptr
    214                 isX64 ? register("rbx") : register("ebx")
    215             when :quad
    216                 isX64 ? register("rbx") : raise
    217             else
    218                 raise
    219             end
    220         when "t4"
    221             case kind
    222             when :byte
    223                 register("dil")
    224             when :half
    225                 register("di")
    226             when :int
    227                 register("edi")
    228             when :ptr
    229                 isX64 ? register("rdi") : register("edi")
    230             when :quad
    231                 isX64 ? register("rdi") : raise
    232             else
    233                 raise
    234             end
    235         when "cfr"
    236             if isX64
    237                 case kind
    238                 when :half
    239                     register("bp")
    240                 when :int
    241                     register("ebp")
    242                 when :ptr
    243                     register("rbp")
    244                 when :quad
    245                     register("rbp")
    246                 else
    247                     raise
    248                 end
    249             else
    250                 case kind
    251                 when :half
    252                     register("bp")
    253                 when :int
    254                     register("ebp")
    255                 when :ptr
    256                     register("ebp")
    257                 else
    258                     raise
    259                 end
    260             end
    261         when "sp"
    262             case kind
    263             when :byte
    264                 register("spl")
    265             when :half
    266                 register("sp")
    267             when :int
    268                 register("esp")
    269             when :ptr
    270                 isX64 ? register("rsp") : register("esp")
    271             when :quad
    272                 isX64 ? register("rsp") : raise
    273             else
    274                 raise
    275             end
    276         when "t5"
    277             case kind
    278             when :byte
    279                 register("sil")
    280             when :half
    281                 register("si")
    282             when :int
    283                 register("esi")
    284             when :ptr
    285                 isX64 ? register("rsi") : register("esi")
    286             when :quad
    287                 isX64 ? register("rsi") : raise
    288             end
    289         when "t6"
    290             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
    291             case kind
    292             when :half
    293                 register("r8w")
    294             when :int
    295                 register("r8d")
    296             when :ptr
    297                 register("r8")
    298             when :quad
    299                 register("r8")
    300             end
    301         when "t7"
    302             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
    303             case kind
    304             when :half
    305                 register("r9w")
    306             when :int
    307                 register("r9d")
    308             when :ptr
    309                 register("r9")
    310             when :quad
    311                 register("r9")
    312             end
    313         when "csr1"
    314             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
    315             case kind
    316             when :half
    317                 register("r14w")
    318             when :int
    319                 register("r14d")
    320             when :ptr
    321                 register("r14")
    322             when :quad
    323                 register("r14")
    324             end
    325         when "csr2"
    326             raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
    327             case kind
    328             when :half
    329                 register("r15w")
    330             when :int
    331                 register("r15d")
    332             when :ptr
    333                 register("r15")
    334             when :quad
    335                 register("r15")
    336             end
    337         else
    338             raise "Bad register #{name} for X86 at #{codeOriginString}"
    339         end
    340     end
     337        x86GPRName(x86GPR, kind)
     338    end
     339
    341340    def x86CallOperand(kind)
    342         isX64 ? "#{callPrefix}#{x86Operand(:quad)}" : "#{callPrefix}#{x86Operand(:ptr)}"
     341        "#{callPrefix}#{x86Operand(:ptr)}"
    343342    end
    344343end
     
    598597   
    599598    def handleX86Shift(opcode, kind)
    600         if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
     599        if operands[0].is_a? Immediate or operands[0].x86GPR == "ecx"
    601600            $asm.puts "#{opcode} #{orderOperands(operands[0].x86Operand(:byte), operands[1].x86Operand(kind))}"
    602601        else
    603             cx = RegisterID.forName(nil, "t2")
    604             $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
     602            $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{x86GPRName("ecx", :ptr)}"
    605603            $asm.puts "#{opcode} #{orderOperands(register("cl"), operands[1].x86Operand(kind))}"
    606             $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
     604            $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{x86GPRName("ecx", :ptr)}"
    607605        end
    608606    end
     
    648646            end
    649647        else
    650             ax = RegisterID.new(nil, "t0")
     648            ax = RegisterID.new(nil, "r0")
    651649            $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
    652             $asm.puts "#{setOpcode} %al"
    653             $asm.puts "movzbl %al, %eax"
     650            $asm.puts "#{setOpcode} #{ax.x86Operand(:byte)}"
     651            if !isIntelSyntax
     652                $asm.puts "movzbl #{ax.x86Operand(:byte)}, #{ax.x86Operand(:int)}"
     653            else
     654                $asm.puts "movzx #{ax.x86Operand(:int)}, #{ax.x86Operand(:byte)}"
     655            end
    654656            $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
    655657        end
Note: See TracChangeset for help on using the changeset viewer.