<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[189293] trunk/Source/JavaScriptCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/189293">189293</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2015-09-03 15:16:23 -0700 (Thu, 03 Sep 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>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:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLinkcpp">trunk/Source/JavaScriptCore/ftl/FTLLink.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitFPRInfoh">trunk/Source/JavaScriptCore/jit/FPRInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitGPRInfoh">trunk/Source/JavaScriptCore/jit/GPRInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITArithmeticcpp">trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp">trunk/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmarmrb">trunk/Source/JavaScriptCore/offlineasm/arm.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmarm64rb">trunk/Source/JavaScriptCore/offlineasm/arm64.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmclooprb">trunk/Source/JavaScriptCore/offlineasm/cloop.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmmipsrb">trunk/Source/JavaScriptCore/offlineasm/mips.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmregistersrb">trunk/Source/JavaScriptCore/offlineasm/registers.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmsh4rb">trunk/Source/JavaScriptCore/offlineasm/sh4.rb</a></li>
<li><a href="#trunkSourceJavaScriptCoreofflineasmx86rb">trunk/Source/JavaScriptCore/offlineasm/x86.rb</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -1,3 +1,66 @@
</span><ins>+2015-09-03 Basile Clement <basile_clement@apple.com> and Michael Saboff <msaboff@apple.com>
+
+ 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:
+
</ins><span class="cx"> 2015-09-03 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> Get rid of RepatchBuffer and replace it with static functions
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -395,18 +395,14 @@
</span><span class="cx"> m_speculative->callOperationWithCallFrameRollbackOnException(m_codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck, GPRInfo::regT0);
</span><span class="cx"> if (maxFrameExtentForSlowPathCall)
</span><span class="cx"> addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
</span><del>- branchTest32(Zero, GPRInfo::regT0).linkTo(fromArityCheck, this);
</del><ins>+ branchTest32(Zero, GPRInfo::returnValueGPR).linkTo(fromArityCheck, this);
</ins><span class="cx"> emitStoreCodeOrigin(CodeOrigin(0));
</span><del>- GPRReg thunkReg;
-#if USE(JSVALUE64)
- thunkReg = GPRInfo::regT7;
-#else
- thunkReg = GPRInfo::regT5;
-#endif
</del><ins>+ GPRReg thunkReg = GPRInfo::argumentGPR1;
</ins><span class="cx"> CodeLocationLabel* arityThunkLabels =
</span><span class="cx"> m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters());
</span><span class="cx"> move(TrustedImmPtr(arityThunkLabels), thunkReg);
</span><del>- loadPtr(BaseIndex(thunkReg, GPRInfo::regT0, timesPtr()), thunkReg);
</del><ins>+ loadPtr(BaseIndex(thunkReg, GPRInfo::returnValueGPR, timesPtr()), thunkReg);
+ move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
</ins><span class="cx"> m_callArityFixup = call();
</span><span class="cx"> jump(fromArityCheck);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLinkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLink.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/ftl/FTLLink.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -165,14 +165,14 @@
</span><span class="cx"> jit.load64(vm.addressOfException(), GPRInfo::regT1);
</span><span class="cx"> jit.jitAssertIsNull(GPRInfo::regT1);
</span><span class="cx"> #endif
</span><del>- jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0);
</del><ins>+ jit.move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0);
</ins><span class="cx"> jit.emitFunctionEpilogue();
</span><del>- mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0));
</del><ins>+ mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0));
</ins><span class="cx"> jit.emitFunctionPrologue();
</span><span class="cx"> CodeLocationLabel* arityThunkLabels =
</span><span class="cx"> vm.arityCheckFailReturnThunks->returnPCsFor(vm, codeBlock->numParameters());
</span><del>- jit.move(CCallHelpers::TrustedImmPtr(arityThunkLabels), GPRInfo::regT7);
- jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::regT7, GPRInfo::regT0, CCallHelpers::timesPtr()), GPRInfo::regT7);
</del><ins>+ jit.move(CCallHelpers::TrustedImmPtr(arityThunkLabels), GPRInfo::argumentGPR1);
+ jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::argumentGPR1, GPRInfo::argumentGPR0, CCallHelpers::timesPtr()), GPRInfo::argumentGPR1);
</ins><span class="cx"> CCallHelpers::Call callArityFixup = jit.call();
</span><span class="cx"> jit.emitFunctionEpilogue();
</span><span class="cx"> mainPathJumps.append(jit.jump());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitFPRInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/FPRInfo.h (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/FPRInfo.h        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/FPRInfo.h        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -268,15 +268,16 @@
</span><span class="cx"> class FPRInfo {
</span><span class="cx"> public:
</span><span class="cx"> typedef FPRReg RegisterType;
</span><del>- static const unsigned numberOfRegisters = 6;
</del><ins>+ static const unsigned numberOfRegisters = 7;
</ins><span class="cx">
</span><span class="cx"> // Temporary registers.
</span><span class="cx"> static const FPRReg fpRegT0 = MIPSRegisters::f0;
</span><del>- static const FPRReg fpRegT1 = MIPSRegisters::f4;
- static const FPRReg fpRegT2 = MIPSRegisters::f6;
- static const FPRReg fpRegT3 = MIPSRegisters::f8;
- static const FPRReg fpRegT4 = MIPSRegisters::f10;
- static const FPRReg fpRegT5 = MIPSRegisters::f18;
</del><ins>+ static const FPRReg fpRegT1 = MIPSRegisters::f2;
+ static const FPRReg fpRegT2 = MIPSRegisters::f4;
+ static const FPRReg fpRegT3 = MIPSRegisters::f6;
+ static const FPRReg fpRegT4 = MIPSRegisters::f8;
+ static const FPRReg fpRegT5 = MIPSRegisters::f10;
+ static const FPRReg fpRegT6 = MIPSRegisters::f18;
</ins><span class="cx">
</span><span class="cx"> static const FPRReg returnValueFPR = MIPSRegisters::f0;
</span><span class="cx">
</span><span class="lines">@@ -286,7 +287,7 @@
</span><span class="cx"> static FPRReg toRegister(unsigned index)
</span><span class="cx"> {
</span><span class="cx"> static const FPRReg registerForIndex[numberOfRegisters] = {
</span><del>- fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 };
</del><ins>+ fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5, fpRegT6 };
</ins><span class="cx">
</span><span class="cx"> ASSERT(index < numberOfRegisters);
</span><span class="cx"> return registerForIndex[index];
</span><span class="lines">@@ -297,11 +298,11 @@
</span><span class="cx"> ASSERT(reg != InvalidFPRReg);
</span><span class="cx"> ASSERT(reg < 20);
</span><span class="cx"> static const unsigned indexForRegister[20] = {
</span><del>- 0, InvalidIndex, InvalidIndex, InvalidIndex,
- 1, InvalidIndex, 2, InvalidIndex,
- 3, InvalidIndex, 4, InvalidIndex,
</del><ins>+ 0, InvalidIndex, 1, InvalidIndex,
+ 2, InvalidIndex, 3, InvalidIndex,
+ 4, InvalidIndex, 5, InvalidIndex,
</ins><span class="cx"> InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
</span><del>- InvalidIndex, InvalidIndex, 5, InvalidIndex,
</del><ins>+ InvalidIndex, InvalidIndex, 6, InvalidIndex,
</ins><span class="cx"> };
</span><span class="cx"> unsigned result = indexForRegister[reg];
</span><span class="cx"> return result;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitGPRInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/GPRInfo.h (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/GPRInfo.h        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/GPRInfo.h        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -31,6 +31,11 @@
</span><span class="cx">
</span><span class="cx"> namespace JSC {
</span><span class="cx">
</span><ins>+// We use the same conventions in the basline JIT as in the LLint. If you
+// change mappings in the GPRInfo, you should change them in the offlineasm
+// compiler adequately. The register naming conventions are described at the
+// top of the LowLevelInterpreter.asm file.
+
</ins><span class="cx"> typedef MacroAssembler::RegisterID GPRReg;
</span><span class="cx"> #define InvalidGPRReg ((::JSC::GPRReg)-1)
</span><span class="cx">
</span><span class="lines">@@ -294,8 +299,6 @@
</span><span class="cx"> };
</span><span class="cx"> #endif // USE(JSVALUE32_64)
</span><span class="cx">
</span><del>-// The baseline JIT requires that regT3 be callee-preserved.
-
</del><span class="cx"> #if CPU(X86)
</span><span class="cx"> #define NUMBER_OF_ARGUMENT_REGISTERS 0u
</span><span class="cx">
</span><span class="lines">@@ -305,25 +308,21 @@
</span><span class="cx"> static const unsigned numberOfRegisters = 6;
</span><span class="cx"> static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
</span><span class="cx">
</span><del>- // Note: regT3 is required to be callee-preserved.
-
</del><span class="cx"> // Temporary registers.
</span><span class="cx"> static const GPRReg regT0 = X86Registers::eax;
</span><span class="cx"> static const GPRReg regT1 = X86Registers::edx;
</span><span class="cx"> static const GPRReg regT2 = X86Registers::ecx;
</span><del>- static const GPRReg regT3 = X86Registers::ebx;
- static const GPRReg regT4 = X86Registers::edi;
- static const GPRReg regT5 = X86Registers::esi;
- // These registers match the baseline JIT.
- static const GPRReg cachedResultRegister = regT0;
- static const GPRReg cachedResultRegister2 = regT1;
</del><ins>+ static const GPRReg regT3 = X86Registers::ebx; // Callee-save
+ static const GPRReg regT4 = X86Registers::esi; // Callee-save
+ static const GPRReg regT5 = X86Registers::edi; // Callee-save
</ins><span class="cx"> static const GPRReg callFrameRegister = X86Registers::ebp;
</span><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><span class="cx"> static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
</span><span class="cx"> static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
</span><ins>+ static const GPRReg argumentGPR2 = X86Registers::eax; // regT0
+ static const GPRReg argumentGPR3 = X86Registers::ebx; // regT3
</ins><span class="cx"> static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
</span><del>- static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
- static const GPRReg nonArgGPR2 = X86Registers::ebx; // regT3
</del><ins>+ static const GPRReg nonArgGPR1 = X86Registers::edi; // regT5
</ins><span class="cx"> static const GPRReg returnValueGPR = X86Registers::eax; // regT0
</span><span class="cx"> static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
</span><span class="cx"> static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
</span><span class="lines">@@ -345,7 +344,7 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(reg != InvalidGPRReg);
</span><span class="cx"> ASSERT(static_cast<int>(reg) < 8);
</span><del>- static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4 };
</del><ins>+ static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, 5 };
</ins><span class="cx"> unsigned result = indexForRegister[reg];
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -379,52 +378,74 @@
</span><span class="cx"> static const unsigned numberOfRegisters = 11;
</span><span class="cx"> static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
</span><span class="cx">
</span><del>- // Note: regT3 is required to be callee-preserved.
-
</del><span class="cx"> // These registers match the baseline JIT.
</span><del>- static const GPRReg cachedResultRegister = X86Registers::eax;
</del><span class="cx"> static const GPRReg callFrameRegister = X86Registers::ebp;
</span><span class="cx"> static const GPRReg tagTypeNumberRegister = X86Registers::r14;
</span><span class="cx"> static const GPRReg tagMaskRegister = X86Registers::r15;
</span><span class="cx"> // Temporary registers.
</span><span class="cx"> static const GPRReg regT0 = X86Registers::eax;
</span><ins>+#if !OS(WINDOWS)
+ static const GPRReg regT1 = X86Registers::esi;
+ static const GPRReg regT2 = X86Registers::edx;
+ static const GPRReg regT3 = X86Registers::ecx;
+ static const GPRReg regT4 = X86Registers::r8;
+ static const GPRReg regT5 = X86Registers::r10;
+ static const GPRReg regT6 = X86Registers::edi;
+ static const GPRReg regT7 = X86Registers::r9;
+#else
</ins><span class="cx"> static const GPRReg regT1 = X86Registers::edx;
</span><del>- static const GPRReg regT2 = X86Registers::ecx;
- static const GPRReg regT3 = X86Registers::ebx;
- static const GPRReg regT4 = X86Registers::edi;
- static const GPRReg regT5 = X86Registers::esi;
- static const GPRReg regT6 = X86Registers::r8;
- static const GPRReg regT7 = X86Registers::r9;
- static const GPRReg regT8 = X86Registers::r10;
- static const GPRReg regT9 = X86Registers::r12;
- static const GPRReg regT10 = X86Registers::r13;
</del><ins>+ static const GPRReg regT2 = X86Registers::r8;
+ static const GPRReg regT3 = X86Registers::r9;
+ static const GPRReg regT4 = X86Registers::r10;
+ static const GPRReg regT5 = X86Registers::ecx;
+#endif
+
+ static const GPRReg regCS0 = X86Registers::ebx;
+
+#if !OS(WINDOWS)
+ static const GPRReg regCS1 = X86Registers::r12;
+ static const GPRReg regCS2 = X86Registers::r13;
+ static const GPRReg regCS3 = X86Registers::r14;
+ static const GPRReg regCS4 = X86Registers::r15;
+#else
+ static const GPRReg regCS1 = X86Registers::esi;
+ static const GPRReg regCS2 = X86Registers::edi;
+ static const GPRReg regCS3 = X86Registers::r12;
+ static const GPRReg regCS4 = X86Registers::r13;
+ static const GPRReg regCS5 = X86Registers::r14;
+ static const GPRReg regCS6 = X86Registers::r15;
+#endif
+
</ins><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><span class="cx"> #if !OS(WINDOWS)
</span><del>- static const GPRReg argumentGPR0 = X86Registers::edi; // regT4
- static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
- static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
- static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
- static const GPRReg argumentGPR4 = X86Registers::r8; // regT6
- static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
</del><ins>+ static const GPRReg argumentGPR0 = X86Registers::edi; // regT6
+ static const GPRReg argumentGPR1 = X86Registers::esi; // regT1
+ static const GPRReg argumentGPR2 = X86Registers::edx; // regT2
+ static const GPRReg argumentGPR3 = X86Registers::ecx; // regT3
+ static const GPRReg argumentGPR4 = X86Registers::r8; // regT4
+ static const GPRReg argumentGPR5 = X86Registers::r9; // regT7
</ins><span class="cx"> #else
</span><del>- static const GPRReg argumentGPR0 = X86Registers::ecx;
- static const GPRReg argumentGPR1 = X86Registers::edx;
- static const GPRReg argumentGPR2 = X86Registers::r8; // regT6
- static const GPRReg argumentGPR3 = X86Registers::r9; // regT7
</del><ins>+ static const GPRReg argumentGPR0 = X86Registers::ecx; // regT5
+ static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
+ static const GPRReg argumentGPR2 = X86Registers::r8; // regT2
+ static const GPRReg argumentGPR3 = X86Registers::r9; // regT3
</ins><span class="cx"> #endif
</span><del>- static const GPRReg nonArgGPR0 = X86Registers::r10; // regT8
- static const GPRReg nonArgGPR1 = X86Registers::ebx; // regT3
- static const GPRReg nonArgGPR2 = X86Registers::r12; // regT9
</del><ins>+ static const GPRReg nonArgGPR0 = X86Registers::r10; // regT5 (regT4 on Windows)
+ static const GPRReg nonArgGPR1 = X86Registers::ebx; // Callee save
</ins><span class="cx"> static const GPRReg returnValueGPR = X86Registers::eax; // regT0
</span><del>- static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
- static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
- static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10;
</del><ins>+ static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1 or regT2
+ static const GPRReg nonPreservedNonReturnGPR = X86Registers::r10; // regT5 (regT4 on Windows)
+ static const GPRReg nonPreservedNonArgumentGPR = X86Registers::r10; // regT5 (regT4 on Windows)
</ins><span class="cx"> static const GPRReg patchpointScratchRegister = MacroAssembler::scratchRegister;
</span><span class="cx">
</span><span class="cx"> static GPRReg toRegister(unsigned index)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(index < numberOfRegisters);
</span><del>- static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8, regT9, regT10 };
</del><ins>+#if !OS(WINDOWS)
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regCS0, regCS1, regCS2 };
+#else
+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regCS0, regCS1, regCS2, regCS3, regCS4 };
+#endif
</ins><span class="cx"> return registerForIndex[index];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -443,7 +464,11 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(reg != InvalidGPRReg);
</span><span class="cx"> ASSERT(static_cast<int>(reg) < 16);
</span><del>- static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
</del><ins>+#if !OS(WINDOWS)
+ static const unsigned indexForRegister[16] = { 0, 3, 2, 8, InvalidIndex, InvalidIndex, 1, 6, 4, 7, 5, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
+#else
+ static const unsigned indexForRegister[16] = { 0, 5, 1, 6, InvalidIndex, InvalidIndex, 7, 8, 2, 3, 4, InvalidIndex, 9, 10, InvalidIndex, InvalidIndex };
+#endif
</ins><span class="cx"> return indexForRegister[reg];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -474,13 +499,11 @@
</span><span class="cx"> static const unsigned numberOfRegisters = 9;
</span><span class="cx"> static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
</span><span class="cx">
</span><del>- // Note: regT3 is required to be callee-preserved.
-
</del><span class="cx"> // Temporary registers.
</span><span class="cx"> static const GPRReg regT0 = ARMRegisters::r0;
</span><span class="cx"> static const GPRReg regT1 = ARMRegisters::r1;
</span><span class="cx"> static const GPRReg regT2 = ARMRegisters::r2;
</span><del>- static const GPRReg regT3 = ARMRegisters::r4;
</del><ins>+ static const GPRReg regT3 = ARMRegisters::r3;
</ins><span class="cx"> static const GPRReg regT4 = ARMRegisters::r8;
</span><span class="cx"> static const GPRReg regT5 = ARMRegisters::r9;
</span><span class="cx"> static const GPRReg regT6 = ARMRegisters::r10;
</span><span class="lines">@@ -489,22 +512,20 @@
</span><span class="cx"> #else
</span><span class="cx"> static const GPRReg regT7 = ARMRegisters::r7;
</span><span class="cx"> #endif
</span><del>- static const GPRReg regT8 = ARMRegisters::r3;
</del><ins>+ static const GPRReg regT8 = ARMRegisters::r4;
</ins><span class="cx"> // These registers match the baseline JIT.
</span><del>- static const GPRReg cachedResultRegister = regT0;
- static const GPRReg cachedResultRegister2 = regT1;
</del><span class="cx"> static const GPRReg callFrameRegister = ARMRegisters::fp;
</span><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><span class="cx"> static const GPRReg argumentGPR0 = ARMRegisters::r0; // regT0
</span><span class="cx"> static const GPRReg argumentGPR1 = ARMRegisters::r1; // regT1
</span><span class="cx"> static const GPRReg argumentGPR2 = ARMRegisters::r2; // regT2
</span><del>- static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT8
- static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT3
</del><ins>+ static const GPRReg argumentGPR3 = ARMRegisters::r3; // regT3
+ static const GPRReg nonArgGPR0 = ARMRegisters::r4; // regT8
</ins><span class="cx"> static const GPRReg nonArgGPR1 = ARMRegisters::r8; // regT4
</span><span class="cx"> static const GPRReg nonArgGPR2 = ARMRegisters::r9; // regT5
</span><span class="cx"> static const GPRReg returnValueGPR = ARMRegisters::r0; // regT0
</span><span class="cx"> static const GPRReg returnValueGPR2 = ARMRegisters::r1; // regT1
</span><del>- static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5; // regT7
</del><ins>+ static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r5;
</ins><span class="cx">
</span><span class="cx"> static GPRReg toRegister(unsigned index)
</span><span class="cx"> {
</span><span class="lines">@@ -526,9 +547,9 @@
</span><span class="cx"> ASSERT(static_cast<int>(reg) < 16);
</span><span class="cx"> static const unsigned indexForRegister[16] =
</span><span class="cx"> #if CPU(ARM_THUMB2)
</span><del>- { 0, 1, 2, 8, 3, 9, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
</del><ins>+ { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
</ins><span class="cx"> #else
</span><del>- { 0, 1, 2, 8, 3, 9, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
</del><ins>+ { 0, 1, 2, 3, 8, InvalidIndex, InvalidIndex, 7, 4, 5, 6, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
</ins><span class="cx"> #endif
</span><span class="cx"> unsigned result = indexForRegister[reg];
</span><span class="cx"> return result;
</span><span class="lines">@@ -561,11 +582,7 @@
</span><span class="cx"> static const unsigned numberOfRegisters = 16;
</span><span class="cx"> static const unsigned numberOfArgumentRegisters = 8;
</span><span class="cx">
</span><del>- // Note: regT3 is required to be callee-preserved.
-
</del><span class="cx"> // These registers match the baseline JIT.
</span><del>- static const GPRReg cachedResultRegister = ARM64Registers::x0;
- static const GPRReg timeoutCheckRegister = ARM64Registers::x26;
</del><span class="cx"> static const GPRReg callFrameRegister = ARM64Registers::fp;
</span><span class="cx"> static const GPRReg tagTypeNumberRegister = ARM64Registers::x27;
</span><span class="cx"> static const GPRReg tagMaskRegister = ARM64Registers::x28;
</span><span class="lines">@@ -573,9 +590,9 @@
</span><span class="cx"> static const GPRReg regT0 = ARM64Registers::x0;
</span><span class="cx"> static const GPRReg regT1 = ARM64Registers::x1;
</span><span class="cx"> static const GPRReg regT2 = ARM64Registers::x2;
</span><del>- static const GPRReg regT3 = ARM64Registers::x23;
- static const GPRReg regT4 = ARM64Registers::x5;
- static const GPRReg regT5 = ARM64Registers::x24;
</del><ins>+ static const GPRReg regT3 = ARM64Registers::x3;
+ static const GPRReg regT4 = ARM64Registers::x4;
+ static const GPRReg regT5 = ARM64Registers::x5;
</ins><span class="cx"> static const GPRReg regT6 = ARM64Registers::x6;
</span><span class="cx"> static const GPRReg regT7 = ARM64Registers::x7;
</span><span class="cx"> static const GPRReg regT8 = ARM64Registers::x8;
</span><span class="lines">@@ -586,18 +603,20 @@
</span><span class="cx"> static const GPRReg regT13 = ARM64Registers::x13;
</span><span class="cx"> static const GPRReg regT14 = ARM64Registers::x14;
</span><span class="cx"> static const GPRReg regT15 = ARM64Registers::x15;
</span><ins>+ static const GPRReg regCS0 = ARM64Registers::x26; // Used by LLInt only
+ static const GPRReg regCS1 = ARM64Registers::x27; // tagTypeNumber
+ static const GPRReg regCS2 = ARM64Registers::x28; // tagMask
</ins><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><span class="cx"> static const GPRReg argumentGPR0 = ARM64Registers::x0; // regT0
</span><span class="cx"> static const GPRReg argumentGPR1 = ARM64Registers::x1; // regT1
</span><span class="cx"> static const GPRReg argumentGPR2 = ARM64Registers::x2; // regT2
</span><del>- static const GPRReg argumentGPR3 = ARM64Registers::x3;
- static const GPRReg argumentGPR4 = ARM64Registers::x4;
- static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT4
</del><ins>+ static const GPRReg argumentGPR3 = ARM64Registers::x3; // regT3
+ static const GPRReg argumentGPR4 = ARM64Registers::x4; // regT4
+ static const GPRReg argumentGPR5 = ARM64Registers::x5; // regT5
</ins><span class="cx"> static const GPRReg argumentGPR6 = ARM64Registers::x6; // regT6
</span><span class="cx"> static const GPRReg argumentGPR7 = ARM64Registers::x7; // regT7
</span><span class="cx"> static const GPRReg nonArgGPR0 = ARM64Registers::x8; // regT8
</span><span class="cx"> static const GPRReg nonArgGPR1 = ARM64Registers::x9; // regT9
</span><del>- static const GPRReg nonArgGPR2 = ARM64Registers::x10; // regT10
</del><span class="cx"> static const GPRReg returnValueGPR = ARM64Registers::x0; // regT0
</span><span class="cx"> static const GPRReg returnValueGPR2 = ARM64Registers::x1; // regT1
</span><span class="cx"> static const GPRReg nonPreservedNonReturnGPR = ARM64Registers::x2;
</span><span class="lines">@@ -663,41 +682,38 @@
</span><span class="cx"> class GPRInfo {
</span><span class="cx"> public:
</span><span class="cx"> typedef GPRReg RegisterType;
</span><del>- static const unsigned numberOfRegisters = 7;
</del><ins>+ static const unsigned numberOfRegisters = 8;
</ins><span class="cx"> static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
</span><span class="cx">
</span><span class="cx"> // regT0 must be v0 for returning a 32-bit value.
</span><span class="cx"> // regT1 must be v1 for returning a pair of 32-bit value.
</span><del>- // regT3 must be saved in the callee, so use an S register.
</del><span class="cx">
</span><span class="cx"> // Temporary registers.
</span><span class="cx"> static const GPRReg regT0 = MIPSRegisters::v0;
</span><span class="cx"> static const GPRReg regT1 = MIPSRegisters::v1;
</span><del>- static const GPRReg regT2 = MIPSRegisters::t4;
- static const GPRReg regT3 = MIPSRegisters::s2;
- static const GPRReg regT4 = MIPSRegisters::t5;
- static const GPRReg regT5 = MIPSRegisters::t6;
- static const GPRReg regT6 = MIPSRegisters::s0;
</del><ins>+ static const GPRReg regT2 = MIPSRegisters::t2;
+ static const GPRReg regT3 = MIPSRegisters::t3;
+ static const GPRReg regT4 = MIPSRegisters::t4;
+ static const GPRReg regT5 = MIPSRegisters::t5;
+ static const GPRReg regT6 = MIPSRegisters::t0;
+ static const GPRReg regT7 = MIPSRegisters::t1;
</ins><span class="cx"> // These registers match the baseline JIT.
</span><del>- static const GPRReg cachedResultRegister = regT0;
- static const GPRReg cachedResultRegister2 = regT1;
</del><span class="cx"> static const GPRReg callFrameRegister = MIPSRegisters::fp;
</span><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><span class="cx"> static const GPRReg argumentGPR0 = MIPSRegisters::a0;
</span><span class="cx"> static const GPRReg argumentGPR1 = MIPSRegisters::a1;
</span><span class="cx"> static const GPRReg argumentGPR2 = MIPSRegisters::a2;
</span><span class="cx"> static const GPRReg argumentGPR3 = MIPSRegisters::a3;
</span><del>- static const GPRReg nonArgGPR0 = regT2;
- static const GPRReg nonArgGPR1 = regT3;
- static const GPRReg nonArgGPR2 = regT4;
</del><ins>+ static const GPRReg nonArgGPR0 = regT0;
+ static const GPRReg nonArgGPR1 = regT1;
</ins><span class="cx"> static const GPRReg returnValueGPR = regT0;
</span><span class="cx"> static const GPRReg returnValueGPR2 = regT1;
</span><del>- static const GPRReg nonPreservedNonReturnGPR = regT5;
</del><ins>+ static const GPRReg nonPreservedNonReturnGPR = regT2;
</ins><span class="cx">
</span><span class="cx"> static GPRReg toRegister(unsigned index)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(index < numberOfRegisters);
</span><del>- static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6 };
</del><ins>+ static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 };
</ins><span class="cx"> return registerForIndex[index];
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -707,8 +723,8 @@
</span><span class="cx"> ASSERT(reg < 24);
</span><span class="cx"> static const unsigned indexForRegister[24] = {
</span><span class="cx"> InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
</span><del>- InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 4, 5, InvalidIndex,
- 6, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
</del><ins>+ 6, 7, 2, 3, 4, 5, InvalidIndex, InvalidIndex,
+ InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex
</ins><span class="cx"> };
</span><span class="cx"> unsigned result = indexForRegister[reg];
</span><span class="cx"> return result;
</span><span class="lines">@@ -745,12 +761,12 @@
</span><span class="cx"> // Temporary registers.
</span><span class="cx"> static const GPRReg regT0 = SH4Registers::r0;
</span><span class="cx"> static const GPRReg regT1 = SH4Registers::r1;
</span><del>- static const GPRReg regT2 = SH4Registers::r2;
- static const GPRReg regT3 = SH4Registers::r10;
- static const GPRReg regT4 = SH4Registers::r4;
- static const GPRReg regT5 = SH4Registers::r5;
- static const GPRReg regT6 = SH4Registers::r6;
- static const GPRReg regT7 = SH4Registers::r7;
</del><ins>+ static const GPRReg regT2 = SH4Registers::r6;
+ static const GPRReg regT3 = SH4Registers::r7;
+ static const GPRReg regT4 = SH4Registers::r2;
+ static const GPRReg regT5 = SH4Registers::r3;
+ static const GPRReg regT6 = SH4Registers::r4;
+ static const GPRReg regT7 = SH4Registers::r5;
</ins><span class="cx"> static const GPRReg regT8 = SH4Registers::r8;
</span><span class="cx"> static const GPRReg regT9 = SH4Registers::r9;
</span><span class="cx"> // These registers match the baseline JIT.
</span><span class="lines">@@ -758,13 +774,12 @@
</span><span class="cx"> static const GPRReg cachedResultRegister2 = regT1;
</span><span class="cx"> static const GPRReg callFrameRegister = SH4Registers::fp;
</span><span class="cx"> // These constants provide the names for the general purpose argument & return value registers.
</span><del>- static const GPRReg argumentGPR0 = regT4;
- static const GPRReg argumentGPR1 = regT5;
- static const GPRReg argumentGPR2 = regT6;
- static const GPRReg argumentGPR3 = regT7;
- static const GPRReg nonArgGPR0 = regT3;
- static const GPRReg nonArgGPR1 = regT8;
- static const GPRReg nonArgGPR2 = regT9;
</del><ins>+ static const GPRReg argumentGPR0 = SH4Registers::r4; // regT6
+ static const GPRReg argumentGPR1 = SH4Registers::r5; // regT7
+ static const GPRReg argumentGPR2 = SH4Registers::r6; // regT2
+ static const GPRReg argumentGPR3 = SH4Registers::r7; // regT3
+ static const GPRReg nonArgGPR0 = regT4;
+ static const GPRReg nonArgGPR1 = regT5;
</ins><span class="cx"> static const GPRReg returnValueGPR = regT0;
</span><span class="cx"> static const GPRReg returnValueGPR2 = regT1;
</span><span class="cx"> static const GPRReg nonPreservedNonReturnGPR = regT2;
</span><span class="lines">@@ -780,7 +795,7 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(reg != InvalidGPRReg);
</span><span class="cx"> ASSERT(reg < 14);
</span><del>- static const unsigned indexForRegister[14] = { 0, 1, 2, InvalidIndex, 4, 5, 6, 7, 8, 9, 3, InvalidIndex, InvalidIndex, InvalidIndex };
</del><ins>+ static const unsigned indexForRegister[14] = { 0, 1, 4, 5, 6, 7, 2, 3, 8, 9, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
</ins><span class="cx"> unsigned result = indexForRegister[reg];
</span><span class="cx"> return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -572,19 +572,13 @@
</span><span class="cx"> callOperationWithCallFrameRollbackOnException(m_codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck);
</span><span class="cx"> if (maxFrameExtentForSlowPathCall)
</span><span class="cx"> addPtr(TrustedImm32(maxFrameExtentForSlowPathCall), stackPointerRegister);
</span><del>- if (returnValueGPR != regT0)
- move(returnValueGPR, regT0);
- branchTest32(Zero, regT0).linkTo(beginLabel, this);
- GPRReg thunkReg;
-#if USE(JSVALUE64)
- thunkReg = GPRInfo::regT7;
-#else
- thunkReg = GPRInfo::regT5;
-#endif
</del><ins>+ branchTest32(Zero, returnValueGPR).linkTo(beginLabel, this);
+ GPRReg thunkReg = GPRInfo::argumentGPR1;
</ins><span class="cx"> CodeLocationLabel* failThunkLabels =
</span><span class="cx"> m_vm->arityCheckFailReturnThunks->returnPCsFor(*m_vm, m_codeBlock->numParameters());
</span><span class="cx"> move(TrustedImmPtr(failThunkLabels), thunkReg);
</span><del>- loadPtr(BaseIndex(thunkReg, regT0, timesPtr()), thunkReg);
</del><ins>+ loadPtr(BaseIndex(thunkReg, returnValueGPR, timesPtr()), thunkReg);
+ move(returnValueGPR, GPRInfo::argumentGPR0);
</ins><span class="cx"> emitNakedCall(m_vm->getCTIStub(arityFixupGenerator).code());
</span><span class="cx">
</span><span class="cx"> #if !ASSERT_DISABLED
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmeticcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -611,25 +611,35 @@
</span><span class="cx"> int op2 = currentInstruction[3].u.operand;
</span><span class="cx">
</span><span class="cx"> // Make sure registers are correct for x86 IDIV instructions.
</span><ins>+#if CPU(X86)
+ auto edx = regT1;
+ auto ecx = regT2;
+#elif OS(WINDOWS)
+ auto edx = regT1;
+ auto ecx = regT5;
+#else
+ auto edx = regT2;
+ auto ecx = regT3;
+#endif
</ins><span class="cx"> ASSERT(regT0 == X86Registers::eax);
</span><del>- ASSERT(regT1 == X86Registers::edx);
- ASSERT(regT2 == X86Registers::ecx);
</del><ins>+ ASSERT(edx == X86Registers::edx);
+ ASSERT(ecx == X86Registers::ecx);
</ins><span class="cx">
</span><del>- emitGetVirtualRegisters(op1, regT3, op2, regT2);
- emitJumpSlowCaseIfNotImmediateInteger(regT3);
- emitJumpSlowCaseIfNotImmediateInteger(regT2);
</del><ins>+ emitGetVirtualRegisters(op1, regT4, op2, ecx);
+ emitJumpSlowCaseIfNotImmediateInteger(regT4);
+ emitJumpSlowCaseIfNotImmediateInteger(ecx);
</ins><span class="cx">
</span><del>- move(regT3, regT0);
- addSlowCase(branchTest32(Zero, regT2));
- Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1));
</del><ins>+ move(regT4, regT0);
+ addSlowCase(branchTest32(Zero, ecx));
+ Jump denominatorNotNeg1 = branch32(NotEqual, ecx, TrustedImm32(-1));
</ins><span class="cx"> addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1)));
</span><span class="cx"> denominatorNotNeg1.link(this);
</span><span class="cx"> m_assembler.cdq();
</span><del>- m_assembler.idivl_r(regT2);
- Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
- addSlowCase(branchTest32(Zero, regT1));
</del><ins>+ m_assembler.idivl_r(ecx);
+ Jump numeratorPositive = branch32(GreaterThanOrEqual, regT4, TrustedImm32(0));
+ addSlowCase(branchTest32(Zero, edx));
</ins><span class="cx"> numeratorPositive.link(this);
</span><del>- emitFastArithReTagImmediate(regT1, regT0);
</del><ins>+ emitFastArithReTagImmediate(edx, regT0);
</ins><span class="cx"> emitPutVirtualRegister(result);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -928,7 +928,7 @@
</span><span class="cx"> callOperation(operationOptimize, m_bytecodeOffset);
</span><span class="cx"> Jump noOptimizedEntry = branchTestPtr(Zero, returnValueGPR);
</span><span class="cx"> if (!ASSERT_DISABLED) {
</span><del>- Jump ok = branchPtr(MacroAssembler::Above, regT0, TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000))));
</del><ins>+ Jump ok = branchPtr(MacroAssembler::Above, returnValueGPR, TrustedImmPtr(bitwise_cast<void*>(static_cast<intptr_t>(1000))));
</ins><span class="cx"> abortWithReason(JITUnreasonableLoopHintJumpTarget);
</span><span class="cx"> ok.link(this);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -147,7 +147,7 @@
</span><span class="cx"> void JIT::emit_op_end(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(returnValueGPR != callFrameRegister);
</span><del>- emitLoad(currentInstruction[1].u.operand, regT1, regT0);
</del><ins>+ emitLoad(currentInstruction[1].u.operand, regT1, returnValueGPR);
</ins><span class="cx"> emitFunctionEpilogue();
</span><span class="cx"> ret();
</span><span class="cx"> }
</span><span class="lines">@@ -164,9 +164,9 @@
</span><span class="cx"> size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
</span><span class="cx"> MarkedAllocator* allocator = &m_vm->heap.allocatorForObjectWithoutDestructor(allocationSize);
</span><span class="cx">
</span><del>- RegisterID resultReg = regT0;
</del><ins>+ RegisterID resultReg = returnValueGPR;
</ins><span class="cx"> RegisterID allocatorReg = regT1;
</span><del>- RegisterID scratchReg = regT2;
</del><ins>+ RegisterID scratchReg = regT3;
</ins><span class="cx">
</span><span class="cx"> move(TrustedImmPtr(allocator), allocatorReg);
</span><span class="cx"> emitAllocateJSObject(allocatorReg, TrustedImmPtr(structure), resultReg, scratchReg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -65,6 +65,10 @@
</span><span class="cx"> // We shouldn't ever be generating wrappers for native functions.
</span><span class="cx"> RegisterSet toSave = registersToPreserve();
</span><span class="cx"> ptrdiff_t offset = registerPreservationOffset();
</span><ins>+
+ ASSERT(!toSave.get(GPRInfo::regT1));
+ ASSERT(!toSave.get(GPRInfo::regT2));
+ ASSERT(!toSave.get(GPRInfo::regT3));
</ins><span class="cx">
</span><span class="cx"> AssemblyHelpers jit(&vm, 0);
</span><span class="cx">
</span><span class="lines">@@ -84,31 +88,30 @@
</span><span class="cx"> JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize),
</span><span class="cx"> GPRInfo::regT2);
</span><span class="cx">
</span><del>- ASSERT(!toSave.get(GPRInfo::regT4));
- jit.move(AssemblyHelpers::stackPointerRegister, GPRInfo::regT4);
</del><ins>+ jit.move(AssemblyHelpers::stackPointerRegister, GPRInfo::regT3);
</ins><span class="cx">
</span><span class="cx"> AssemblyHelpers::Label loop = jit.label();
</span><span class="cx"> jit.sub32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
</span><del>- jit.load64(AssemblyHelpers::Address(GPRInfo::regT4, offset), GPRInfo::regT0);
- jit.store64(GPRInfo::regT0, GPRInfo::regT4);
- jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(Register)), GPRInfo::regT4);
</del><ins>+ jit.load64(AssemblyHelpers::Address(GPRInfo::regT3, offset), GPRInfo::regT0);
+ jit.store64(GPRInfo::regT0, GPRInfo::regT3);
+ jit.addPtr(AssemblyHelpers::TrustedImm32(sizeof(Register)), GPRInfo::regT3);
</ins><span class="cx"> jit.branchTest32(AssemblyHelpers::NonZero, GPRInfo::regT2).linkTo(loop, &jit);
</span><span class="cx">
</span><del>- // At this point regT4 + offset points to where we save things.
</del><ins>+ // At this point regT3 + offset points to where we save things.
</ins><span class="cx"> ptrdiff_t currentOffset = 0;
</span><del>- jit.storePtr(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
</del><ins>+ jit.storePtr(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
</ins><span class="cx">
</span><span class="cx"> for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr <= AssemblyHelpers::lastRegister(); gpr = static_cast<GPRReg>(gpr + 1)) {
</span><span class="cx"> if (!toSave.get(gpr))
</span><span class="cx"> continue;
</span><span class="cx"> currentOffset += sizeof(Register);
</span><del>- jit.store64(gpr, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
</del><ins>+ jit.store64(gpr, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
</ins><span class="cx"> }
</span><span class="cx"> for (FPRReg fpr = AssemblyHelpers::firstFPRegister(); fpr <= AssemblyHelpers::lastFPRegister(); fpr = static_cast<FPRReg>(fpr + 1)) {
</span><span class="cx"> if (!toSave.get(fpr))
</span><span class="cx"> continue;
</span><span class="cx"> currentOffset += sizeof(Register);
</span><del>- jit.storeDouble(fpr, AssemblyHelpers::Address(GPRInfo::regT4, currentOffset));
</del><ins>+ jit.storeDouble(fpr, AssemblyHelpers::Address(GPRInfo::regT3, currentOffset));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Assume that there aren't any saved FP registers.
</span><span class="lines">@@ -151,7 +154,9 @@
</span><span class="cx"> RegisterSet toSave = registersToPreserve();
</span><span class="cx"> ptrdiff_t offset = registerPreservationOffset();
</span><span class="cx">
</span><del>- ASSERT(!toSave.get(GPRInfo::regT4));
</del><ins>+ ASSERT(!toSave.get(GPRInfo::regT1));
+ ASSERT(!toSave.get(GPRInfo::regT2));
+ ASSERT(!toSave.get(GPRInfo::regT3));
</ins><span class="cx">
</span><span class="cx"> // We need to place the stack pointer back to where the caller thought they left it.
</span><span class="cx"> // But also, in order to recover the registers, we need to figure out how big the
</span><span class="lines">@@ -161,9 +166,9 @@
</span><span class="cx"> AssemblyHelpers::Address(
</span><span class="cx"> AssemblyHelpers::stackPointerRegister,
</span><span class="cx"> (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset),
</span><del>- GPRInfo::regT4);
</del><ins>+ GPRInfo::regT3);
</ins><span class="cx">
</span><del>- jit.move(GPRInfo::regT4, GPRInfo::regT2);
</del><ins>+ jit.move(GPRInfo::regT3, GPRInfo::regT2);
</ins><span class="cx"> jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
</span><span class="cx">
</span><span class="cx"> jit.addPtr(AssemblyHelpers::TrustedImm32(offset), AssemblyHelpers::stackPointerRegister);
</span><span class="lines">@@ -203,7 +208,7 @@
</span><span class="cx">
</span><span class="cx"> // Thunks like this rely on the ArgumentCount being intact. Pay it forward.
</span><span class="cx"> jit.store32(
</span><del>- GPRInfo::regT4,
</del><ins>+ GPRInfo::regT3,
</ins><span class="cx"> AssemblyHelpers::Address(
</span><span class="cx"> AssemblyHelpers::stackPointerRegister,
</span><span class="cx"> (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -255,8 +255,6 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> #elif CPU(ARM64)
</span><del>- COMPILE_ASSERT(ARM64Registers::x3 != JSInterfaceJIT::regT1, prev_callframe_not_trampled_by_T1);
- COMPILE_ASSERT(ARM64Registers::x3 != JSInterfaceJIT::regT3, prev_callframe_not_trampled_by_T3);
</del><span class="cx"> COMPILE_ASSERT(ARM64Registers::x0 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_0);
</span><span class="cx"> COMPILE_ASSERT(ARM64Registers::x1 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_1);
</span><span class="cx"> COMPILE_ASSERT(ARM64Registers::x2 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_2);
</span><span class="lines">@@ -355,46 +353,51 @@
</span><span class="cx"> {
</span><span class="cx"> JSInterfaceJIT jit(vm);
</span><span class="cx">
</span><del>- // We enter with fixup count, in aligned stack units, in regT0 and the return thunk in
- // regT5 on 32-bit and regT7 on 64-bit.
</del><ins>+ // We enter with fixup count, in aligned stack units, in argumentGPR0 and the return thunk in argumentGPR1
+ // We have the guarantee that a0, a1, a2, t3, t4 and t5 (or t0 for Windows) are all distinct :-)
</ins><span class="cx"> #if USE(JSVALUE64)
</span><ins>+#if OS(WINDOWS)
+ const GPRReg extraTemp = JSInterfaceJIT::regT0;
+#else
+ const GPRReg extraTemp = JSInterfaceJIT::regT5;
+#endif
</ins><span class="cx"> # if CPU(X86_64)
</span><span class="cx"> jit.pop(JSInterfaceJIT::regT4);
</span><span class="cx"> # endif
</span><del>- jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::regT0);
- jit.neg64(JSInterfaceJIT::regT0);
- jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT6);
- jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::regT2);
- jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2);
</del><ins>+ jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+ jit.neg64(JSInterfaceJIT::argumentGPR0);
+ jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
+ jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
+ jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
</ins><span class="cx">
</span><del>- // Move current frame down regT0 number of slots
</del><ins>+ // Move current frame down argumentGPR0 number of slots
</ins><span class="cx"> JSInterfaceJIT::Label copyLoop(jit.label());
</span><del>- jit.load64(JSInterfaceJIT::regT6, JSInterfaceJIT::regT1);
- jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
- jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT6);
- jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit);
</del><ins>+ jit.load64(JSInterfaceJIT::regT3, extraTemp);
+ jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+ jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
+ jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
</ins><span class="cx">
</span><del>- // Fill in regT0 - 1 missing arg slots with undefined
- jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2);
- jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), JSInterfaceJIT::regT1);
- jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2);
</del><ins>+ // Fill in argumentGPR0 - 1 missing arg slots with undefined
+ jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
+ jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
+ jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
</ins><span class="cx"> JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
</span><del>- jit.store64(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
- jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT6);
- jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit);
</del><ins>+ jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+ jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
+ jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &jit);
</ins><span class="cx">
</span><span class="cx"> // Adjust call frame register and stack pointer to account for missing args
</span><del>- jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1);
- jit.lshift64(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT1);
- jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister);
- jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::stackPointerRegister);
</del><ins>+ jit.move(JSInterfaceJIT::argumentGPR0, extraTemp);
+ jit.lshift64(JSInterfaceJIT::TrustedImm32(3), extraTemp);
+ jit.addPtr(extraTemp, JSInterfaceJIT::callFrameRegister);
+ jit.addPtr(extraTemp, JSInterfaceJIT::stackPointerRegister);
</ins><span class="cx">
</span><span class="cx"> // Save the original return PC.
</span><del>- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT1);
- jit.storePtr(GPRInfo::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT6, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
-
</del><ins>+ jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), extraTemp);
+ jit.storePtr(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+
</ins><span class="cx"> // Install the new return PC.
</span><del>- jit.storePtr(GPRInfo::regT7, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
</del><ins>+ jit.storePtr(GPRInfo::argumentGPR1, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
</ins><span class="cx">
</span><span class="cx"> # if CPU(X86_64)
</span><span class="cx"> jit.push(JSInterfaceJIT::regT4);
</span><span class="lines">@@ -404,45 +407,45 @@
</span><span class="cx"> # if CPU(X86)
</span><span class="cx"> jit.pop(JSInterfaceJIT::regT4);
</span><span class="cx"> # endif
</span><del>- jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::regT0);
- jit.neg32(JSInterfaceJIT::regT0);
</del><ins>+ jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+ jit.neg32(JSInterfaceJIT::argumentGPR0);
</ins><span class="cx"> jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
</span><del>- jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::regT2);
- jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::regT2);
</del><ins>+ jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
+ jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
</ins><span class="cx">
</span><del>- // Move current frame down regT0 number of slots
</del><ins>+ // Move current frame down argumentGPR0 number of slots
</ins><span class="cx"> JSInterfaceJIT::Label copyLoop(jit.label());
</span><del>- jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT1);
- jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
- jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT1);
- jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4));
</del><ins>+ jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT5);
+ jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+ jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT5);
+ jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
</ins><span class="cx"> jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><del>- jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(copyLoop, &jit);
</del><ins>+ jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
</ins><span class="cx">
</span><del>- // Fill in regT0 - 1 missing arg slots with undefined
- jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT2);
- jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2);
</del><ins>+ // Fill in argumentGPR0 - 1 missing arg slots with undefined
+ jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
+ jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
</ins><span class="cx"> JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
</span><del>- jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT1);
- jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
- jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT1);
- jit.store32(JSInterfaceJIT::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight, 4));
</del><ins>+ jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
+ jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+ jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
+ jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
</ins><span class="cx">
</span><span class="cx"> jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
</span><del>- jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::regT2).linkTo(fillUndefinedLoop, &jit);
</del><ins>+ jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &jit);
</ins><span class="cx">
</span><span class="cx"> // Adjust call frame register and stack pointer to account for missing args
</span><del>- jit.move(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1);
- jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT1);
- jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister);
- jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::stackPointerRegister);
</del><ins>+ jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::regT5);
+ jit.lshift32(JSInterfaceJIT::TrustedImm32(3), JSInterfaceJIT::regT5);
+ jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::callFrameRegister);
+ jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::stackPointerRegister);
</ins><span class="cx">
</span><span class="cx"> // Save the original return PC.
</span><del>- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT1);
- jit.storePtr(GPRInfo::regT1, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::regT0, JSInterfaceJIT::TimesEight));
</del><ins>+ jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()), GPRInfo::regT5);
+ jit.storePtr(GPRInfo::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
</ins><span class="cx">
</span><span class="cx"> // Install the new return PC.
</span><del>- jit.storePtr(GPRInfo::regT5, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
</del><ins>+ jit.storePtr(GPRInfo::argumentGPR1, JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, CallFrame::returnPCOffset()));
</ins><span class="cx">
</span><span class="cx"> # if CPU(X86)
</span><span class="cx"> jit.push(JSInterfaceJIT::regT4);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -21,6 +21,126 @@
</span><span class="cx"> # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
</span><span class="cx"> # THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">
</span><ins>+# Crash course on the language that this is written in (which I just call
+# "assembly" even though it's more than that):
+#
+# - Mostly gas-style operand ordering. The last operand tends to be the
+# destination. So "a := b" is written as "mov b, a". But unlike gas,
+# comparisons are in-order, so "if (a < b)" is written as
+# "bilt a, b, ...".
+#
+# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
+# For 32-bit, "i" and "p" are interchangeable except when an op supports one
+# but not the other.
+#
+# - In general, valid operands for macro invocations and instructions are
+# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
+# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
+# (eg "_foo" or ".foo"). Macro invocations can also take anonymous
+# macros as operands. Instructions cannot take anonymous macros.
+#
+# - Labels must have names that begin with either "_" or ".". A "." label
+# is local and gets renamed before code gen to minimize namespace
+# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
+# may or may not be removed during code gen depending on whether the asm
+# conventions for C name mangling on the target platform mandate a "_"
+# prefix.
+#
+# - A "macro" is a lambda expression, which may be either anonymous or
+# named. But this has caveats. "macro" can take zero or more arguments,
+# which may be macros or any valid operands, but it can only return
+# code. But you can do Turing-complete things via continuation passing
+# style: "macro foo (a, b) b(a, a) end foo(foo, foo)". Actually, don't do
+# that, since you'll just crash the assembler.
+#
+# - An "if" is a conditional on settings. Any identifier supplied in the
+# predicate of an "if" is assumed to be a #define that is available
+# during code gen. So you can't use "if" for computation in a macro, but
+# you can use it to select different pieces of code for different
+# platforms.
+#
+# - Arguments to macros follow lexical scoping rather than dynamic scoping.
+# Const's also follow lexical scoping and may override (hide) arguments
+# or other consts. All variables (arguments and constants) can be bound
+# to operands. Additionally, arguments (but not constants) can be bound
+# to macros.
+
+# The following general-purpose registers are available:
+#
+# - cfr and sp hold the call frame and (native) stack pointer respectively.
+# They are callee-save registers, and guaranteed to be distinct from all other
+# registers on all architectures.
+#
+# - lr is defined on non-X86 architectures (ARM64, ARMv7, ARM,
+# ARMv7_TRADITIONAL, MIPS, SH4 and CLOOP) and holds the return PC
+#
+# - pc holds the (native) program counter on 32-bits ARM architectures (ARM,
+# ARMv7, ARMv7_TRADITIONAL)
+#
+# - t0, t1, t2, t3, t4 and optionally t5 are temporary registers that can get trashed on
+# calls, and are pairwise distinct registers. t4 holds the JS program counter, so use
+# with caution in opcodes (actually, don't use it in opcodes at all, except as PC).
+#
+# - r0 and r1 are the platform's customary return registers, and thus are
+# two distinct registers
+#
+# - a0, a1, a2 and a3 are the platform's customary argument registers, and
+# thus are pairwise distinct registers. Be mindful that:
+# + On X86, there are no argument registers. a0 and a1 are edx and
+# ecx following the fastcall convention, but you should still use the stack
+# to pass your arguments. The cCall2 and cCall4 macros do this for you.
+# + On X86_64_WIN, you should allocate space on the stack for the arguments,
+# and the return convention is weird for > 8 bytes types. The only place we
+# use > 8 bytes return values is on a cCall, and cCall2 and cCall4 handle
+# this for you.
+#
+# - The only registers guaranteed to be caller-saved are r0, r1, a0, a1 and a2, and
+# you should be mindful of that in functions that are called directly from C.
+# If you need more registers, you should push and pop them like a good
+# assembly citizen, because any other register will be callee-saved on X86.
+#
+# You can additionally assume:
+#
+# - a3, t2, t3, t4 and t5 are never return registers; t0, t1, a0, a1 and a2
+# can be return registers.
+#
+# - t4 and t5 are never argument registers, t3 can only be a3, t1 can only be
+# a1; but t0 and t2 can be either a0 or a2.
+#
+# - On 64 bits, csr0, csr1, csr2 and optionally csr3, csr4, csr5 and csr6
+# are available as callee-save registers.
+# csr0 is used to store the PC base, while the last two csr registers are used
+# to store special tag values. Don't use them for anything else.
+#
+# Additional platform-specific details (you shouldn't rely on this remaining
+# true):
+#
+# - For consistency with the baseline JIT, t0 is always r0 (and t1 is always
+# r1 on 32 bits platforms). You should use the r version when you need return
+# registers, and the t version otherwise: code using t0 (or t1) should still
+# work if swapped with e.g. t3, while code using r0 (or r1) should not. There
+# *may* be legacy code relying on this.
+#
+# - On all platforms other than X86, t0 can only be a0 and t2 can only be a2.
+#
+# - On all platforms other than X86 and X86_64, a2 is not a return register.
+# a2 is r0 on X86 (because we have so few registers) and r1 on X86_64 (because
+# the ABI enforces it).
+#
+# The following floating-point registers are available:
+#
+# - ft0-ft5 are temporary floating-point registers that get trashed on calls,
+# and are pairwise distinct.
+#
+# - fa0 and fa1 are the platform's customary floating-point argument
+# registers, and are both distinct. On 64-bits platforms, fa2 and fa3 are
+# additional floating-point argument registers.
+#
+# - fr is the platform's customary floating-point return register
+#
+# You can assume that ft1-ft5 or fa1-fa3 are never fr, and that ftX is never
+# faY if X != Y.
+
</ins><span class="cx"> # First come the common protocols that both interpreters use. Note that each
</span><span class="cx"> # of these must have an ASSERT() in LLIntData.cpp
</span><span class="cx">
</span><span class="lines">@@ -107,16 +227,25 @@
</span><span class="cx"> if JSVALUE64
</span><span class="cx"> # - Use a pair of registers to represent the PC: one register for the
</span><span class="cx"> # base of the bytecodes, and one register for the index.
</span><del>- # - The PC base (or PB for short) should be stored in the csr. It will
- # get clobbered on calls to other JS code, but will get saved on calls
- # to C functions.
</del><ins>+ # - The PC base (or PB for short) must be stored in a callee-save register.
</ins><span class="cx"> # - C calls are still given the Instruction* rather than the PC index.
</span><span class="cx"> # This requires an add before the call, and a sub after.
</span><del>- const PC = t5
- const PB = t6
- const tagTypeNumber = csr1
- const tagMask = csr2
-
</del><ins>+ const PC = t4
+ const PB = csr0
+ if ARM64
+ const tagTypeNumber = csr1
+ const tagMask = csr2
+ elsif X86_64
+ const tagTypeNumber = csr3
+ const tagMask = csr4
+ elsif X86_64_WIN
+ const tagTypeNumber = csr5
+ const tagMask = csr6
+ elsif C_LOOP
+ const tagTypeNumber = csr1
+ const tagMask = csr2
+ end
+
</ins><span class="cx"> macro loadisFromInstruction(offset, dest)
</span><span class="cx"> loadis offset * 8[PB, PC, 8], dest
</span><span class="cx"> end
</span><span class="lines">@@ -130,7 +259,7 @@
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> else
</span><del>- const PC = t5
</del><ins>+ const PC = t4
</ins><span class="cx"> macro loadisFromInstruction(offset, dest)
</span><span class="cx"> loadis offset * 4[PC], dest
</span><span class="cx"> end
</span><span class="lines">@@ -140,6 +269,12 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+if X86_64_WIN
+ const extraTempReg = t0
+else
+ const extraTempReg = t5
+end
+
</ins><span class="cx"> # Constants for reasoning about value representation.
</span><span class="cx"> if BIG_ENDIAN
</span><span class="cx"> const TagOffset = 0
</span><span class="lines">@@ -465,12 +600,12 @@
</span><span class="cx">
</span><span class="cx"> macro restoreStackPointerAfterCall()
</span><span class="cx"> loadp CodeBlock[cfr], t2
</span><del>- getFrameRegisterSizeForCodeBlock(t2, t4)
</del><ins>+ getFrameRegisterSizeForCodeBlock(t2, t2)
</ins><span class="cx"> if ARMv7
</span><del>- subp cfr, t4, t4
- move t4, sp
</del><ins>+ subp cfr, t2, t2
+ move t2, sp
</ins><span class="cx"> else
</span><del>- subp cfr, t4, sp
</del><ins>+ subp cfr, t2, sp
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -494,13 +629,13 @@
</span><span class="cx"> macro slowPathForCall(slowPath)
</span><span class="cx"> callCallSlowPath(
</span><span class="cx"> slowPath,
</span><del>- macro (callee)
- btpz t1, .dontUpdateSP
</del><ins>+ macro (callee, calleeFrame)
+ btpz calleeFrame, .dontUpdateSP
</ins><span class="cx"> if ARMv7
</span><del>- addp CallerFrameAndPCSize, t1, t1
- move t1, sp
</del><ins>+ addp CallerFrameAndPCSize, calleeFrame, calleeFrame
+ move calleeFrame, sp
</ins><span class="cx"> else
</span><del>- addp CallerFrameAndPCSize, t1, sp
</del><ins>+ addp CallerFrameAndPCSize, calleeFrame, sp
</ins><span class="cx"> end
</span><span class="cx"> .dontUpdateSP:
</span><span class="cx"> if C_LOOP
</span><span class="lines">@@ -596,15 +731,19 @@
</span><span class="cx"> if not C_LOOP
</span><span class="cx"> baddis 5, CodeBlock::m_llintExecuteCounter + BaselineExecutionCounter::m_counter[t1], .continue
</span><span class="cx"> if JSVALUE64
</span><del>- cCall2(osrSlowPath, cfr, PC)
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(osrSlowPath)
</ins><span class="cx"> else
</span><span class="cx"> # We are after the function prologue, but before we have set up sp from the CodeBlock.
</span><span class="cx"> # Temporarily align stack pointer for this call.
</span><span class="cx"> subp 8, sp
</span><del>- cCall2(osrSlowPath, cfr, PC)
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(osrSlowPath)
</ins><span class="cx"> addp 8, sp
</span><span class="cx"> end
</span><del>- btpz t0, .recover
</del><ins>+ btpz r0, .recover
</ins><span class="cx"> move cfr, sp # restore the previous sp
</span><span class="cx"> # pop the callerFrame since we will jump to a function that wants to save it
</span><span class="cx"> if ARM64
</span><span class="lines">@@ -615,7 +754,7 @@
</span><span class="cx"> else
</span><span class="cx"> pop cfr
</span><span class="cx"> end
</span><del>- jmp t0
</del><ins>+ jmp r0
</ins><span class="cx"> .recover:
</span><span class="cx"> codeBlockGetter(t1)
</span><span class="cx"> .continue:
</span><span class="lines">@@ -640,8 +779,8 @@
</span><span class="cx"> # Stack height check failed - need to call a slow_path.
</span><span class="cx"> subp maxFrameExtentForSlowPathCall, sp # Set up temporary stack pointer for call
</span><span class="cx"> callSlowPath(_llint_stack_check)
</span><del>- bpeq t1, 0, .stackHeightOKGetCodeBlock
- move t1, cfr
</del><ins>+ bpeq r1, 0, .stackHeightOKGetCodeBlock
+ move r1, cfr
</ins><span class="cx"> dispatch(0) # Go to exception handler in PC
</span><span class="cx">
</span><span class="cx"> .stackHeightOKGetCodeBlock:
</span><span class="lines">@@ -738,27 +877,14 @@
</span><span class="cx"> # void sanitizeStackForVMImpl(VM* vm)
</span><span class="cx"> global _sanitizeStackForVMImpl
</span><span class="cx"> _sanitizeStackForVMImpl:
</span><del>- if X86_64
- const vm = t4
- const address = t1
- const zeroValue = t0
- elsif X86_64_WIN
- const vm = t2
- const address = t1
- const zeroValue = t0
- elsif X86 or X86_WIN
- const vm = t2
- const address = t1
- const zeroValue = t0
- else
- const vm = a0
- const address = t1
- const zeroValue = t2
- end
-
</del><ins>+ # We need three non-aliased caller-save registers. We are guaranteed
+ # this for a0, a1 and a2 on all architectures.
</ins><span class="cx"> if X86 or X86_WIN
</span><del>- loadp 4[sp], vm
</del><ins>+ loadp 4[sp], a0
</ins><span class="cx"> end
</span><ins>+ const vm = a0
+ const address = a1
+ const zeroValue = a2
</ins><span class="cx">
</span><span class="cx"> loadp VM::m_lastStackTop[vm], address
</span><span class="cx"> bpbeq sp, address, .zeroFillDone
</span><span class="lines">@@ -777,22 +903,11 @@
</span><span class="cx"> # VMEntryRecord* vmEntryRecord(const VMEntryFrame* entryFrame)
</span><span class="cx"> global _vmEntryRecord
</span><span class="cx"> _vmEntryRecord:
</span><del>- if X86_64
- const entryFrame = t4
- const result = t0
- elsif X86 or X86_WIN or X86_64_WIN
- const entryFrame = t2
- const result = t0
- else
- const entryFrame = a0
- const result = t0
- end
-
</del><span class="cx"> if X86 or X86_WIN
</span><del>- loadp 4[sp], entryFrame
</del><ins>+ loadp 4[sp], a0
</ins><span class="cx"> end
</span><del>-
- vmEntryRecord(entryFrame, result)
</del><ins>+
+ vmEntryRecord(a0, r0)
</ins><span class="cx"> ret
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -800,17 +915,12 @@
</span><span class="cx"> # Dummy entry point the C Loop uses to initialize.
</span><span class="cx"> _llint_entry:
</span><span class="cx"> crash()
</span><del>- else
</del><ins>+else
</ins><span class="cx"> macro initPCRelative(pcBase)
</span><del>- if X86_64 or X86_64_WIN
</del><ins>+ if X86_64 or X86_64_WIN or X86 or X86_WIN
</ins><span class="cx"> call _relativePCBase
</span><span class="cx"> _relativePCBase:
</span><span class="cx"> pop pcBase
</span><del>- elsif X86 or X86_WIN
- call _relativePCBase
- _relativePCBase:
- pop pcBase
- loadp 20[sp], t4
</del><span class="cx"> elsif ARM64
</span><span class="cx"> elsif ARMv7
</span><span class="cx"> _relativePCBase:
</span><span class="lines">@@ -831,41 +941,39 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+# The PC base is in t1, as this is what _llint_entry leaves behind through
+# initPCRelative(t1)
</ins><span class="cx"> macro setEntryAddress(index, label)
</span><del>- if X86_64
- leap (label - _relativePCBase)[t1], t0
- move index, t2
- storep t0, [t4, t2, 8]
- elsif X86_64_WIN
- leap (label - _relativePCBase)[t1], t0
</del><ins>+ if X86_64 or X86_64_WIN
+ leap (label - _relativePCBase)[t1], t3
</ins><span class="cx"> move index, t4
</span><del>- storep t0, [t2, t4, 8]
</del><ins>+ storep t3, [a0, t4, 8]
</ins><span class="cx"> elsif X86 or X86_WIN
</span><del>- leap (label - _relativePCBase)[t1], t0
- move index, t2
- storep t0, [t4, t2, 4]
</del><ins>+ leap (label - _relativePCBase)[t1], t3
+ move index, t4
+ storep t3, [a0, t4, 4]
</ins><span class="cx"> elsif ARM64
</span><span class="cx"> pcrtoaddr label, t1
</span><del>- move index, t2
- storep t1, [a0, t2, 8]
</del><ins>+ move index, t4
+ storep t1, [a0, t4, 8]
</ins><span class="cx"> elsif ARM or ARMv7 or ARMv7_TRADITIONAL
</span><del>- mvlbl (label - _relativePCBase), t2
- addp t2, t1, t2
</del><ins>+ mvlbl (label - _relativePCBase), t4
+ addp t4, t1, t4
</ins><span class="cx"> move index, t3
</span><del>- storep t2, [a0, t3, 4]
</del><ins>+ storep t4, [a0, t3, 4]
</ins><span class="cx"> elsif SH4
</span><del>- move (label - _relativePCBase), t2
- addp t2, t1, t2
</del><ins>+ move (label - _relativePCBase), t4
+ addp t4, t1, t4
</ins><span class="cx"> move index, t3
</span><del>- storep t2, [a0, t3, 4]
</del><ins>+ storep t4, [a0, t3, 4]
</ins><span class="cx"> flushcp # Force constant pool flush to avoid "pcrel too far" link error.
</span><span class="cx"> elsif MIPS
</span><del>- la label, t2
</del><ins>+ la label, t4
</ins><span class="cx"> la _relativePCBase, t3
</span><del>- subp t3, t2
- addp t2, t1, t2
</del><ins>+ subp t3, t4
+ addp t4, t1, t4
</ins><span class="cx"> move index, t3
</span><del>- storep t2, [a0, t3, 4]
</del><ins>+ storep t4, [a0, t3, 4]
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -874,6 +982,9 @@
</span><span class="cx"> _llint_entry:
</span><span class="cx"> functionPrologue()
</span><span class="cx"> pushCalleeSaves()
</span><ins>+ if X86 or X86_WIN
+ loadp 20[sp], a0
+ end
</ins><span class="cx"> initPCRelative(t1)
</span><span class="cx">
</span><span class="cx"> # Include generated bytecode initialization file.
</span><span class="lines">@@ -1213,16 +1324,16 @@
</span><span class="cx"> traceExecution()
</span><span class="cx"> callSlowPath(_llint_slow_path_size_frame_for_varargs)
</span><span class="cx"> branchIfException(_llint_throw_from_slow_path_trampoline)
</span><del>- # calleeFrame in t1
</del><ins>+ # calleeFrame in r1
</ins><span class="cx"> if JSVALUE64
</span><del>- move t1, sp
</del><ins>+ move r1, sp
</ins><span class="cx"> else
</span><span class="cx"> # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
</span><span class="cx"> if ARMv7
</span><del>- subp t1, CallerFrameAndPCSize, t2
</del><ins>+ subp r1, CallerFrameAndPCSize, t2
</ins><span class="cx"> move t2, sp
</span><span class="cx"> else
</span><del>- subp t1, CallerFrameAndPCSize, sp
</del><ins>+ subp r1, CallerFrameAndPCSize, sp
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx"> slowPathForCall(_llint_slow_path_call_varargs)
</span><span class="lines">@@ -1231,16 +1342,16 @@
</span><span class="cx"> traceExecution()
</span><span class="cx"> callSlowPath(_llint_slow_path_size_frame_for_varargs)
</span><span class="cx"> branchIfException(_llint_throw_from_slow_path_trampoline)
</span><del>- # calleeFrame in t1
</del><ins>+ # calleeFrame in r1
</ins><span class="cx"> if JSVALUE64
</span><del>- move t1, sp
</del><ins>+ move r1, sp
</ins><span class="cx"> else
</span><span class="cx"> # The calleeFrame is not stack aligned, move down by CallerFrameAndPCSize to align
</span><span class="cx"> if ARMv7
</span><del>- subp t1, CallerFrameAndPCSize, t2
</del><ins>+ subp r1, CallerFrameAndPCSize, t2
</ins><span class="cx"> move t2, sp
</span><span class="cx"> else
</span><del>- subp t1, CallerFrameAndPCSize, sp
</del><ins>+ subp r1, CallerFrameAndPCSize, sp
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx"> slowPathForCall(_llint_slow_path_construct_varargs)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -22,54 +22,6 @@
</span><span class="cx"> # THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">
</span><span class="cx">
</span><del>-# Crash course on the language that this is written in (which I just call
-# "assembly" even though it's more than that):
-#
-# - Mostly gas-style operand ordering. The last operand tends to be the
-# destination. So "a := b" is written as "mov b, a". But unlike gas,
-# comparisons are in-order, so "if (a < b)" is written as
-# "bilt a, b, ...".
-#
-# - "b" = byte, "h" = 16-bit word, "i" = 32-bit word, "p" = pointer.
-# Currently this is just 32-bit so "i" and "p" are interchangeable
-# except when an op supports one but not the other.
-#
-# - In general, valid operands for macro invocations and instructions are
-# registers (eg "t0"), addresses (eg "4[t0]"), base-index addresses
-# (eg "7[t0, t1, 2]"), absolute addresses (eg "0xa0000000[]"), or labels
-# (eg "_foo" or ".foo"). Macro invocations can also take anonymous
-# macros as operands. Instructions cannot take anonymous macros.
-#
-# - Labels must have names that begin with either "_" or ".". A "." label
-# is local and gets renamed before code gen to minimize namespace
-# pollution. A "_" label is an extern symbol (i.e. ".globl"). The "_"
-# may or may not be removed during code gen depending on whether the asm
-# conventions for C name mangling on the target platform mandate a "_"
-# prefix.
-#
-# - A "macro" is a lambda expression, which may be either anonymous or
-# named. But this has caveats. "macro" can take zero or more arguments,
-# which may be macros or any valid operands, but it can only return
-# code. But you can do Turing-complete things via continuation passing
-# style: "macro foo (a, b) b(a) end foo(foo, foo)". Actually, don't do
-# that, since you'll just crash the assembler.
-#
-# - An "if" is a conditional on settings. Any identifier supplied in the
-# predicate of an "if" is assumed to be a #define that is available
-# during code gen. So you can't use "if" for computation in a macro, but
-# you can use it to select different pieces of code for different
-# platforms.
-#
-# - Arguments to macros follow lexical scoping rather than dynamic scoping.
-# Const's also follow lexical scoping and may override (hide) arguments
-# or other consts. All variables (arguments and constants) can be bound
-# to operands. Additionally, arguments (but not constants) can be bound
-# to macros.
-
-
-# Below we have a bunch of constant declarations. Each constant must have
-# a corresponding ASSERT() in LLIntData.cpp.
-
</del><span class="cx"> # Utilities
</span><span class="cx"> macro dispatch(advance)
</span><span class="cx"> addp advance * 4, PC
</span><span class="lines">@@ -89,60 +41,47 @@
</span><span class="cx">
</span><span class="cx"> macro dispatchAfterCall()
</span><span class="cx"> loadi ArgumentCount + TagOffset[cfr], PC
</span><del>- loadi 4[PC], t2
- storei t1, TagOffset[cfr, t2, 8]
- storei t0, PayloadOffset[cfr, t2, 8]
- valueProfile(t1, t0, 4 * (CallOpCodeSize - 1), t3)
</del><ins>+ loadi 4[PC], t3
+ storei r1, TagOffset[cfr, t3, 8]
+ storei r0, PayloadOffset[cfr, t3, 8]
+ valueProfile(r1, r0, 4 * (CallOpCodeSize - 1), t3)
</ins><span class="cx"> dispatch(CallOpCodeSize)
</span><span class="cx"> end
</span><span class="cx">
</span><del>-macro cCall2(function, arg1, arg2)
- if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
- move arg1, a0
- move arg2, a1
</del><ins>+macro cCall2(function)
+ if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
</ins><span class="cx"> call function
</span><span class="cx"> elsif X86 or X86_WIN
</span><span class="cx"> subp 8, sp
</span><del>- push arg2
- push arg1
</del><ins>+ push a1
+ push a0
</ins><span class="cx"> call function
</span><span class="cx"> addp 16, sp
</span><del>- elsif SH4
- setargs arg1, arg2
- call function
</del><span class="cx"> elsif C_LOOP
</span><del>- cloopCallSlowPath function, arg1, arg2
</del><ins>+ cloopCallSlowPath function, a0, a1
</ins><span class="cx"> else
</span><span class="cx"> error
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-macro cCall2Void(function, arg1, arg2)
</del><ins>+macro cCall2Void(function)
</ins><span class="cx"> if C_LOOP
</span><del>- cloopCallSlowPathVoid function, arg1, arg2
</del><ins>+ cloopCallSlowPathVoid function, a0, a1
</ins><span class="cx"> else
</span><del>- cCall2(function, arg1, arg2)
</del><ins>+ cCall2(function)
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-# This barely works. arg3 and arg4 should probably be immediates.
-macro cCall4(function, arg1, arg2, arg3, arg4)
- if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS
- move arg1, a0
- move arg2, a1
- move arg3, a2
- move arg4, a3
</del><ins>+macro cCall4(function)
+ if ARM or ARMv7 or ARMv7_TRADITIONAL or MIPS or SH4
</ins><span class="cx"> call function
</span><span class="cx"> elsif X86 or X86_WIN
</span><del>- push arg4
- push arg3
- push arg2
- push arg1
</del><ins>+ push a3
+ push a2
+ push a1
+ push a0
</ins><span class="cx"> call function
</span><span class="cx"> addp 16, sp
</span><del>- elsif SH4
- setargs arg1, arg2, arg3, arg4
- call function
</del><span class="cx"> elsif C_LOOP
</span><span class="cx"> error
</span><span class="cx"> else
</span><span class="lines">@@ -151,133 +90,105 @@
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro callSlowPath(slowPath)
</span><del>- cCall2(slowPath, cfr, PC)
- move t0, PC
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath)
+ move r0, PC
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro doVMEntry(makeCall)
</span><del>- if X86 or X86_WIN
- const entry = t4
- const vm = t3
- const protoCallFrame = t5
-
- const temp1 = t0
- const temp2 = t1
- const temp3 = t2
- const temp4 = t3 # same as vm
- elsif ARM or ARMv7 or ARMv7_TRADITIONAL or C_LOOP
- const entry = a0
- const vm = a1
- const protoCallFrame = a2
-
- const temp1 = t3
- const temp2 = t4
- const temp3 = t5
- const temp4 = t4 # Same as temp2
- elsif MIPS
- const entry = a0
- const vm = a1
- const protoCallFrame = a2
-
- const temp1 = t3
- const temp2 = t5
- const temp3 = t4
- const temp4 = t6
- elsif SH4
- const entry = a0
- const vm = a1
- const protoCallFrame = a2
-
- const temp1 = t3
- const temp2 = a3
- const temp3 = t8
- const temp4 = t9
- end
-
</del><span class="cx"> functionPrologue()
</span><span class="cx"> pushCalleeSaves()
</span><span class="cx">
</span><ins>+ # x86 needs to load arguments from the stack
</ins><span class="cx"> if X86 or X86_WIN
</span><del>- loadp 12[cfr], vm
- loadp 8[cfr], entry
</del><ins>+ loadp 16[cfr], a2
+ loadp 12[cfr], a1
+ loadp 8[cfr], a0
</ins><span class="cx"> end
</span><span class="cx">
</span><ins>+ const entry = a0
+ const vm = a1
+ const protoCallFrame = a2
+
+ # We are using t3, t4 and t5 as temporaries through the function.
+ # Since we have the guarantee that tX != aY when X != Y, we are safe from
+ # aliasing problems with our arguments.
+
</ins><span class="cx"> if ARMv7
</span><del>- vmEntryRecord(cfr, temp1)
- move temp1, sp
</del><ins>+ vmEntryRecord(cfr, t3)
+ move t3, sp
</ins><span class="cx"> else
</span><span class="cx"> vmEntryRecord(cfr, sp)
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> storep vm, VMEntryRecord::m_vm[sp]
</span><del>- loadp VM::topCallFrame[vm], temp2
- storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
- loadp VM::topVMEntryFrame[vm], temp2
- storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
</del><ins>+ loadp VM::topCallFrame[vm], t4
+ storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
+ loadp VM::topVMEntryFrame[vm], t4
+ storep t4, VMEntryRecord::m_prevTopVMEntryFrame[sp]
</ins><span class="cx">
</span><span class="cx"> # Align stack pointer
</span><span class="cx"> if X86_WIN
</span><del>- addp CallFrameAlignSlots * SlotSize, sp, temp1
- andp ~StackAlignmentMask, temp1
- subp temp1, CallFrameAlignSlots * SlotSize, sp
</del><ins>+ addp CallFrameAlignSlots * SlotSize, sp, t3
+ andp ~StackAlignmentMask, t3
+ subp t3, CallFrameAlignSlots * SlotSize, sp
</ins><span class="cx"> elsif ARM or ARMv7 or ARMv7_TRADITIONAL
</span><del>- addp CallFrameAlignSlots * SlotSize, sp, temp1
- clrbp temp1, StackAlignmentMask, temp1
</del><ins>+ addp CallFrameAlignSlots * SlotSize, sp, t3
+ clrbp t3, StackAlignmentMask, t3
</ins><span class="cx"> if ARMv7
</span><del>- subp temp1, CallFrameAlignSlots * SlotSize, temp1
- move temp1, sp
</del><ins>+ subp t3, CallFrameAlignSlots * SlotSize, t3
+ move t3, sp
</ins><span class="cx"> else
</span><del>- subp temp1, CallFrameAlignSlots * SlotSize, sp
</del><ins>+ subp t3, CallFrameAlignSlots * SlotSize, sp
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>- if X86 or X86_WIN
- loadp 16[cfr], protoCallFrame
- end
</del><ins>+ loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
+ addp CallFrameHeaderSlots, t4, t4
+ lshiftp 3, t4
+ subp sp, t4, t3
</ins><span class="cx">
</span><del>- loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
- addp CallFrameHeaderSlots, temp2, temp2
- lshiftp 3, temp2
- subp sp, temp2, temp1
-
</del><span class="cx"> # Ensure that we have enough additional stack capacity for the incoming args,
</span><span class="cx"> # and the frame for the JS code we're executing. We need to do this check
</span><span class="cx"> # before we start copying the args from the protoCallFrame below.
</span><del>- bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
</del><ins>+ bpaeq t3, VM::m_jsStackLimit[vm], .stackHeightOK
</ins><span class="cx">
</span><span class="cx"> if C_LOOP
</span><del>- move entry, temp2
- move vm, temp3
- cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
</del><ins>+ move entry, t4
+ move vm, t5
+ cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
</ins><span class="cx"> bpeq t0, 0, .stackCheckFailed
</span><del>- move temp2, entry
- move temp3, vm
</del><ins>+ move t4, entry
+ move t5, vm
</ins><span class="cx"> jmp .stackHeightOK
</span><span class="cx">
</span><span class="cx"> .stackCheckFailed:
</span><del>- move temp2, entry
- move temp3, vm
</del><ins>+ move t4, entry
+ move t5, vm
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> subp 8, sp # Align stack for cCall2() to make a call.
</span><del>- cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
</del><ins>+ move vm, a0
+ move protoCallFrame, a1
+ cCall2(_llint_throw_stack_overflow_error)
</ins><span class="cx">
</span><span class="cx"> if ARMv7
</span><del>- vmEntryRecord(cfr, temp1)
- move temp1, sp
</del><ins>+ vmEntryRecord(cfr, t3)
+ move t3, sp
</ins><span class="cx"> else
</span><span class="cx"> vmEntryRecord(cfr, sp)
</span><span class="cx"> end
</span><span class="cx">
</span><del>- loadp VMEntryRecord::m_vm[sp], temp3
- loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
- storep temp4, VM::topCallFrame[temp3]
- loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
- storep temp4, VM::topVMEntryFrame[temp3]
</del><ins>+ loadp VMEntryRecord::m_vm[sp], t5
+ loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
+ storep t4, VM::topCallFrame[t5]
+ loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], t4
+ storep t4, VM::topVMEntryFrame[t5]
</ins><span class="cx">
</span><span class="cx"> if ARMv7
</span><del>- subp cfr, CalleeRegisterSaveSize, temp3
- move temp3, sp
</del><ins>+ subp cfr, CalleeRegisterSaveSize, t5
+ move t5, sp
</ins><span class="cx"> else
</span><span class="cx"> subp cfr, CalleeRegisterSaveSize, sp
</span><span class="cx"> end
</span><span class="lines">@@ -287,63 +198,63 @@
</span><span class="cx"> ret
</span><span class="cx">
</span><span class="cx"> .stackHeightOK:
</span><del>- move temp1, sp
- move 4, temp1
</del><ins>+ move t3, sp
+ move 4, t3
</ins><span class="cx">
</span><span class="cx"> .copyHeaderLoop:
</span><del>- subi 1, temp1
- loadi TagOffset[protoCallFrame, temp1, 8], temp3
- storei temp3, TagOffset + CodeBlock[sp, temp1, 8]
- loadi PayloadOffset[protoCallFrame, temp1, 8], temp3
- storei temp3, PayloadOffset + CodeBlock[sp, temp1, 8]
- btinz temp1, .copyHeaderLoop
</del><ins>+ subi 1, t3
+ loadi TagOffset[protoCallFrame, t3, 8], t5
+ storei t5, TagOffset + CodeBlock[sp, t3, 8]
+ loadi PayloadOffset[protoCallFrame, t3, 8], t5
+ storei t5, PayloadOffset + CodeBlock[sp, t3, 8]
+ btinz t3, .copyHeaderLoop
</ins><span class="cx">
</span><del>- loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
- subi 1, temp2
- loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
- subi 1, temp3
</del><ins>+ loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
+ subi 1, t4
+ loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t5
+ subi 1, t5
</ins><span class="cx">
</span><del>- bieq temp2, temp3, .copyArgs
</del><ins>+ bieq t4, t5, .copyArgs
</ins><span class="cx"> .fillExtraArgsLoop:
</span><del>- subi 1, temp3
- storei UndefinedTag, ThisArgumentOffset + 8 + TagOffset[sp, temp3, 8]
- storei 0, ThisArgumentOffset + 8 + PayloadOffset[sp, temp3, 8]
- bineq temp2, temp3, .fillExtraArgsLoop
</del><ins>+ subi 1, t5
+ storei UndefinedTag, ThisArgumentOffset + 8 + TagOffset[sp, t5, 8]
+ storei 0, ThisArgumentOffset + 8 + PayloadOffset[sp, t5, 8]
+ bineq t4, t5, .fillExtraArgsLoop
</ins><span class="cx">
</span><span class="cx"> .copyArgs:
</span><del>- loadp ProtoCallFrame::args[protoCallFrame], temp1
</del><ins>+ loadp ProtoCallFrame::args[protoCallFrame], t3
</ins><span class="cx">
</span><span class="cx"> .copyArgsLoop:
</span><del>- btiz temp2, .copyArgsDone
- subi 1, temp2
- loadi TagOffset[temp1, temp2, 8], temp3
- storei temp3, ThisArgumentOffset + 8 + TagOffset[sp, temp2, 8]
- loadi PayloadOffset[temp1, temp2, 8], temp3
- storei temp3, ThisArgumentOffset + 8 + PayloadOffset[sp, temp2, 8]
</del><ins>+ btiz t4, .copyArgsDone
+ subi 1, t4
+ loadi TagOffset[t3, t4, 8], t5
+ storei t5, ThisArgumentOffset + 8 + TagOffset[sp, t4, 8]
+ loadi PayloadOffset[t3, t4, 8], t5
+ storei t5, ThisArgumentOffset + 8 + PayloadOffset[sp, t4, 8]
</ins><span class="cx"> jmp .copyArgsLoop
</span><span class="cx">
</span><span class="cx"> .copyArgsDone:
</span><span class="cx"> storep sp, VM::topCallFrame[vm]
</span><span class="cx"> storep cfr, VM::topVMEntryFrame[vm]
</span><span class="cx">
</span><del>- makeCall(entry, temp1, temp2)
</del><ins>+ makeCall(entry, t3, t4)
</ins><span class="cx">
</span><span class="cx"> if ARMv7
</span><del>- vmEntryRecord(cfr, temp1)
- move temp1, sp
</del><ins>+ vmEntryRecord(cfr, t3)
+ move t3, sp
</ins><span class="cx"> else
</span><span class="cx"> vmEntryRecord(cfr, sp)
</span><span class="cx"> end
</span><span class="cx">
</span><del>- loadp VMEntryRecord::m_vm[sp], temp3
- loadp VMEntryRecord::m_prevTopCallFrame[sp], temp4
- storep temp4, VM::topCallFrame[temp3]
- loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], temp4
- storep temp4, VM::topVMEntryFrame[temp3]
</del><ins>+ loadp VMEntryRecord::m_vm[sp], t5
+ loadp VMEntryRecord::m_prevTopCallFrame[sp], t4
+ storep t4, VM::topCallFrame[t5]
+ loadp VMEntryRecord::m_prevTopVMEntryFrame[sp], t4
+ storep t4, VM::topVMEntryFrame[t5]
</ins><span class="cx">
</span><span class="cx"> if ARMv7
</span><del>- subp cfr, CalleeRegisterSaveSize, temp3
- move temp3, sp
</del><ins>+ subp cfr, CalleeRegisterSaveSize, t5
+ move t5, sp
</ins><span class="cx"> else
</span><span class="cx"> subp cfr, CalleeRegisterSaveSize, sp
</span><span class="cx"> end
</span><span class="lines">@@ -355,13 +266,13 @@
</span><span class="cx">
</span><span class="cx"> macro makeJavaScriptCall(entry, temp, unused)
</span><span class="cx"> addp CallerFrameAndPCSize, sp
</span><del>- checkStackPointerAlignment(t2, 0xbad0dc02)
</del><ins>+ checkStackPointerAlignment(temp, 0xbad0dc02)
</ins><span class="cx"> if C_LOOP
</span><span class="cx"> cloopCallJSFunction entry
</span><span class="cx"> else
</span><span class="cx"> call entry
</span><span class="cx"> end
</span><del>- checkStackPointerAlignment(t2, 0xbad0dc03)
</del><ins>+ checkStackPointerAlignment(temp, 0xbad0dc03)
</ins><span class="cx"> subp CallerFrameAndPCSize, sp
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -376,9 +287,9 @@
</span><span class="cx"> # Put callee frame pointer on stack as arg0, also put it in ecx for "fastcall" targets
</span><span class="cx"> move 0, temp2
</span><span class="cx"> move temp2, 4[sp] # put 0 in ReturnPC
</span><del>- move sp, t2 # t2 is ecx
</del><ins>+ move sp, a0 # a0 is ecx
</ins><span class="cx"> push temp2 # Push dummy arg1
</span><del>- push t2
</del><ins>+ push a0
</ins><span class="cx"> call temp1
</span><span class="cx"> addp 8, sp
</span><span class="cx"> else
</span><span class="lines">@@ -429,31 +340,43 @@
</span><span class="cx"> # debugging from. operand should likewise be an immediate, and should identify the operand
</span><span class="cx"> # in the instruction stream you'd like to print out.
</span><span class="cx"> macro traceOperand(fromWhere, operand)
</span><del>- cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
- move t0, PC
- move t1, cfr
</del><ins>+ move fromWhere, a2
+ move operand, a3
+ move cfr, a0
+ move PC, a1
+ cCall4(_llint_trace_operand)
+ move r0, PC
+ move r1, cfr
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> # Debugging operation if you'd like to print the value of an operand in the instruction
</span><span class="cx"> # stream. Same as traceOperand(), but assumes that the operand is a register, and prints its
</span><span class="cx"> # value.
</span><span class="cx"> macro traceValue(fromWhere, operand)
</span><del>- cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
- move t0, PC
- move t1, cfr
</del><ins>+ move fromWhere, a2
+ move operand, a3
+ move cfr, a0
+ move PC, a1
+ cCall4(_llint_trace_value)
+ move r0, PC
+ move r1, cfr
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> # Call a slowPath for call opcodes.
</span><span class="cx"> macro callCallSlowPath(slowPath, action)
</span><span class="cx"> storep PC, ArgumentCount + TagOffset[cfr]
</span><del>- cCall2(slowPath, cfr, PC)
- action(t0)
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath)
+ action(r0, r1)
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro callWatchdogTimerHandler(throwHandler)
</span><span class="cx"> storei PC, ArgumentCount + TagOffset[cfr]
</span><del>- cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
- btpnz t0, throwHandler
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(_llint_slow_path_handle_watchdog_timer)
+ btpnz r0, throwHandler
</ins><span class="cx"> loadi ArgumentCount + TagOffset[cfr], PC
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -462,10 +385,12 @@
</span><span class="cx"> 1,
</span><span class="cx"> macro ()
</span><span class="cx"> storei PC, ArgumentCount + TagOffset[cfr]
</span><del>- cCall2(_llint_loop_osr, cfr, PC)
- btpz t0, .recover
- move t1, sp
- jmp t0
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(_llint_loop_osr)
+ btpz r0, .recover
+ move r1, sp
+ jmp r0
</ins><span class="cx"> .recover:
</span><span class="cx"> loadi ArgumentCount + TagOffset[cfr], PC
</span><span class="cx"> end)
</span><span class="lines">@@ -576,7 +501,9 @@
</span><span class="cx"> push cfr, PC
</span><span class="cx"> # We make two extra slots because cCall2 will poke.
</span><span class="cx"> subp 8, sp
</span><del>- cCall2Void(_llint_write_barrier_slow, cfr, t2)
</del><ins>+ move t2, a1 # t2 can be a0 on x86
+ move cfr, a0
+ cCall2Void(_llint_write_barrier_slow)
</ins><span class="cx"> addp 8, sp
</span><span class="cx"> pop PC, cfr
</span><span class="cx"> end
</span><span class="lines">@@ -610,7 +537,9 @@
</span><span class="cx"> push cfr, PC
</span><span class="cx"> # We make two extra slots because cCall2 will poke.
</span><span class="cx"> subp 8, sp
</span><del>- cCall2Void(_llint_write_barrier_slow, cfr, t3)
</del><ins>+ move cfr, a0
+ move t3, a1
+ cCall2Void(_llint_write_barrier_slow)
</ins><span class="cx"> addp 8, sp
</span><span class="cx"> pop PC, cfr
</span><span class="cx"> end
</span><span class="lines">@@ -649,19 +578,21 @@
</span><span class="cx"> macro functionArityCheck(doneLabel, slowPath)
</span><span class="cx"> loadi PayloadOffset + ArgumentCount[cfr], t0
</span><span class="cx"> biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
</span><del>- cCall2(slowPath, cfr, PC) # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error
- btiz t0, .noError
- move t1, cfr # t1 contains caller frame
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath) # This slowPath has a simple protocol: t0 = 0 => no error, t0 != 0 => error
+ btiz r0, .noError
+ move r1, cfr # r1 contains caller frame
</ins><span class="cx"> jmp _llint_throw_from_slow_path_trampoline
</span><span class="cx">
</span><span class="cx"> .noError:
</span><del>- # t1 points to ArityCheckData.
- loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
- btpz t2, .proceedInline
</del><ins>+ # r1 points to ArityCheckData.
+ loadp CommonSlowPaths::ArityCheckData::thunkToCall[r1], t3
+ btpz t3, .proceedInline
</ins><span class="cx">
</span><del>- loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t5
- loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
- call t2
</del><ins>+ loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], a0
+ loadp CommonSlowPaths::ArityCheckData::returnPC[r1], a1
+ call t3
</ins><span class="cx"> if ASSERT_ENABLED
</span><span class="cx"> loadp ReturnPC[cfr], t0
</span><span class="cx"> loadp [t0], t0
</span><span class="lines">@@ -669,7 +600,7 @@
</span><span class="cx"> jmp .continue
</span><span class="cx">
</span><span class="cx"> .proceedInline:
</span><del>- loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
</del><ins>+ loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
</ins><span class="cx"> btiz t1, .continue
</span><span class="cx">
</span><span class="cx"> // Move frame up "t1 * 2" slots
</span><span class="lines">@@ -751,14 +682,14 @@
</span><span class="cx"> traceExecution()
</span><span class="cx"> loadi 8[PC], t0
</span><span class="cx"> loadp PayloadOffset[cfr, t0, 8], t0
</span><del>- loadp JSFunction::m_rareData[t0], t4
- btpz t4, .opCreateThisSlow
- loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
- loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
</del><ins>+ loadp JSFunction::m_rareData[t0], t5
+ btpz t5, .opCreateThisSlow
+ loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t5], t1
+ loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t5], t2
</ins><span class="cx"> btpz t1, .opCreateThisSlow
</span><del>- loadpFromInstruction(4, t4)
- bpeq t4, 1, .hasSeenMultipleCallee
- bpneq t4, t0, .opCreateThisSlow
</del><ins>+ loadpFromInstruction(4, t5)
+ bpeq t5, 1, .hasSeenMultipleCallee
+ bpneq t5, t0, .opCreateThisSlow
</ins><span class="cx"> .hasSeenMultipleCallee:
</span><span class="cx"> allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
</span><span class="cx"> loadi 4[PC], t1
</span><span class="lines">@@ -2006,8 +1937,8 @@
</span><span class="cx"> andp MarkedBlockMask, t1
</span><span class="cx"> loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t3
</span><span class="cx"> storep cfr, VM::topCallFrame[t3]
</span><del>- move cfr, t2 # t2 = ecx
- storep t2, [sp]
</del><ins>+ move cfr, a0 # a0 = ecx
+ storep a0, [sp]
</ins><span class="cx"> loadi Callee + PayloadOffset[cfr], t1
</span><span class="cx"> loadp JSFunction::m_executable[t1], t1
</span><span class="cx"> checkStackPointerAlignment(t3, 0xdead0001)
</span><span class="lines">@@ -2022,11 +1953,7 @@
</span><span class="cx"> andp MarkedBlockMask, t1
</span><span class="cx"> loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
</span><span class="cx"> storep cfr, VM::topCallFrame[t1]
</span><del>- if MIPS or SH4
- move cfr, a0
- else
- move cfr, t0
- end
</del><ins>+ move cfr, a0
</ins><span class="cx"> loadi Callee + PayloadOffset[cfr], t1
</span><span class="cx"> loadp JSFunction::m_executable[t1], t1
</span><span class="cx"> checkStackPointerAlignment(t3, 0xdead0001)
</span><span class="lines">@@ -2269,9 +2196,9 @@
</span><span class="cx"> macro putLocalClosureVar()
</span><span class="cx"> loadisFromInstruction(3, t1)
</span><span class="cx"> loadConstantOrVariable(t1, t2, t3)
</span><del>- loadpFromInstruction(5, t4)
- btpz t4, .noVariableWatchpointSet
- notifyWrite(t4, .pDynamic)
</del><ins>+ loadpFromInstruction(5, t5)
+ btpz t5, .noVariableWatchpointSet
+ notifyWrite(t5, .pDynamic)
</ins><span class="cx"> .noVariableWatchpointSet:
</span><span class="cx"> loadisFromInstruction(6, t1)
</span><span class="cx"> storei t2, JSEnvironmentRecord_variables + TagOffset[t0, t1, 8]
</span><span class="lines">@@ -2396,9 +2323,9 @@
</span><span class="cx"> # t1 is holding the pointer to the typeProfilerLog.
</span><span class="cx"> loadp VM::m_typeProfilerLog[t1], t1
</span><span class="cx">
</span><del>- # t0 is holding the payload, t4 is holding the tag.
</del><ins>+ # t0 is holding the payload, t5 is holding the tag.
</ins><span class="cx"> loadisFromInstruction(1, t2)
</span><del>- loadConstantOrVariable(t2, t4, t0)
</del><ins>+ loadConstantOrVariable(t2, t5, t0)
</ins><span class="cx">
</span><span class="cx"> bieq t4, EmptyValueTag, .opProfileTypeDone
</span><span class="cx">
</span><span class="lines">@@ -2406,14 +2333,14 @@
</span><span class="cx"> loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
</span><span class="cx">
</span><span class="cx"> # Store the JSValue onto the log entry.
</span><del>- storei t4, TypeProfilerLog::LogEntry::value + TagOffset[t2]
</del><ins>+ storei t5, TypeProfilerLog::LogEntry::value + TagOffset[t2]
</ins><span class="cx"> storei t0, TypeProfilerLog::LogEntry::value + PayloadOffset[t2]
</span><span class="cx">
</span><span class="cx"> # Store the TypeLocation onto the log entry.
</span><span class="cx"> loadpFromInstruction(2, t3)
</span><span class="cx"> storep t3, TypeProfilerLog::LogEntry::location[t2]
</span><span class="cx">
</span><del>- bieq t4, CellTag, .opProfileTypeIsCell
</del><ins>+ bieq t5, CellTag, .opProfileTypeIsCell
</ins><span class="cx"> storei 0, TypeProfilerLog::LogEntry::structureID[t2]
</span><span class="cx"> jmp .opProfileTypeSkipIsCell
</span><span class="cx"> .opProfileTypeIsCell:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -46,177 +46,127 @@
</span><span class="cx"> loadp CodeBlock[cfr], PB
</span><span class="cx"> loadp CodeBlock::m_instructions[PB], PB
</span><span class="cx"> loadisFromInstruction(1, t1)
</span><del>- storeq t0, [cfr, t1, 8]
- valueProfile(t0, (CallOpCodeSize - 1), t2)
</del><ins>+ storeq r0, [cfr, t1, 8]
+ valueProfile(r0, (CallOpCodeSize - 1), t3)
</ins><span class="cx"> dispatch(CallOpCodeSize)
</span><span class="cx"> end
</span><span class="cx">
</span><del>-macro cCall2(function, arg1, arg2)
</del><ins>+macro cCall2(function)
</ins><span class="cx"> checkStackPointerAlignment(t4, 0xbad0c002)
</span><del>- if X86_64
- move arg1, t4
- move arg2, t5
</del><ins>+ if X86_64 or ARM64
</ins><span class="cx"> call function
</span><span class="cx"> elsif X86_64_WIN
</span><span class="cx"> # Note: this implementation is only correct if the return type size is > 8 bytes.
</span><span class="cx"> # See macro cCall2Void for an implementation when the return type <= 8 bytes.
</span><span class="cx"> # On Win64, when the return type is larger than 8 bytes, we need to allocate space on the stack for the return value.
</span><del>- # On entry rcx (t2), should contain a pointer to this stack space. The other parameters are shifted to the right,
- # rdx (t1) should contain the first argument, and r8 (t6) should contain the second argument.
- # 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)
</del><ins>+ # On entry rcx (a0), should contain a pointer to this stack space. The other parameters are shifted to the right,
+ # rdx (a1) should contain the first argument, and r8 (a2) should contain the second argument.
+ # 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)
</ins><span class="cx"> # since the return value is expected to be split between the two.
</span><span class="cx"> # See http://msdn.microsoft.com/en-us/library/7572ztz4.aspx
</span><del>- move arg1, t1
- move arg2, t6
</del><ins>+ move a1, a2
+ move a0, a1
</ins><span class="cx"> subp 48, sp
</span><del>- move sp, t2
- addp 32, t2
</del><ins>+ move sp, a0
+ addp 32, a0
</ins><span class="cx"> call function
</span><span class="cx"> addp 48, sp
</span><del>- move 8[t0], t1
- move [t0], t0
- elsif ARM64
- move arg1, t0
- move arg2, t1
- call function
</del><ins>+ move 8[r0], r1
+ move [r0], r0
</ins><span class="cx"> elsif C_LOOP
</span><del>- cloopCallSlowPath function, arg1, arg2
</del><ins>+ cloopCallSlowPath function, a0, a1
</ins><span class="cx"> else
</span><span class="cx"> error
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-macro cCall2Void(function, arg1, arg2)
</del><ins>+macro cCall2Void(function)
</ins><span class="cx"> if C_LOOP
</span><del>- cloopCallSlowPathVoid function, arg1, arg2
</del><ins>+ cloopCallSlowPathVoid function, a0, a1
</ins><span class="cx"> elsif X86_64_WIN
</span><span class="cx"> # Note: we cannot use the cCall2 macro for Win64 in this case,
</span><span class="cx"> # as the Win64 cCall2 implemenation is only correct when the return type size is > 8 bytes.
</span><span class="cx"> # On Win64, rcx and rdx are used for passing the first two parameters.
</span><span class="cx"> # We also need to make room on the stack for all four parameter registers.
</span><span class="cx"> # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
</span><del>- move arg2, t1
- move arg1, t2
</del><span class="cx"> subp 32, sp
</span><span class="cx"> call function
</span><span class="cx"> addp 32, sp
</span><span class="cx"> else
</span><del>- cCall2(function, arg1, arg2)
</del><ins>+ cCall2(function)
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> # This barely works. arg3 and arg4 should probably be immediates.
</span><del>-macro cCall4(function, arg1, arg2, arg3, arg4)
</del><ins>+macro cCall4(function)
</ins><span class="cx"> checkStackPointerAlignment(t4, 0xbad0c004)
</span><del>- if X86_64
- move arg1, t4
- move arg2, t5
- move arg3, t1
- move arg4, t2
</del><ins>+ if X86_64 or ARM64
</ins><span class="cx"> call function
</span><span class="cx"> elsif X86_64_WIN
</span><span class="cx"> # On Win64, rcx, rdx, r8, and r9 are used for passing the first four parameters.
</span><span class="cx"> # We also need to make room on the stack for all four parameter registers.
</span><span class="cx"> # See http://msdn.microsoft.com/en-us/library/ms235286.aspx
</span><del>- move arg1, t2
- move arg2, t1
- move arg3, t6
- move arg4, t7
- subp 32, sp
</del><ins>+ subp 64, sp
</ins><span class="cx"> call function
</span><del>- addp 32, sp
- elsif ARM64
- move arg1, t0
- move arg2, t1
- move arg3, t2
- move arg4, t3
- call function
- elsif C_LOOP
- error
</del><ins>+ addp 64, sp
</ins><span class="cx"> else
</span><span class="cx"> error
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro doVMEntry(makeCall)
</span><del>- if X86_64
- const entry = t4
- const vm = t5
- const protoCallFrame = t1
-
- const previousCFR = t0
- const previousPC = t6
- const temp1 = t0
- const temp2 = t3
- const temp3 = t6
- elsif X86_64_WIN
- const entry = t2
- const vm = t1
- const protoCallFrame = t6
-
- const previousCFR = t0
- const previousPC = t4
- const temp1 = t0
- const temp2 = t3
- const temp3 = t7
- elsif ARM64 or C_LOOP
- const entry = a0
- const vm = a1
- const protoCallFrame = a2
-
- const previousCFR = t5
- const previousPC = lr
- const temp1 = t3
- const temp2 = t4
- const temp3 = t6
- end
-
</del><span class="cx"> functionPrologue()
</span><span class="cx"> pushCalleeSaves()
</span><span class="cx">
</span><ins>+ const entry = a0
+ const vm = a1
+ const protoCallFrame = a2
+
</ins><span class="cx"> vmEntryRecord(cfr, sp)
</span><span class="cx">
</span><del>- checkStackPointerAlignment(temp2, 0xbad0dc01)
</del><ins>+ checkStackPointerAlignment(t4, 0xbad0dc01)
</ins><span class="cx">
</span><span class="cx"> storep vm, VMEntryRecord::m_vm[sp]
</span><del>- loadp VM::topCallFrame[vm], temp2
- storep temp2, VMEntryRecord::m_prevTopCallFrame[sp]
- loadp VM::topVMEntryFrame[vm], temp2
- storep temp2, VMEntryRecord::m_prevTopVMEntryFrame[sp]
</del><ins>+ loadp VM::topCallFrame[vm], t4
+ storep t4, VMEntryRecord::m_prevTopCallFrame[sp]
+ loadp VM::topVMEntryFrame[vm], t4
+ storep t4, VMEntryRecord::m_prevTopVMEntryFrame[sp]
</ins><span class="cx">
</span><del>- loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp2
- addp CallFrameHeaderSlots, temp2, temp2
- lshiftp 3, temp2
- subp sp, temp2, temp1
</del><ins>+ loadi ProtoCallFrame::paddedArgCount[protoCallFrame], t4
+ addp CallFrameHeaderSlots, t4, t4
+ lshiftp 3, t4
+ subp sp, t4, t3
</ins><span class="cx">
</span><span class="cx"> # Ensure that we have enough additional stack capacity for the incoming args,
</span><span class="cx"> # and the frame for the JS code we're executing. We need to do this check
</span><span class="cx"> # before we start copying the args from the protoCallFrame below.
</span><del>- bpaeq temp1, VM::m_jsStackLimit[vm], .stackHeightOK
</del><ins>+ bpaeq t3, VM::m_jsStackLimit[vm], .stackHeightOK
</ins><span class="cx">
</span><span class="cx"> if C_LOOP
</span><del>- move entry, temp2
- move vm, temp3
- cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, temp1
</del><ins>+ move entry, t4
+ move vm, t5
+ cloopCallSlowPath _llint_stack_check_at_vm_entry, vm, t3
</ins><span class="cx"> bpeq t0, 0, .stackCheckFailed
</span><del>- move temp2, entry
- move temp3, vm
</del><ins>+ move t4, entry
+ move t5, vm
</ins><span class="cx"> jmp .stackHeightOK
</span><span class="cx">
</span><span class="cx"> .stackCheckFailed:
</span><del>- move temp2, entry
- move temp3, vm
</del><ins>+ move t4, entry
+ move t5, vm
</ins><span class="cx"> end
</span><span class="cx">
</span><del>- cCall2(_llint_throw_stack_overflow_error, vm, protoCallFrame)
</del><ins>+ move vm, a0
+ move protoCallFrame, a1
+ cCall2(_llint_throw_stack_overflow_error)
</ins><span class="cx">
</span><del>- vmEntryRecord(cfr, temp2)
</del><ins>+ vmEntryRecord(cfr, t4)
</ins><span class="cx">
</span><del>- loadp VMEntryRecord::m_vm[temp2], vm
- loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
- storep temp3, VM::topCallFrame[vm]
- loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
- storep temp3, VM::topVMEntryFrame[vm]
</del><ins>+ loadp VMEntryRecord::m_vm[t4], vm
+ loadp VMEntryRecord::m_prevTopCallFrame[t4], extraTempReg
+ storep extraTempReg, VM::topCallFrame[vm]
+ loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], extraTempReg
+ storep extraTempReg, VM::topVMEntryFrame[vm]
</ins><span class="cx">
</span><span class="cx"> subp cfr, CalleeRegisterSaveSize, sp
</span><span class="cx">
</span><span class="lines">@@ -225,62 +175,65 @@
</span><span class="cx"> ret
</span><span class="cx">
</span><span class="cx"> .stackHeightOK:
</span><del>- move temp1, sp
- move 4, temp1
</del><ins>+ move t3, sp
+ move 4, t3
</ins><span class="cx">
</span><span class="cx"> .copyHeaderLoop:
</span><del>- subi 1, temp1
- loadq [protoCallFrame, temp1, 8], temp3
- storeq temp3, CodeBlock[sp, temp1, 8]
- btinz temp1, .copyHeaderLoop
</del><ins>+ subi 1, t3
+ loadq [protoCallFrame, t3, 8], extraTempReg
+ storeq extraTempReg, CodeBlock[sp, t3, 8]
+ btinz t3, .copyHeaderLoop
</ins><span class="cx">
</span><del>- loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], temp2
- subi 1, temp2
- loadi ProtoCallFrame::paddedArgCount[protoCallFrame], temp3
- subi 1, temp3
</del><ins>+ loadi PayloadOffset + ProtoCallFrame::argCountAndCodeOriginValue[protoCallFrame], t4
+ subi 1, t4
+ loadi ProtoCallFrame::paddedArgCount[protoCallFrame], extraTempReg
+ subi 1, extraTempReg
</ins><span class="cx">
</span><del>- bieq temp2, temp3, .copyArgs
- move ValueUndefined, temp1
</del><ins>+ bieq t4, extraTempReg, .copyArgs
+ move ValueUndefined, t3
</ins><span class="cx"> .fillExtraArgsLoop:
</span><del>- subi 1, temp3
- storeq temp1, ThisArgumentOffset + 8[sp, temp3, 8]
- bineq temp2, temp3, .fillExtraArgsLoop
</del><ins>+ subi 1, extraTempReg
+ storeq t3, ThisArgumentOffset + 8[sp, extraTempReg, 8]
+ bineq t4, extraTempReg, .fillExtraArgsLoop
</ins><span class="cx">
</span><span class="cx"> .copyArgs:
</span><del>- loadp ProtoCallFrame::args[protoCallFrame], temp1
</del><ins>+ loadp ProtoCallFrame::args[protoCallFrame], t3
</ins><span class="cx">
</span><span class="cx"> .copyArgsLoop:
</span><del>- btiz temp2, .copyArgsDone
- subi 1, temp2
- loadq [temp1, temp2, 8], temp3
- storeq temp3, ThisArgumentOffset + 8[sp, temp2, 8]
</del><ins>+ btiz t4, .copyArgsDone
+ subi 1, t4
+ loadq [t3, t4, 8], extraTempReg
+ storeq extraTempReg, ThisArgumentOffset + 8[sp, t4, 8]
</ins><span class="cx"> jmp .copyArgsLoop
</span><span class="cx">
</span><span class="cx"> .copyArgsDone:
</span><span class="cx"> if ARM64
</span><del>- move sp, temp2
- storep temp2, VM::topCallFrame[vm]
</del><ins>+ move sp, t4
+ storep t4, VM::topCallFrame[vm]
</ins><span class="cx"> else
</span><span class="cx"> storep sp, VM::topCallFrame[vm]
</span><span class="cx"> end
</span><span class="cx"> storep cfr, VM::topVMEntryFrame[vm]
</span><span class="cx">
</span><del>- move 0xffff000000000000, csr1
- addp 2, csr1, csr2
</del><ins>+ move TagTypeNumber, tagTypeNumber
+ addp TagBitTypeOther, tagTypeNumber, tagMask
</ins><span class="cx">
</span><del>- checkStackPointerAlignment(temp3, 0xbad0dc02)
</del><ins>+ checkStackPointerAlignment(extraTempReg, 0xbad0dc02)
</ins><span class="cx">
</span><del>- makeCall(entry, temp1)
</del><ins>+ makeCall(entry, t3)
</ins><span class="cx">
</span><del>- checkStackPointerAlignment(temp3, 0xbad0dc03)
</del><ins>+ # We may have just made a call into a JS function, so we can't rely on sp
+ # for anything but the fact that our own locals (ie the VMEntryRecord) are
+ # not below it. It also still has to be aligned, though.
+ checkStackPointerAlignment(t2, 0xbad0dc03)
</ins><span class="cx">
</span><del>- vmEntryRecord(cfr, temp2)
</del><ins>+ vmEntryRecord(cfr, t4)
</ins><span class="cx">
</span><del>- loadp VMEntryRecord::m_vm[temp2], vm
- loadp VMEntryRecord::m_prevTopCallFrame[temp2], temp3
- storep temp3, VM::topCallFrame[vm]
- loadp VMEntryRecord::m_prevTopVMEntryFrame[temp2], temp3
- storep temp3, VM::topVMEntryFrame[vm]
</del><ins>+ loadp VMEntryRecord::m_vm[t4], vm
+ loadp VMEntryRecord::m_prevTopCallFrame[t4], t2
+ storep t2, VM::topCallFrame[vm]
+ loadp VMEntryRecord::m_prevTopVMEntryFrame[t4], t2
+ storep t2, VM::topVMEntryFrame[vm]
</ins><span class="cx">
</span><span class="cx"> subp cfr, CalleeRegisterSaveSize, sp
</span><span class="cx">
</span><span class="lines">@@ -305,13 +258,7 @@
</span><span class="cx"> macro makeHostFunctionCall(entry, temp)
</span><span class="cx"> move entry, temp
</span><span class="cx"> storep cfr, [sp]
</span><del>- if X86_64
- move sp, t4
- elsif X86_64_WIN
- move sp, t2
- elsif ARM64 or C_LOOP
- move sp, a0
- end
</del><ins>+ move sp, a0
</ins><span class="cx"> if C_LOOP
</span><span class="cx"> storep lr, 8[sp]
</span><span class="cx"> cloopCallNative temp
</span><span class="lines">@@ -336,10 +283,10 @@
</span><span class="cx"> vmEntryRecord(cfr, t2)
</span><span class="cx">
</span><span class="cx"> loadp VMEntryRecord::m_vm[t2], t3
</span><del>- loadp VMEntryRecord::m_prevTopCallFrame[t2], t5
- storep t5, VM::topCallFrame[t3]
- loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], t5
- storep t5, VM::topVMEntryFrame[t3]
</del><ins>+ loadp VMEntryRecord::m_prevTopCallFrame[t2], extraTempReg
+ storep extraTempReg, VM::topCallFrame[t3]
+ loadp VMEntryRecord::m_prevTopVMEntryFrame[t2], extraTempReg
+ storep extraTempReg, VM::topVMEntryFrame[t3]
</ins><span class="cx">
</span><span class="cx"> subp cfr, CalleeRegisterSaveSize, sp
</span><span class="cx">
</span><span class="lines">@@ -350,31 +297,39 @@
</span><span class="cx">
</span><span class="cx"> macro prepareStateForCCall()
</span><span class="cx"> leap [PB, PC, 8], PC
</span><del>- move PB, t3
</del><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro restoreStateAfterCCall()
</span><del>- move t0, PC
- move t3, PB
</del><ins>+ move r0, PC
</ins><span class="cx"> subp PB, PC
</span><span class="cx"> rshiftp 3, PC
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro callSlowPath(slowPath)
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall2(slowPath, cfr, PC)
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath)
</ins><span class="cx"> restoreStateAfterCCall()
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro traceOperand(fromWhere, operand)
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall4(_llint_trace_operand, cfr, PC, fromWhere, operand)
</del><ins>+ move fromWhere, a2
+ move operand, a3
+ move cfr, a0
+ move PC, a1
+ cCall4(_llint_trace_operand)
</ins><span class="cx"> restoreStateAfterCCall()
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro traceValue(fromWhere, operand)
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall4(_llint_trace_value, cfr, PC, fromWhere, operand)
</del><ins>+ move fromWhere, a2
+ move operand, a3
+ move cfr, a0
+ move PC, a1
+ cCall4(_llint_trace_value)
</ins><span class="cx"> restoreStateAfterCCall()
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -382,16 +337,19 @@
</span><span class="cx"> macro callCallSlowPath(slowPath, action)
</span><span class="cx"> storei PC, ArgumentCount + TagOffset[cfr]
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall2(slowPath, cfr, PC)
- action(t0)
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath)
+ action(r0, r1)
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> macro callWatchdogTimerHandler(throwHandler)
</span><span class="cx"> storei PC, ArgumentCount + TagOffset[cfr]
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall2(_llint_slow_path_handle_watchdog_timer, cfr, PC)
- btpnz t0, throwHandler
- move t3, PB
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(_llint_slow_path_handle_watchdog_timer)
+ btpnz r0, throwHandler
</ins><span class="cx"> loadi ArgumentCount + TagOffset[cfr], PC
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -401,12 +359,13 @@
</span><span class="cx"> macro()
</span><span class="cx"> storei PC, ArgumentCount + TagOffset[cfr]
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall2(_llint_loop_osr, cfr, PC)
- btpz t0, .recover
- move t1, sp
- jmp t0
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(_llint_loop_osr)
+ btpz r0, .recover
+ move r1, sp
+ jmp r0
</ins><span class="cx"> .recover:
</span><del>- move t3, PB
</del><span class="cx"> loadi ArgumentCount + TagOffset[cfr], PC
</span><span class="cx"> end)
</span><span class="cx"> end
</span><span class="lines">@@ -447,7 +406,9 @@
</span><span class="cx"> macro(gcData)
</span><span class="cx"> btbnz gcData, .writeBarrierDone
</span><span class="cx"> push PB, PC
</span><del>- cCall2Void(_llint_write_barrier_slow, cfr, t2)
</del><ins>+ move t2, a1 # t2 can be a0 (not on 64 bits, but better safe than sorry)
+ move cfr, a0
+ cCall2Void(_llint_write_barrier_slow)
</ins><span class="cx"> pop PC, PB
</span><span class="cx"> end
</span><span class="cx"> )
</span><span class="lines">@@ -477,7 +438,9 @@
</span><span class="cx"> macro(gcData)
</span><span class="cx"> btbnz gcData, .writeBarrierDone
</span><span class="cx"> push PB, PC
</span><del>- cCall2Void(_llint_write_barrier_slow, cfr, t3)
</del><ins>+ move cfr, a0
+ move t3, a1
+ cCall2Void(_llint_write_barrier_slow)
</ins><span class="cx"> pop PC, PB
</span><span class="cx"> end
</span><span class="cx"> )
</span><span class="lines">@@ -538,19 +501,21 @@
</span><span class="cx"> loadi PayloadOffset + ArgumentCount[cfr], t0
</span><span class="cx"> biaeq t0, CodeBlock::m_numParameters[t1], doneLabel
</span><span class="cx"> prepareStateForCCall()
</span><del>- cCall2(slowPath, cfr, PC) # This slowPath has the protocol: t0 = 0 => no error, t0 != 0 => error
- btiz t0, .noError
- move t1, cfr # t1 contains caller frame
</del><ins>+ move cfr, a0
+ move PC, a1
+ cCall2(slowPath) # This slowPath has the protocol: r0 = 0 => no error, r0 != 0 => error
+ btiz r0, .noError
+ move r1, cfr # r1 contains caller frame
</ins><span class="cx"> jmp _llint_throw_from_slow_path_trampoline
</span><span class="cx">
</span><span class="cx"> .noError:
</span><del>- # t1 points to ArityCheckData.
- loadp CommonSlowPaths::ArityCheckData::thunkToCall[t1], t2
- btpz t2, .proceedInline
</del><ins>+ # r1 points to ArityCheckData.
+ loadp CommonSlowPaths::ArityCheckData::thunkToCall[r1], t3
+ btpz t3, .proceedInline
</ins><span class="cx">
</span><del>- loadp CommonSlowPaths::ArityCheckData::returnPC[t1], t7
- loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t0
- call t2
</del><ins>+ loadp CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], a0
+ loadp CommonSlowPaths::ArityCheckData::returnPC[r1], a1
+ call t3
</ins><span class="cx"> if ASSERT_ENABLED
</span><span class="cx"> loadp ReturnPC[cfr], t0
</span><span class="cx"> loadp [t0], t0
</span><span class="lines">@@ -558,7 +523,7 @@
</span><span class="cx"> jmp .continue
</span><span class="cx">
</span><span class="cx"> .proceedInline:
</span><del>- loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[t1], t1
</del><ins>+ loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
</ins><span class="cx"> btiz t1, .continue
</span><span class="cx">
</span><span class="cx"> // Move frame up "t1 * 2" slots
</span><span class="lines">@@ -604,7 +569,6 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> # Instruction implementations
</span><del>-
</del><span class="cx"> _llint_op_enter:
</span><span class="cx"> traceExecution()
</span><span class="cx"> checkStackPointerAlignment(t2, 0xdead00e1)
</span><span class="lines">@@ -636,14 +600,14 @@
</span><span class="cx"> traceExecution()
</span><span class="cx"> loadisFromInstruction(2, t0)
</span><span class="cx"> loadp [cfr, t0, 8], t0
</span><del>- loadp JSFunction::m_rareData[t0], t4
- btpz t4, .opCreateThisSlow
- loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t4], t1
- loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t4], t2
</del><ins>+ loadp JSFunction::m_rareData[t0], t3
+ btpz t3, .opCreateThisSlow
+ loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_allocator[t3], t1
+ loadp FunctionRareData::m_allocationProfile + ObjectAllocationProfile::m_structure[t3], t2
</ins><span class="cx"> btpz t1, .opCreateThisSlow
</span><del>- loadpFromInstruction(4, t4)
- bpeq t4, 1, .hasSeenMultipleCallee
- bpneq t4, t0, .opCreateThisSlow
</del><ins>+ loadpFromInstruction(4, t3)
+ bpeq t3, 1, .hasSeenMultipleCallee
+ bpneq t3, t0, .opCreateThisSlow
</ins><span class="cx"> .hasSeenMultipleCallee:
</span><span class="cx"> allocateJSObject(t1, t2, t0, t3, .opCreateThisSlow)
</span><span class="cx"> loadisFromInstruction(1, t1)
</span><span class="lines">@@ -1776,7 +1740,7 @@
</span><span class="cx"> traceExecution()
</span><span class="cx"> checkSwitchToJITForEpilogue()
</span><span class="cx"> loadisFromInstruction(1, t2)
</span><del>- loadConstantOrVariable(t2, t0)
</del><ins>+ loadConstantOrVariable(t2, r0)
</ins><span class="cx"> doReturn()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1839,7 +1803,7 @@
</span><span class="cx"> checkSwitchToJITForEpilogue()
</span><span class="cx"> loadisFromInstruction(1, t0)
</span><span class="cx"> assertNotConstant(t0)
</span><del>- loadq [cfr, t0, 8], t0
</del><ins>+ loadq [cfr, t0, 8], r0
</ins><span class="cx"> doReturn()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1864,56 +1828,31 @@
</span><span class="cx">
</span><span class="cx"> functionPrologue()
</span><span class="cx"> storep 0, CodeBlock[cfr]
</span><del>- if X86_64 or X86_64_WIN
- if X86_64
- const arg1 = t4 # t4 = rdi
- const arg2 = t5 # t5 = rsi
- const temp = t1
- elsif X86_64_WIN
- const arg1 = t2 # t2 = rcx
- const arg2 = t1 # t1 = rdx
- const temp = t0
- end
- loadp Callee[cfr], t0
- andp MarkedBlockMask, t0, t1
- loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
- storep cfr, VM::topCallFrame[t1]
- move cfr, arg1
- loadp Callee[cfr], arg2
- loadp JSFunction::m_executable[arg2], temp
- checkStackPointerAlignment(t3, 0xdead0001)
</del><ins>+ loadp Callee[cfr], t0
+ andp MarkedBlockMask, t0, t1
+ loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
+ storep cfr, VM::topCallFrame[t1]
+ if ARM64 or C_LOOP
+ storep lr, ReturnPC[cfr]
+ end
+ move cfr, a0
+ loadp Callee[cfr], t1
+ loadp JSFunction::m_executable[t1], t1
+ checkStackPointerAlignment(t3, 0xdead0001)
+ if C_LOOP
+ cloopCallNative executableOffsetToFunction[t1]
+ else
</ins><span class="cx"> if X86_64_WIN
</span><span class="cx"> subp 32, sp
</span><span class="cx"> end
</span><del>- call executableOffsetToFunction[temp]
</del><ins>+ call executableOffsetToFunction[t1]
</ins><span class="cx"> if X86_64_WIN
</span><span class="cx"> addp 32, sp
</span><span class="cx"> end
</span><del>- loadp Callee[cfr], t3
- andp MarkedBlockMask, t3
- loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
- elsif ARM64 or C_LOOP
- loadp Callee[cfr], t0
- andp MarkedBlockMask, t0, t1
- loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
- storep cfr, VM::topCallFrame[t1]
- preserveReturnAddressAfterCall(t3)
- storep t3, ReturnPC[cfr]
- move cfr, t0
- loadp Callee[cfr], t1
- loadp JSFunction::m_executable[t1], t1
- if C_LOOP
- cloopCallNative executableOffsetToFunction[t1]
- else
- call executableOffsetToFunction[t1]
- end
- restoreReturnAddressBeforeReturn(t3)
- loadp Callee[cfr], t3
- andp MarkedBlockMask, t3
- loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
- else
- error
</del><span class="cx"> end
</span><ins>+ loadp Callee[cfr], t3
+ andp MarkedBlockMask, t3
+ loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
</ins><span class="cx">
</span><span class="cx"> functionEpilogue()
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmarmrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/arm.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/arm.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/arm.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -27,6 +27,34 @@
</span><span class="cx"> require "opt"
</span><span class="cx"> require "risc"
</span><span class="cx">
</span><ins>+# GPR conventions, to match the baseline JIT
+#
+# x0 => t0, a0, r0
+# x1 => t1, a1, r1
+# x2 => t2, a2, r2
+# x3 => t3, a3, r3
+# x6 => (callee-save scratch)
+# x7 => cfr (ARMv7 only)
+# x8 => t4 (callee-save)
+# x9 => t5 (callee-save)
+# x10 => (callee-save scratch)
+# x11 => cfr (ARM and ARMv7 traditional)
+# x12 => (callee-save scratch)
+# lr => lr
+# sp => sp
+# pc => pc
+#
+# FPR conventions, to match the baseline JIT
+#
+# d0 => ft0, fa0, fr
+# d1 => ft1, fa1
+# d2 => ft2
+# d3 => ft3
+# d4 => ft4
+# d5 => ft5
+# d6 => (scratch)
+# d7 => (scratch)
+
</ins><span class="cx"> def isARMv7
</span><span class="cx"> case $activeBackend
</span><span class="cx"> when "ARMv7"
</span><span class="lines">@@ -119,9 +147,9 @@
</span><span class="cx"> class FPRegisterID
</span><span class="cx"> def armOperand
</span><span class="cx"> case name
</span><del>- when "ft0", "fr"
</del><ins>+ when "ft0", "fr", "fa0"
</ins><span class="cx"> "d0"
</span><del>- when "ft1"
</del><ins>+ when "ft1", "fa1"
</ins><span class="cx"> "d1"
</span><span class="cx"> when "ft2"
</span><span class="cx"> "d2"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmarm64rb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/arm64.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/arm64.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/arm64.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -37,32 +37,30 @@
</span><span class="cx"> #
</span><span class="cx"> # GPR conventions, to match the baseline JIT:
</span><span class="cx"> #
</span><del>-# x0 => return value, cached result, first argument, t0, a0, r0
</del><ins>+# x0 => t0, a0, r0
</ins><span class="cx"> # x1 => t1, a1, r1
</span><span class="cx"> # x2 => t2, a2
</span><del>-# x3 => a3
-# x5 => t4
-# x6 => t6
-# x9 => (nonArgGPR1 in baseline)
-# x13 => scratch (unused in baseline)
-# x16 => scratch
-# x17 => scratch
-# x23 => t3
-# x24 => t5
-# x27 => csr1 (tagTypeNumber)
-# x28 => csr2 (tagMask)
</del><ins>+# x3 => t3, a3
+# x4 => t4
+# x5 => t5
+# x13 => (scratch)
+# x16 => (scratch)
+# x17 => (scratch)
+# x26 => csr0 (PB)
+# x27 => csr1 (tagTypeNumber)
+# x28 => csr2 (tagMask)
</ins><span class="cx"> # x29 => cfr
</span><span class="cx"> # sp => sp
</span><span class="cx"> # lr => lr
</span><span class="cx"> #
</span><del>-# FPR conentions, to match the baseline JIT:
</del><ins>+# FPR conventions, to match the baseline JIT:
</ins><span class="cx"> #
</span><del>-# q0 => ft0
-# q1 => ft1
-# q2 => ft2
-# q3 => ft3
-# q4 => ft4 (unused in baseline)
-# q5 => ft5 (unused in baseline)
</del><ins>+# q0 => ft0, fa0, fr
+# q1 => ft1, fa1
+# q2 => ft2, fa2
+# q3 => ft3, fa3
+# q4 => ft4 (unused in baseline)
+# q5 => ft5 (unused in baseline)
</ins><span class="cx"> # q31 => scratch
</span><span class="cx">
</span><span class="cx"> def arm64GPRName(name, kind)
</span><span class="lines">@@ -109,20 +107,16 @@
</span><span class="cx"> arm64GPRName('x1', kind)
</span><span class="cx"> when 't2', 'a2'
</span><span class="cx"> arm64GPRName('x2', kind)
</span><del>- when 'a3'
</del><ins>+ when 't3', 'a3'
</ins><span class="cx"> arm64GPRName('x3', kind)
</span><del>- when 't3'
- arm64GPRName('x23', kind)
</del><span class="cx"> when 't4'
</span><del>- arm64GPRName('x5', kind)
</del><ins>+ arm64GPRName('x4', kind)
</ins><span class="cx"> when 't5'
</span><del>- arm64GPRName('x24', kind)
- when 't6'
- arm64GPRName('x6', kind)
- when 't7'
- arm64GPRName('x7', kind)
</del><ins>+ arm64GPRName('x5', kind)
</ins><span class="cx"> when 'cfr'
</span><span class="cx"> arm64GPRName('x29', kind)
</span><ins>+ when 'csr0'
+ arm64GPRName('x26', kind)
</ins><span class="cx"> when 'csr1'
</span><span class="cx"> arm64GPRName('x27', kind)
</span><span class="cx"> when 'csr2'
</span><span class="lines">@@ -140,13 +134,13 @@
</span><span class="cx"> class FPRegisterID
</span><span class="cx"> def arm64Operand(kind)
</span><span class="cx"> case @name
</span><del>- when 'ft0'
</del><ins>+ when 'ft0', 'fr', 'fa0'
</ins><span class="cx"> arm64FPRName('q0', kind)
</span><del>- when 'ft1'
</del><ins>+ when 'ft1', 'fa1'
</ins><span class="cx"> arm64FPRName('q1', kind)
</span><del>- when 'ft2'
</del><ins>+ when 'ft2', 'fa2'
</ins><span class="cx"> arm64FPRName('q2', kind)
</span><del>- when 'ft3'
</del><ins>+ when 'ft3', 'fa3'
</ins><span class="cx"> arm64FPRName('q3', kind)
</span><span class="cx"> when 'ft4'
</span><span class="cx"> arm64FPRName('q4', kind)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmclooprb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/cloop.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/cloop.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/cloop.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -70,9 +70,9 @@
</span><span class="cx"> case name
</span><span class="cx"> # The cloop is modelled on the ARM implementation. Hence, the a0-a3
</span><span class="cx"> # registers are aliases for r0-r3 i.e. t0-t3 in our case.
</span><del>- when "t0", "a0"
</del><ins>+ when "t0", "a0", "r0"
</ins><span class="cx"> "t0"
</span><del>- when "t1", "a1"
</del><ins>+ when "t1", "a1", "r1"
</ins><span class="cx"> "t1"
</span><span class="cx"> when "t2", "a2"
</span><span class="cx"> "t2"
</span><span class="lines">@@ -82,10 +82,8 @@
</span><span class="cx"> "pc"
</span><span class="cx"> when "t5"
</span><span class="cx"> "t5"
</span><del>- when "t6"
</del><ins>+ when "csr0"
</ins><span class="cx"> "pcBase"
</span><del>- when "t7"
- "t7"
</del><span class="cx"> when "csr1"
</span><span class="cx"> "tagTypeNumber"
</span><span class="cx"> when "csr2"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmmipsrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/mips.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/mips.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/mips.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -24,6 +24,41 @@
</span><span class="cx">
</span><span class="cx"> require 'risc'
</span><span class="cx">
</span><ins>+# GPR conventions, to match the baseline JIT
+#
+# $a0 => a0
+# $a1 => a1
+# $a2 => a2
+# $a3 => a3
+# $v0 => t0, r0
+# $v1 => t1, r1
+# $t2 => t2
+# $t3 => t3
+# $t4 => t4
+# $t5 => t5
+# $t6 => (scratch)
+# $t7 => (scratch)
+# $t8 => (scratch)
+# $t9 => (stores the callee of a call opcode)
+# $gp => (globals)
+# $s4 => (callee-save used to preserve $gp across calls)
+# $ra => lr
+# $sp => sp
+# $fp => cfr
+#
+# FPR conventions, to match the baseline JIT
+# We don't have fa2 or fa3!
+# $f0 => ft0, fr
+# $f2 => ft1
+# $f4 => ft2
+# $f6 => ft3
+# $f8 => ft4
+# $f10 => ft5
+# $f12 => fa0
+# $f14 => fa1
+# $f16 => (scratch)
+# $f18 => (scratch)
+
</ins><span class="cx"> class Assembler
</span><span class="cx"> def putStr(str)
</span><span class="cx"> @outp.puts str
</span><span class="lines">@@ -57,8 +92,7 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-MIPS_TEMP_GPRS = [SpecialRegister.new("$t5"), SpecialRegister.new("$t6"), SpecialRegister.new("$t7"),
- SpecialRegister.new("$t8")]
</del><ins>+MIPS_TEMP_GPRS = [SpecialRegister.new("$t6"), SpecialRegister.new("$t7"), SpecialRegister.new("$t8")]
</ins><span class="cx"> MIPS_ZERO_REG = SpecialRegister.new("$zero")
</span><span class="cx"> MIPS_GP_REG = SpecialRegister.new("$gp")
</span><span class="cx"> MIPS_GPSAVE_REG = SpecialRegister.new("$s4")
</span><span class="lines">@@ -85,24 +119,18 @@
</span><span class="cx"> "$a2"
</span><span class="cx"> when "a3"
</span><span class="cx"> "$a3"
</span><del>- when "r0", "t0"
</del><ins>+ when "t0", "r0"
</ins><span class="cx"> "$v0"
</span><del>- when "r1", "t1"
</del><ins>+ when "t1", "r1"
</ins><span class="cx"> "$v1"
</span><span class="cx"> when "t2"
</span><span class="cx"> "$t2"
</span><span class="cx"> when "t3"
</span><del>- "$s3"
- when "t4" # PC reg in llint
- "$s2"
</del><ins>+ "$t3"
+ when "t4"
+ "$t4"
</ins><span class="cx"> when "t5"
</span><span class="cx"> "$t5"
</span><del>- when "t6"
- "$t6"
- when "t7"
- "$t7"
- when "t8"
- "$t8"
</del><span class="cx"> when "cfr"
</span><span class="cx"> "$fp"
</span><span class="cx"> when "lr"
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmregistersrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/registers.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/registers.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/registers.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -31,10 +31,6 @@
</span><span class="cx"> "t3",
</span><span class="cx"> "t4",
</span><span class="cx"> "t5",
</span><del>- "t6",
- "t7",
- "t8",
- "t9",
</del><span class="cx"> "cfr",
</span><span class="cx"> "a0",
</span><span class="cx"> "a1",
</span><span class="lines">@@ -46,8 +42,13 @@
</span><span class="cx"> "lr",
</span><span class="cx"> "pc",
</span><span class="cx"> # 64-bit only registers:
</span><del>- "csr1", # tag type number register
- "csr2" # tag mask register
</del><ins>+ "csr0",
+ "csr1",
+ "csr2",
+ "csr3",
+ "csr4",
+ "csr5",
+ "csr6"
</ins><span class="cx"> ]
</span><span class="cx">
</span><span class="cx"> FPRS =
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmsh4rb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/sh4.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/sh4.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/sh4.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -24,6 +24,33 @@
</span><span class="cx">
</span><span class="cx"> require 'risc'
</span><span class="cx">
</span><ins>+# GPR conventions, to match the baseline JIT
+#
+# r0 => t0, r0
+# r1 => t1, r1
+# r2 => t4
+# r3 => t5
+# r4 => a0
+# r5 => a1
+# r6 => t2, a2
+# r7 => t3, a3
+# r10 => (scratch)
+# r11 => (scratch)
+# r13 => (scratch)
+# r14 => cfr
+# r15 => sp
+# pr => lr
+
+# FPR conventions, to match the baseline JIT
+# We don't have fa2 or fa3!
+# dr0 => ft0, fr
+# dr2 => ft1
+# dr4 => ft2, fa0
+# dr6 => ft3, fa1
+# dr8 => ft4
+# dr10 => ft5
+# dr12 => (scratch)
+
</ins><span class="cx"> class Node
</span><span class="cx"> def sh4SingleHi
</span><span class="cx"> doubleOperand = sh4Operand
</span><span class="lines">@@ -51,32 +78,28 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-SH4_TMP_GPRS = [ SpecialRegister.new("r3"), SpecialRegister.new("r11"), SpecialRegister.new("r13") ]
-SH4_TMP_FPRS = [ SpecialRegister.new("dr10") ]
</del><ins>+SH4_TMP_GPRS = [ SpecialRegister.new("r10"), SpecialRegister.new("r11"), SpecialRegister.new("r13") ]
+SH4_TMP_FPRS = [ SpecialRegister.new("dr12") ]
</ins><span class="cx">
</span><span class="cx"> class RegisterID
</span><span class="cx"> def sh4Operand
</span><span class="cx"> case name
</span><del>- when "t0"
</del><ins>+ when "a0"
+ "r4"
+ when "a1"
+ "r5"
+ when "r0", "t0"
</ins><span class="cx"> "r0"
</span><del>- when "t1"
</del><ins>+ when "r1", "t1"
</ins><span class="cx"> "r1"
</span><del>- when "t2"
- "r2"
- when "t3"
- "r10"
- when "t4", "a0"
- "r4"
- when "t5", "a1"
- "r5"
- when "t6", "a2"
</del><ins>+ when "a2", "t2"
</ins><span class="cx"> "r6"
</span><del>- when "t7", "a3"
</del><ins>+ when "a3", "t3"
</ins><span class="cx"> "r7"
</span><del>- when "t8"
- "r8"
- when "t9"
- "r9"
</del><ins>+ when "t4"
+ "r2"
+ when "t5"
+ "r3"
</ins><span class="cx"> when "cfr"
</span><span class="cx"> "r14"
</span><span class="cx"> when "sp"
</span><span class="lines">@@ -96,14 +119,14 @@
</span><span class="cx"> "dr0"
</span><span class="cx"> when "ft1"
</span><span class="cx"> "dr2"
</span><del>- when "ft2"
</del><ins>+ when "ft2", "fa0"
</ins><span class="cx"> "dr4"
</span><del>- when "ft3"
</del><ins>+ when "ft3", "fa1"
</ins><span class="cx"> "dr6"
</span><span class="cx"> when "ft4"
</span><span class="cx"> "dr8"
</span><del>- when "fa0"
- "dr12"
</del><ins>+ when "ft5"
+ "dr10"
</ins><span class="cx"> else
</span><span class="cx"> raise "Bad register #{name} for SH4 at #{codeOriginString}"
</span><span class="cx"> end
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreofflineasmx86rb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/offlineasm/x86.rb (189292 => 189293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/offlineasm/x86.rb        2015-09-03 21:55:40 UTC (rev 189292)
+++ trunk/Source/JavaScriptCore/offlineasm/x86.rb        2015-09-03 22:16:23 UTC (rev 189293)
</span><span class="lines">@@ -24,6 +24,62 @@
</span><span class="cx">
</span><span class="cx"> require "config"
</span><span class="cx">
</span><ins>+# GPR conventions, to match the baseline JIT:
+#
+#
+# On x86-32 bits (windows and non-windows)
+# a0, a1, a2, a3 are only there for ease-of-use of offlineasm; they are not
+# actually considered as such by the ABI and we need to push/pop our arguments
+# on the stack. a0 and a1 are ecx and edx to follow fastcall.
+#
+# eax => t0, a2, r0
+# edx => t1, a1, r1
+# ecx => t2, a0
+# ebx => t3, a3 (callee-save)
+# esi => t4 (callee-save)
+# edi => t5 (callee-save)
+# ebp => cfr
+# esp => sp
+#
+# On x86-64 non-windows
+#
+# rax => t0, r0
+# rdi => a0
+# rsi => t1, a1
+# rdx => t2, a2, r1
+# rcx => t3, a3
+# r8 => t4
+# r10 => t5
+# rbx => csr0 (callee-save, PB, unused in baseline)
+# r12 => csr1 (callee-save)
+# r13 => csr2 (callee-save)
+# r14 => csr3 (callee-save, tagTypeNumber)
+# r15 => csr4 (callee-save, tagMask)
+# rsp => sp
+# rbp => cfr
+# r11 => (scratch)
+#
+# On x86-64 windows
+# Arguments need to be push/pop'd on the stack in addition to being stored in
+# the registers. Also, >8 return types are returned in a weird way.
+#
+# rax => t0, r0
+# rcx => a0
+# rdx => t1, a1, r1
+# r8 => t2, a2
+# r9 => t3, a3
+# r10 => t4
+# rbx => csr0 (callee-save, PB, unused in baseline)
+# rsi => csr1 (callee-save)
+# rdi => csr2 (callee-save)
+# r12 => csr3 (callee-save)
+# r13 => csr4 (callee-save)
+# r14 => csr5 (callee-save, tagTypeNumber)
+# r15 => csr6 (callee-save, tagMask)
+# rsp => sp
+# rbp => cfr
+# r11 => (scratch)
+
</ins><span class="cx"> def isX64
</span><span class="cx"> case $activeBackend
</span><span class="cx"> when "X86"
</span><span class="lines">@@ -39,6 +95,21 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><ins>+def isWin
+ case $activeBackend
+ when "X86"
+ false
+ when "X86_WIN"
+ true
+ when "X86_64"
+ false
+ when "X86_64_WIN"
+ true
+ else
+ raise "bad value for $activeBackend: #{$activeBackend}"
+ end
+end
+
</ins><span class="cx"> def useX87
</span><span class="cx"> case $activeBackend
</span><span class="cx"> when "X86"
</span><span class="lines">@@ -54,20 +125,20 @@
</span><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><del>-def isWindows
</del><ins>+def isCompilingOnWindows
</ins><span class="cx"> ENV['OS'] == 'Windows_NT'
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def isGCC
</span><del>- !isWindows
</del><ins>+ !isCompilingOnWindows
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def isMSVC
</span><del>- isWindows
</del><ins>+ isCompilingOnWindows
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def isIntelSyntax
</span><del>- isWindows
</del><ins>+ isCompilingOnWindows
</ins><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def register(name)
</span><span class="lines">@@ -141,205 +212,133 @@
</span><span class="cx">
</span><span class="cx"> X64_SCRATCH_REGISTER = SpecialRegister.new("r11")
</span><span class="cx">
</span><ins>+def x86GPRName(name, kind)
+ case name
+ when "eax", "ebx", "ecx", "edx"
+ name8 = name[1] + 'l'
+ name16 = name[1..2]
+ when "esi", "edi", "ebp", "esp"
+ name16 = name[1..2]
+ name8 = name16 + 'l'
+ when "rax", "rbx", "rcx", "rdx"
+ raise "bad GPR name #{name} in 32-bit X86" unless isX64
+ name8 = name[1] + 'l'
+ name16 = name[1..2]
+ when "r8", "r9", "r10", "r12", "r13", "r14", "r15"
+ raise "bad GPR name #{name} in 32-bit X86" unless isX64
+ case kind
+ when :half
+ return register(name + "w")
+ when :int
+ return register(name + "d")
+ when :ptr
+ return register(name)
+ when :quad
+ return register(name)
+ end
+ else
+ raise "bad GPR name #{name}"
+ end
+ case kind
+ when :byte
+ register(name8)
+ when :half
+ register(name16)
+ when :int
+ register("e" + name16)
+ when :ptr
+ register((isX64 ? "r" : "e") + name16)
+ when :quad
+ isX64 ? register("r" + name16) : raise
+ else
+ raise "invalid kind #{kind} for GPR #{name} in X86"
+ end
+end
+
</ins><span class="cx"> class RegisterID
</span><span class="cx"> def supports8BitOnX86
</span><del>- case name
- when "t0", "a0", "r0", "t1", "a1", "r1", "t2", "t3", "t4", "t5"
</del><ins>+ case x86GPR
+ when "eax", "ebx", "ecx", "edx", "edi", "esi", "ebp", "esp"
</ins><span class="cx"> true
</span><del>- when "cfr", "ttnr", "tmr"
</del><ins>+ when "r8", "r9", "r10", "r12", "r13", "r14", "r15"
</ins><span class="cx"> false
</span><del>- when "t6"
- isX64
</del><span class="cx"> else
</span><span class="cx"> raise
</span><span class="cx"> end
</span><span class="cx"> end
</span><del>-
- def x86Operand(kind)
- case name
- when "t0", "a0", "r0"
- case kind
- when :byte
- register("al")
- when :half
- register("ax")
- when :int
- register("eax")
- when :ptr
- isX64 ? register("rax") : register("eax")
- when :quad
- isX64 ? register("rax") : raise
</del><ins>+
+ def x86GPR
+ if isX64
+ case name
+ when "t0", "r0"
+ "eax"
+ when "r1"
+ "edx" # t1 = a1 when isWin, t2 = a2 otherwise
+ when "a0"
+ isWin ? "ecx" : "edi"
+ when "t1", "a1"
+ isWin ? "edx" : "esi"
+ when "t2", "a2"
+ isWin ? "r8" : "edx"
+ when "t3", "a3"
+ isWin ? "r9" : "ecx"
+ when "t4"
+ isWin ? "r10" : "r8"
+ when "t5"
+ raise "cannot use register #{name} on X86-64 Windows" unless not isWin
+ "r10"
+ when "csr0"
+ "ebx"
+ when "csr1"
+ "r12"
+ when "csr2"
+ "r13"
+ when "csr3"
+ isWin ? "esi" : "r14"
+ when "csr4"
+ isWin ? "edi" : "r15"
+ "r15"
+ when "csr5"
+ raise "cannot use register #{name} on X86-64" unless isWin
+ "r14"
+ when "csr6"
+ raise "cannot use register #{name} on X86-64" unless isWin
+ "r15"
+ when "cfr"
+ "ebp"
+ when "sp"
+ "esp"
</ins><span class="cx"> else
</span><del>- raise "Invalid kind #{kind} for name #{name}"
</del><ins>+ raise "cannot use register #{name} on X86"
</ins><span class="cx"> end
</span><del>- when "t1", "a1", "r1"
- case kind
- when :byte
- register("dl")
- when :half
- register("dx")
- when :int
- register("edx")
- when :ptr
- isX64 ? register("rdx") : register("edx")
- when :quad
- isX64 ? register("rdx") : raise
- else
- raise
</del><ins>+ else
+ case name
+ when "t0", "r0", "a2"
+ "eax"
+ when "t1", "r1", "a1"
+ "edx"
+ when "t2", "a0"
+ "ecx"
+ when "t3", "a3"
+ "ebx"
+ when "t4"
+ "esi"
+ when "t5"
+ "edi"
+ when "cfr"
+ "ebp"
+ when "sp"
+ "esp"
</ins><span class="cx"> end
</span><del>- when "t2"
- case kind
- when :byte
- register("cl")
- when :half
- register("cx")
- when :int
- register("ecx")
- when :ptr
- isX64 ? register("rcx") : register("ecx")
- when :quad
- isX64 ? register("rcx") : raise
- else
- raise
- end
- when "t3"
- case kind
- when :byte
- register("bl")
- when :half
- register("bx")
- when :int
- register("ebx")
- when :ptr
- isX64 ? register("rbx") : register("ebx")
- when :quad
- isX64 ? register("rbx") : raise
- else
- raise
- end
- when "t4"
- case kind
- when :byte
- register("dil")
- when :half
- register("di")
- when :int
- register("edi")
- when :ptr
- isX64 ? register("rdi") : register("edi")
- when :quad
- isX64 ? register("rdi") : raise
- else
- raise
- end
- when "cfr"
- if isX64
- case kind
- when :half
- register("bp")
- when :int
- register("ebp")
- when :ptr
- register("rbp")
- when :quad
- register("rbp")
- else
- raise
- end
- else
- case kind
- when :half
- register("bp")
- when :int
- register("ebp")
- when :ptr
- register("ebp")
- else
- raise
- end
- end
- when "sp"
- case kind
- when :byte
- register("spl")
- when :half
- register("sp")
- when :int
- register("esp")
- when :ptr
- isX64 ? register("rsp") : register("esp")
- when :quad
- isX64 ? register("rsp") : raise
- else
- raise
- end
- when "t5"
- case kind
- when :byte
- register("sil")
- when :half
- register("si")
- when :int
- register("esi")
- when :ptr
- isX64 ? register("rsi") : register("esi")
- when :quad
- isX64 ? register("rsi") : raise
- end
- when "t6"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- register("r8w")
- when :int
- register("r8d")
- when :ptr
- register("r8")
- when :quad
- register("r8")
- end
- when "t7"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- register("r9w")
- when :int
- register("r9d")
- when :ptr
- register("r9")
- when :quad
- register("r9")
- end
- when "csr1"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- register("r14w")
- when :int
- register("r14d")
- when :ptr
- register("r14")
- when :quad
- register("r14")
- end
- when "csr2"
- raise "Cannot use #{name} in 32-bit X86 at #{codeOriginString}" unless isX64
- case kind
- when :half
- register("r15w")
- when :int
- register("r15d")
- when :ptr
- register("r15")
- when :quad
- register("r15")
- end
- else
- raise "Bad register #{name} for X86 at #{codeOriginString}"
</del><span class="cx"> end
</span><span class="cx"> end
</span><ins>+
+ def x86Operand(kind)
+ x86GPRName(x86GPR, kind)
+ end
+
</ins><span class="cx"> def x86CallOperand(kind)
</span><del>- isX64 ? "#{callPrefix}#{x86Operand(:quad)}" : "#{callPrefix}#{x86Operand(:ptr)}"
</del><ins>+ "#{callPrefix}#{x86Operand(:ptr)}"
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -597,13 +596,12 @@
</span><span class="cx"> end
</span><span class="cx">
</span><span class="cx"> def handleX86Shift(opcode, kind)
</span><del>- if operands[0].is_a? Immediate or operands[0] == RegisterID.forName(nil, "t2")
</del><ins>+ if operands[0].is_a? Immediate or operands[0].x86GPR == "ecx"
</ins><span class="cx"> $asm.puts "#{opcode} #{orderOperands(operands[0].x86Operand(:byte), operands[1].x86Operand(kind))}"
</span><span class="cx"> else
</span><del>- cx = RegisterID.forName(nil, "t2")
- $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
</del><ins>+ $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{x86GPRName("ecx", :ptr)}"
</ins><span class="cx"> $asm.puts "#{opcode} #{orderOperands(register("cl"), operands[1].x86Operand(kind))}"
</span><del>- $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{cx.x86Operand(:ptr)}"
</del><ins>+ $asm.puts "xchg#{x86Suffix(:ptr)} #{operands[0].x86Operand(:ptr)}, #{x86GPRName("ecx", :ptr)}"
</ins><span class="cx"> end
</span><span class="cx"> end
</span><span class="cx">
</span><span class="lines">@@ -647,10 +645,14 @@
</span><span class="cx"> $asm.puts "movzx #{orderOperands(operand.x86Operand(:byte), operand.x86Operand(:int))}"
</span><span class="cx"> end
</span><span class="cx"> else
</span><del>- ax = RegisterID.new(nil, "t0")
</del><ins>+ ax = RegisterID.new(nil, "r0")
</ins><span class="cx"> $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
</span><del>- $asm.puts "#{setOpcode} %al"
- $asm.puts "movzbl %al, %eax"
</del><ins>+ $asm.puts "#{setOpcode} #{ax.x86Operand(:byte)}"
+ if !isIntelSyntax
+                $asm.puts "movzbl #{ax.x86Operand(:byte)}, #{ax.x86Operand(:int)}"
+ else
+ $asm.puts "movzx #{ax.x86Operand(:int)}, #{ax.x86Operand(:byte)}"
+ end
</ins><span class="cx"> $asm.puts "xchg#{x86Suffix(:ptr)} #{operand.x86Operand(:ptr)}, #{ax.x86Operand(:ptr)}"
</span><span class="cx"> end
</span><span class="cx"> end
</span></span></pre>
</div>
</div>
</body>
</html>