39259514b94ca02227f71390312568f860458a9a
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / buildroot-2015.05 / package / webkit / 0007-mips-dfg.patch
1 Upstream patch for DFG implementation for MIPS
2
3 Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
4
5 From c921d19863ccf66bdd0ffa5d38eaf05efab6b136 Mon Sep 17 00:00:00 2001
6 From: "commit-queue@webkit.org"
7  <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
8 Date: Mon, 18 Feb 2013 19:25:23 +0000
9 Subject: [PATCH] MIPS DFG implementation.
10  https://bugs.webkit.org/show_bug.cgi?id=101328
11
12 Patch by Balazs Kilvady <kilvadyb@homejinni.com> on 2013-02-18
13 Reviewed by Oliver Hunt.
14
15 DFG implementation for MIPS.
16
17 Source/JavaScriptCore:
18
19 * assembler/MIPSAssembler.h:
20 (JSC::MIPSAssembler::MIPSAssembler):
21 (JSC::MIPSAssembler::sllv):
22 (JSC::MIPSAssembler::movd):
23 (MIPSAssembler):
24 (JSC::MIPSAssembler::negd):
25 (JSC::MIPSAssembler::labelForWatchpoint):
26 (JSC::MIPSAssembler::label):
27 (JSC::MIPSAssembler::vmov):
28 (JSC::MIPSAssembler::linkDirectJump):
29 (JSC::MIPSAssembler::maxJumpReplacementSize):
30 (JSC::MIPSAssembler::revertJumpToMove):
31 (JSC::MIPSAssembler::replaceWithJump):
32 * assembler/MacroAssembler.h:
33 (MacroAssembler):
34 (JSC::MacroAssembler::poke):
35 * assembler/MacroAssemblerMIPS.h:
36 (JSC::MacroAssemblerMIPS::add32):
37 (MacroAssemblerMIPS):
38 (JSC::MacroAssemblerMIPS::and32):
39 (JSC::MacroAssemblerMIPS::lshift32):
40 (JSC::MacroAssemblerMIPS::mul32):
41 (JSC::MacroAssemblerMIPS::or32):
42 (JSC::MacroAssemblerMIPS::rshift32):
43 (JSC::MacroAssemblerMIPS::urshift32):
44 (JSC::MacroAssemblerMIPS::sub32):
45 (JSC::MacroAssemblerMIPS::xor32):
46 (JSC::MacroAssemblerMIPS::store32):
47 (JSC::MacroAssemblerMIPS::jump):
48 (JSC::MacroAssemblerMIPS::branchAdd32):
49 (JSC::MacroAssemblerMIPS::branchMul32):
50 (JSC::MacroAssemblerMIPS::branchSub32):
51 (JSC::MacroAssemblerMIPS::branchNeg32):
52 (JSC::MacroAssemblerMIPS::call):
53 (JSC::MacroAssemblerMIPS::loadDouble):
54 (JSC::MacroAssemblerMIPS::moveDouble):
55 (JSC::MacroAssemblerMIPS::swapDouble):
56 (JSC::MacroAssemblerMIPS::subDouble):
57 (JSC::MacroAssemblerMIPS::mulDouble):
58 (JSC::MacroAssemblerMIPS::divDouble):
59 (JSC::MacroAssemblerMIPS::negateDouble):
60 (JSC::MacroAssemblerMIPS::branchEqual):
61 (JSC::MacroAssemblerMIPS::branchNotEqual):
62 (JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32):
63 (JSC::MacroAssemblerMIPS::branchTruncateDoubleToUint32):
64 (JSC::MacroAssemblerMIPS::truncateDoubleToInt32):
65 (JSC::MacroAssemblerMIPS::truncateDoubleToUint32):
66 (JSC::MacroAssemblerMIPS::branchDoubleNonZero):
67 (JSC::MacroAssemblerMIPS::branchDoubleZeroOrNaN):
68 (JSC::MacroAssemblerMIPS::invert):
69 (JSC::MacroAssemblerMIPS::replaceWithJump):
70 (JSC::MacroAssemblerMIPS::maxJumpReplacementSize):
71 * dfg/DFGAssemblyHelpers.h:
72 (AssemblyHelpers):
73 (JSC::DFG::AssemblyHelpers::preserveReturnAddressAfterCall):
74 (JSC::DFG::AssemblyHelpers::restoreReturnAddressBeforeReturn):
75 (JSC::DFG::AssemblyHelpers::debugCall):
76 * dfg/DFGCCallHelpers.h:
77 (CCallHelpers):
78 (JSC::DFG::CCallHelpers::setupArguments):
79 (JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
80 * dfg/DFGFPRInfo.h:
81 (DFG):
82 (FPRInfo):
83 (JSC::DFG::FPRInfo::toRegister):
84 (JSC::DFG::FPRInfo::toIndex):
85 (JSC::DFG::FPRInfo::debugName):
86 * dfg/DFGGPRInfo.h:
87 (DFG):
88 (GPRInfo):
89 (JSC::DFG::GPRInfo::toRegister):
90 (JSC::DFG::GPRInfo::toIndex):
91 (JSC::DFG::GPRInfo::debugName):
92 * dfg/DFGSpeculativeJIT.h:
93 (SpeculativeJIT):
94 * jit/JSInterfaceJIT.h:
95 (JSInterfaceJIT):
96 * runtime/JSGlobalData.h:
97 (JSC::ScratchBuffer::allocationSize):
98 (ScratchBuffer):
99
100 Source/WTF:
101
102 * wtf/Platform.h:
103
104 git-svn-id: http://svn.webkit.org/repository/webkit/trunk@143247 268f45cc-cd09-0410-ab3c-d52691b4dbfc
105 ---
106  Source/JavaScriptCore/ChangeLog                    |  90 ++++
107  Source/JavaScriptCore/assembler/MIPSAssembler.h    | 109 ++++-
108  Source/JavaScriptCore/assembler/MacroAssembler.h   |   7 +
109  .../JavaScriptCore/assembler/MacroAssemblerMIPS.h  | 480 +++++++++++++++++++--
110  Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h     |  19 +-
111  Source/JavaScriptCore/dfg/DFGCCallHelpers.h        |  92 ++--
112  Source/JavaScriptCore/dfg/DFGFPRInfo.h             |  68 +++
113  Source/JavaScriptCore/dfg/DFGGPRInfo.h             |  67 +++
114  Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h      |   4 +-
115  Source/JavaScriptCore/jit/JSInterfaceJIT.h         |   4 +
116  Source/JavaScriptCore/runtime/JSGlobalData.h       |   6 +-
117  Source/WTF/ChangeLog                               |  11 +
118  Source/WTF/wtf/Platform.h                          |   4 +
119  13 files changed, 888 insertions(+), 73 deletions(-)
120
121 diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h
122 index 026f87e..7f553bb 100644
123 --- a/Source/JavaScriptCore/assembler/MIPSAssembler.h
124 +++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h
125 @@ -152,6 +152,8 @@ public:
126      typedef SegmentedVector<AssemblerLabel, 64> Jumps;
127  
128      MIPSAssembler()
129 +        : m_indexOfLastWatchpoint(INT_MIN)
130 +        , m_indexOfTailOfLastWatchpoint(INT_MIN)
131      {
132      }
133  
134 @@ -325,7 +327,7 @@ public:
135          emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT));
136      }
137  
138 -    void sllv(RegisterID rd, RegisterID rt, int rs)
139 +    void sllv(RegisterID rd, RegisterID rt, RegisterID rs)
140      {
141          emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS));
142      }
143 @@ -527,6 +529,16 @@ public:
144          emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
145      }
146  
147 +    void movd(FPRegisterID fd, FPRegisterID fs)
148 +    {
149 +        emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
150 +    }
151 +
152 +    void negd(FPRegisterID fd, FPRegisterID fs)
153 +    {
154 +        emitInst(0x46200007 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
155 +    }
156 +
157      void truncwd(FPRegisterID fd, FPRegisterID fs)
158      {
159          emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
160 @@ -619,9 +631,24 @@ public:
161          return m_buffer.label();
162      }
163  
164 +    AssemblerLabel labelForWatchpoint()
165 +    {
166 +        AssemblerLabel result = m_buffer.label();
167 +        if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
168 +            result = label();
169 +        m_indexOfLastWatchpoint = result.m_offset;
170 +        m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
171 +        return result;
172 +    }
173 +
174      AssemblerLabel label()
175      {
176 -        return m_buffer.label();
177 +        AssemblerLabel result = m_buffer.label();
178 +        while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
179 +            nop();
180 +            result = m_buffer.label();
181 +        }
182 +        return result;
183      }
184  
185      AssemblerLabel align(int alignment)
186 @@ -664,14 +691,24 @@ public:
187      // Assembly helpers for moving data between fp and registers.
188      void vmov(RegisterID rd1, RegisterID rd2, FPRegisterID rn)
189      {
190 +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
191 +        mfc1(rd1, rn);
192 +        mfhc1(rd2, rn);
193 +#else
194          mfc1(rd1, rn);
195          mfc1(rd2, FPRegisterID(rn + 1));
196 +#endif
197      }
198  
199      void vmov(FPRegisterID rd, RegisterID rn1, RegisterID rn2)
200      {
201 +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
202 +        mtc1(rn1, rd);
203 +        mthc1(rn2, rd);
204 +#else
205          mtc1(rn1, rd);
206          mtc1(rn2, FPRegisterID(rd + 1));
207 +#endif
208      }
209  
210      static unsigned getCallReturnOffset(AssemblerLabel call)
211 @@ -688,6 +725,35 @@ public:
212      // writable region of memory; to modify the code in an execute-only execuable
213      // pool the 'repatch' and 'relink' methods should be used.
214  
215 +    static size_t linkDirectJump(void* code, void* to)
216 +    {
217 +        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code));
218 +        size_t ops = 0;
219 +        int32_t slotAddr = reinterpret_cast<int>(insn) + 4;
220 +        int32_t toAddr = reinterpret_cast<int>(to);
221 +
222 +        if ((slotAddr & 0xf0000000) != (toAddr & 0xf0000000)) {
223 +            // lui
224 +            *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((toAddr >> 16) & 0xffff);
225 +            ++insn;
226 +            // ori
227 +            *insn = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (toAddr & 0xffff);
228 +            ++insn;
229 +            // jr
230 +            *insn = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
231 +            ++insn;
232 +            ops = 4 * sizeof(MIPSWord);
233 +        } else {
234 +            // j
235 +            *insn = 0x08000000 | ((toAddr & 0x0fffffff) >> 2);
236 +            ++insn;
237 +            ops = 2 * sizeof(MIPSWord);
238 +        }
239 +        // nop
240 +        *insn = 0x00000000;
241 +        return ops;
242 +    }
243 +
244      void linkJump(AssemblerLabel from, AssemblerLabel to)
245      {
246          ASSERT(to.isSet());
247 @@ -825,29 +891,36 @@ public:
248  #endif
249      }
250  
251 -    static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm)
252 +    static ptrdiff_t maxJumpReplacementSize()
253      {
254 -        MIPSWord* insn = static_cast<MIPSWord*>(instructionStart) + 1;
255 -        ASSERT((*insn & 0xfc000000) == 0x34000000);
256 -        *insn = (*insn & 0xfc1f0000) | (imm & 0xffff);
257 -        cacheFlush(insn, sizeof(MIPSWord));
258 +        return sizeof(MIPSWord) * 4;
259      }
260  
261 -    static void replaceWithJump(void* instructionStart, void* to)
262 +    static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm)
263      {
264 -        MIPSWord* instruction = reinterpret_cast<MIPSWord*>(instructionStart);
265 -        intptr_t jumpTo = reinterpret_cast<intptr_t>(to);
266 +        MIPSWord* insn = static_cast<MIPSWord*>(instructionStart);
267 +        size_t codeSize = 2 * sizeof(MIPSWord);
268  
269          // lui
270 -        instruction[0] = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((jumpTo >> 16) & 0xffff);
271 +        *insn = 0x3c000000 | (rt << OP_SH_RT) | ((imm >> 16) & 0xffff);
272 +        ++insn;
273          // ori
274 -        instruction[1] = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (jumpTo & 0xffff);
275 -        // jr
276 -        instruction[2] = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
277 -        // nop
278 -        instruction[3] = 0x0;
279 +        *insn = 0x34000000 | (rt << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff);
280 +        ++insn;
281 +        // if jr $t9
282 +        if (*insn == 0x03200008) {
283 +            *insn = 0x00000000;
284 +            codeSize += sizeof(MIPSWord);
285 +        }
286 +        cacheFlush(insn, codeSize);
287 +    }
288  
289 -        cacheFlush(instruction, sizeof(MIPSWord) * 4);
290 +    static void replaceWithJump(void* instructionStart, void* to)
291 +    {
292 +        ASSERT(!(bitwise_cast<uintptr_t>(instructionStart) & 3));
293 +        ASSERT(!(bitwise_cast<uintptr_t>(to) & 3));
294 +        size_t ops = linkDirectJump(instructionStart, to);
295 +        cacheFlush(instructionStart, ops);
296      }
297  
298      static void replaceWithLoad(void* instructionStart)
299 @@ -1023,6 +1096,8 @@ private:
300  
301      AssemblerBuffer m_buffer;
302      Jumps m_jumps;
303 +    int m_indexOfLastWatchpoint;
304 +    int m_indexOfTailOfLastWatchpoint;
305  };
306  
307  } // namespace JSC
308 diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h
309 index 60a93db..1f0c3de 100644
310 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h
311 +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h
312 @@ -200,6 +200,13 @@ public:
313      }
314  #endif
315      
316 +#if CPU(MIPS)
317 +    void poke(FPRegisterID src, int index = 0)
318 +    {
319 +        ASSERT(!(index & 1));
320 +        storeDouble(src, addressForPoke(index));
321 +    }
322 +#endif
323  
324      // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
325      void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target)
326 diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
327 index 43ad434..4f14960 100644
328 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
329 +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h
330 @@ -114,6 +114,11 @@ public:
331          m_assembler.addu(dest, dest, src);
332      }
333  
334 +    void add32(RegisterID op1, RegisterID op2, RegisterID dest)
335 +    {
336 +        m_assembler.addu(dest, op1, op2);
337 +    }
338 +
339      void add32(TrustedImm32 imm, RegisterID dest)
340      {
341          add32(imm, dest, dest);
342 @@ -267,6 +272,11 @@ public:
343          m_assembler.andInsn(dest, dest, src);
344      }
345  
346 +    void and32(RegisterID op1, RegisterID op2, RegisterID dest)
347 +    {
348 +        m_assembler.andInsn(dest, op1, op2);
349 +    }
350 +
351      void and32(TrustedImm32 imm, RegisterID dest)
352      {
353          if (!imm.m_value && !m_fixedWidth)
354 @@ -283,9 +293,16 @@ public:
355          }
356      }
357  
358 -    void lshift32(TrustedImm32 imm, RegisterID dest)
359 +    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
360      {
361 -        m_assembler.sll(dest, dest, imm.m_value);
362 +        if (!imm.m_value && !m_fixedWidth)
363 +            move(MIPSRegisters::zero, dest);
364 +        else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth)
365 +            m_assembler.andi(dest, src, imm.m_value);
366 +        else {
367 +            move(imm, immTempRegister);
368 +            m_assembler.andInsn(dest, src, immTempRegister);
369 +        }
370      }
371  
372      void lshift32(RegisterID shiftAmount, RegisterID dest)
373 @@ -293,11 +310,33 @@ public:
374          m_assembler.sllv(dest, dest, shiftAmount);
375      }
376  
377 +    void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
378 +    {
379 +        m_assembler.sllv(dest, src, shiftAmount);
380 +    }
381 +
382 +    void lshift32(TrustedImm32 imm, RegisterID dest)
383 +    {
384 +        move(imm, immTempRegister);
385 +        m_assembler.sllv(dest, dest, immTempRegister);
386 +    }
387 +
388 +    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
389 +    {
390 +        move(imm, immTempRegister);
391 +        m_assembler.sllv(dest, src, immTempRegister);
392 +    }
393 +
394      void mul32(RegisterID src, RegisterID dest)
395      {
396          m_assembler.mul(dest, dest, src);
397      }
398  
399 +    void mul32(RegisterID op1, RegisterID op2, RegisterID dest)
400 +    {
401 +        m_assembler.mul(dest, op1, op2);
402 +    }
403 +
404      void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
405      {
406          if (!imm.m_value && !m_fixedWidth)
407 @@ -348,6 +387,24 @@ public:
408          m_assembler.orInsn(dest, dest, dataTempRegister);
409      }
410  
411 +    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
412 +    {
413 +        if (!imm.m_value && !m_fixedWidth)
414 +            return;
415 +
416 +        if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) {
417 +            m_assembler.ori(dest, src, imm.m_value);
418 +            return;
419 +        }
420 +
421 +        /*
422 +            li      dataTemp, imm
423 +            or      dest, src, dataTemp
424 +        */
425 +        move(imm, dataTempRegister);
426 +        m_assembler.orInsn(dest, src, dataTempRegister);
427 +    }
428 +
429      void or32(RegisterID src, AbsoluteAddress dest)
430      {
431          load32(dest.m_ptr, dataTempRegister);
432 @@ -360,6 +417,11 @@ public:
433          m_assembler.srav(dest, dest, shiftAmount);
434      }
435  
436 +    void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
437 +    {
438 +        m_assembler.srav(dest, src, shiftAmount);
439 +    }
440 +
441      void rshift32(TrustedImm32 imm, RegisterID dest)
442      {
443          m_assembler.sra(dest, dest, imm.m_value);
444 @@ -375,16 +437,31 @@ public:
445          m_assembler.srlv(dest, dest, shiftAmount);
446      }
447  
448 +    void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
449 +    {
450 +        m_assembler.srlv(dest, src, shiftAmount);
451 +    }
452 +
453      void urshift32(TrustedImm32 imm, RegisterID dest)
454      {
455          m_assembler.srl(dest, dest, imm.m_value);
456      }
457  
458 +    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
459 +    {
460 +        m_assembler.srl(dest, src, imm.m_value);
461 +    }
462 +
463      void sub32(RegisterID src, RegisterID dest)
464      {
465          m_assembler.subu(dest, dest, src);
466      }
467  
468 +    void sub32(RegisterID op1, RegisterID op2, RegisterID dest)
469 +    {
470 +        m_assembler.subu(dest, op1, op2);
471 +    }
472 +
473      void sub32(TrustedImm32 imm, RegisterID dest)
474      {
475          if (imm.m_value >= -32767 && imm.m_value <= 32768
476 @@ -495,6 +572,11 @@ public:
477          m_assembler.xorInsn(dest, dest, src);
478      }
479  
480 +    void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
481 +    {
482 +        m_assembler.xorInsn(dest, op1, op2);
483 +    }
484 +
485      void xor32(TrustedImm32 imm, RegisterID dest)
486      {
487          if (imm.m_value == -1) {
488 @@ -510,6 +592,21 @@ public:
489          m_assembler.xorInsn(dest, dest, immTempRegister);
490      }
491  
492 +    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
493 +    {
494 +        if (imm.m_value == -1) {
495 +            m_assembler.nor(dest, src, MIPSRegisters::zero);
496 +            return;
497 +        }
498 +
499 +        /*
500 +            li  immTemp, imm
501 +            xor dest, dest, immTemp
502 +        */
503 +        move(imm, immTempRegister);
504 +        m_assembler.xorInsn(dest, src, immTempRegister);
505 +    }
506 +
507      void sqrtDouble(FPRegisterID src, FPRegisterID dst)
508      {
509          m_assembler.sqrtd(dst, src);
510 @@ -989,6 +1086,44 @@ public:
511          }
512      }
513  
514 +    void store32(TrustedImm32 imm, BaseIndex address)
515 +    {
516 +        if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) {
517 +            /*
518 +                sll     addrTemp, address.index, address.scale
519 +                addu    addrTemp, addrTemp, address.base
520 +                sw      src, address.offset(addrTemp)
521 +            */
522 +            m_assembler.sll(addrTempRegister, address.index, address.scale);
523 +            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
524 +            if (!imm.m_value)
525 +                m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
526 +            else {
527 +                move(imm, immTempRegister);
528 +                m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
529 +            }
530 +        } else {
531 +            /*
532 +                sll     addrTemp, address.index, address.scale
533 +                addu    addrTemp, addrTemp, address.base
534 +                lui     immTemp, (address.offset + 0x8000) >> 16
535 +                addu    addrTemp, addrTemp, immTemp
536 +                sw      src, (address.offset & 0xffff)(at)
537 +            */
538 +            m_assembler.sll(addrTempRegister, address.index, address.scale);
539 +            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
540 +            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
541 +            m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
542 +            if (!imm.m_value && !m_fixedWidth)
543 +                m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
544 +            else {
545 +                move(imm, immTempRegister);
546 +                m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
547 +            }
548 +        }
549 +    }
550 +
551 +
552      void store32(RegisterID src, const void* address)
553      {
554          /*
555 @@ -1336,6 +1471,15 @@ public:
556          m_fixedWidth = false;
557      }
558  
559 +    void jump(AbsoluteAddress address)
560 +    {
561 +        m_fixedWidth = true;
562 +        load32(address.m_ptr, MIPSRegisters::t9);
563 +        m_assembler.jr(MIPSRegisters::t9);
564 +        m_assembler.nop();
565 +        m_fixedWidth = false;
566 +    }
567 +
568      void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
569      {
570          m_assembler.vmov(dest1, dest2, src);
571 @@ -1404,6 +1548,53 @@ public:
572          return Jump();
573      }
574  
575 +    Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
576 +    {
577 +        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
578 +        if (cond == Overflow) {
579 +            /*
580 +                move    dataTemp, op1
581 +                xor     cmpTemp, dataTemp, op2
582 +                bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
583 +                addu    dest, dataTemp, op2
584 +                xor     cmpTemp, dest, dataTemp
585 +                bgez    cmpTemp, No_overflow    # same sign big -> no overflow
586 +                nop
587 +                b       Overflow
588 +                nop
589 +                nop
590 +                nop
591 +                nop
592 +                nop
593 +            No_overflow:
594 +            */
595 +            move(op1, dataTempRegister);
596 +            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
597 +            m_assembler.bltz(cmpTempRegister, 10);
598 +            m_assembler.addu(dest, dataTempRegister, op2);
599 +            m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
600 +            m_assembler.bgez(cmpTempRegister, 7);
601 +            m_assembler.nop();
602 +            return jump();
603 +        }
604 +        if (cond == Signed) {
605 +            add32(op1, op2, dest);
606 +            // Check if dest is negative.
607 +            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
608 +            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
609 +        }
610 +        if (cond == Zero) {
611 +            add32(op1, op2, dest);
612 +            return branchEqual(dest, MIPSRegisters::zero);
613 +        }
614 +        if (cond == NonZero) {
615 +            add32(op1, op2, dest);
616 +            return branchNotEqual(dest, MIPSRegisters::zero);
617 +        }
618 +        ASSERT(0);
619 +        return Jump();
620 +    }
621 +
622      Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
623      {
624          move(imm, immTempRegister);
625 @@ -1417,6 +1608,111 @@ public:
626          return branchAdd32(cond, immTempRegister, dest);
627      }
628  
629 +    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
630 +    {
631 +        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
632 +        if (cond == Overflow) {
633 +            /*
634 +                move    dataTemp, dest
635 +                xori    cmpTemp, dataTemp, imm
636 +                bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
637 +                addiu   dataTemp, dataTemp, imm
638 +                move    dest, dataTemp
639 +                xori    cmpTemp, dataTemp, imm
640 +                bgez    cmpTemp, No_overflow    # same sign big -> no overflow
641 +                nop
642 +                b       Overflow
643 +                nop
644 +                nop
645 +                nop
646 +                nop
647 +                nop
648 +            No_overflow:
649 +            */
650 +            if (imm.m_value >= -32768 && imm.m_value  <= 32767 && !m_fixedWidth) {
651 +                load32(dest.m_ptr, dataTempRegister);
652 +                m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
653 +                m_assembler.bltz(cmpTempRegister, 10);
654 +                m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
655 +                store32(dataTempRegister, dest.m_ptr);
656 +                m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
657 +                m_assembler.bgez(cmpTempRegister, 7);
658 +                m_assembler.nop();
659 +            } else {
660 +                load32(dest.m_ptr, dataTempRegister);
661 +                move(imm, immTempRegister);
662 +                m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister);
663 +                m_assembler.bltz(cmpTempRegister, 10);
664 +                m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister);
665 +                store32(dataTempRegister, dest.m_ptr);
666 +                m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister);
667 +                m_assembler.bgez(cmpTempRegister, 7);
668 +                m_assembler.nop();
669 +            }
670 +            return jump();
671 +        }
672 +        move(imm, immTempRegister);
673 +        load32(dest.m_ptr, dataTempRegister);
674 +        add32(immTempRegister, dataTempRegister);
675 +        store32(dataTempRegister, dest.m_ptr);
676 +        if (cond == Signed) {
677 +            // Check if dest is negative.
678 +            m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero);
679 +            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
680 +        }
681 +        if (cond == Zero)
682 +            return branchEqual(dataTempRegister, MIPSRegisters::zero);
683 +        if (cond == NonZero)
684 +            return branchNotEqual(dataTempRegister, MIPSRegisters::zero);
685 +        ASSERT(0);
686 +        return Jump();
687 +    }
688 +
689 +    Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
690 +    {
691 +        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
692 +        if (cond == Overflow) {
693 +            /*
694 +                mult    src, dest
695 +                mfhi    dataTemp
696 +                mflo    dest
697 +                sra     addrTemp, dest, 31
698 +                beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
699 +                nop
700 +                b       Overflow
701 +                nop
702 +                nop
703 +                nop
704 +                nop
705 +                nop
706 +            No_overflow:
707 +            */
708 +            m_assembler.mult(src1, src2);
709 +            m_assembler.mfhi(dataTempRegister);
710 +            m_assembler.mflo(dest);
711 +            m_assembler.sra(addrTempRegister, dest, 31);
712 +            m_assembler.beq(dataTempRegister, addrTempRegister, 7);
713 +            m_assembler.nop();
714 +            return jump();
715 +        }
716 +        if (cond == Signed) {
717 +            mul32(src1, src2, dest);
718 +            // Check if dest is negative.
719 +            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
720 +            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
721 +        }
722 +        if (cond == Zero) {
723 +            mul32(src1, src2, dest);
724 +            return branchEqual(dest, MIPSRegisters::zero);
725 +        }
726 +        if (cond == NonZero) {
727 +            mul32(src1, src2, dest);
728 +            return branchNotEqual(dest, MIPSRegisters::zero);
729 +        }
730 +        ASSERT(0);
731 +        return Jump();
732 +    }
733 +
734      Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
735      {
736          ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
737 @@ -1465,8 +1761,7 @@ public:
738      Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
739      {
740          move(imm, immTempRegister);
741 -        move(src, dest);
742 -        return branchMul32(cond, immTempRegister, dest);
743 +        return branchMul32(cond, immTempRegister, src, dest);
744      }
745  
746      Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
747 @@ -1525,8 +1820,60 @@ public:
748      Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
749      {
750          move(imm, immTempRegister);
751 -        move(src, dest);
752 -        return branchSub32(cond, immTempRegister, dest);
753 +        return branchSub32(cond, src, immTempRegister, dest);
754 +    }
755 +
756 +    Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
757 +    {
758 +        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
759 +        if (cond == Overflow) {
760 +            /*
761 +                move    dataTemp, op1
762 +                xor     cmpTemp, dataTemp, op2
763 +                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
764 +                subu    dest, dataTemp, op2
765 +                xor     cmpTemp, dest, dataTemp
766 +                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
767 +                nop
768 +                b       Overflow
769 +                nop
770 +                nop
771 +                nop
772 +                nop
773 +                nop
774 +            No_overflow:
775 +            */
776 +            move(op1, dataTempRegister);
777 +            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
778 +            m_assembler.bgez(cmpTempRegister, 10);
779 +            m_assembler.subu(dest, dataTempRegister, op2);
780 +            m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
781 +            m_assembler.bgez(cmpTempRegister, 7);
782 +            m_assembler.nop();
783 +            return jump();
784 +        }
785 +        if (cond == Signed) {
786 +            sub32(op1, op2, dest);
787 +            // Check if dest is negative.
788 +            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
789 +            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
790 +        }
791 +        if (cond == Zero) {
792 +            sub32(op1, op2, dest);
793 +            return branchEqual(dest, MIPSRegisters::zero);
794 +        }
795 +        if (cond == NonZero) {
796 +            sub32(op1, op2, dest);
797 +            return branchNotEqual(dest, MIPSRegisters::zero);
798 +        }
799 +        ASSERT(0);
800 +        return Jump();
801 +    }
802 +
803 +    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
804 +    {
805 +        m_assembler.li(dataTempRegister, -1);
806 +        return branchMul32(cond, dataTempRegister, srcDest);
807      }
808  
809      Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
810 @@ -1578,7 +1925,8 @@ public:
811  
812      Call call(RegisterID target)
813      {
814 -        m_assembler.jalr(target);
815 +        move(target, MIPSRegisters::t9);
816 +        m_assembler.jalr(MIPSRegisters::t9);
817          m_assembler.nop();
818          return Call(m_assembler.label(), Call::None);
819      }
820 @@ -1822,7 +2170,7 @@ public:
821                  lui     immTemp, (address.offset + 0x8000) >> 16
822                  addu    addrTemp, addrTemp, immTemp
823                  lwc1    dest, (address.offset & 0xffff)(at)
824 -                lwc1    dest+4, (address.offset & 0xffff + 4)(at)
825 +                lwc1    dest+1, (address.offset & 0xffff + 4)(at)
826              */
827              m_assembler.sll(addrTempRegister, address.index, address.scale);
828              m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
829 @@ -2009,6 +2357,19 @@ public:
830  #endif
831      }
832  
833 +    void moveDouble(FPRegisterID src, FPRegisterID dest)
834 +    {
835 +        if (src != dest || m_fixedWidth)
836 +            m_assembler.movd(dest, src);
837 +    }
838 +
839 +    void swapDouble(FPRegisterID fr1, FPRegisterID fr2)
840 +    {
841 +        moveDouble(fr1, fpTempRegister);
842 +        moveDouble(fr2, fr1);
843 +        moveDouble(fpTempRegister, fr2);
844 +    }
845 +
846      void addDouble(FPRegisterID src, FPRegisterID dest)
847      {
848          m_assembler.addd(dest, dest, src);
849 @@ -2036,6 +2397,11 @@ public:
850          m_assembler.subd(dest, dest, src);
851      }
852  
853 +    void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
854 +    {
855 +        m_assembler.subd(dest, op1, op2);
856 +    }
857 +
858      void subDouble(Address src, FPRegisterID dest)
859      {
860          loadDouble(src, fpTempRegister);
861 @@ -2053,11 +2419,32 @@ public:
862          m_assembler.muld(dest, dest, fpTempRegister);
863      }
864  
865 +    void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
866 +    {
867 +        m_assembler.muld(dest, op1, op2);
868 +    }
869 +
870      void divDouble(FPRegisterID src, FPRegisterID dest)
871      {
872          m_assembler.divd(dest, dest, src);
873      }
874  
875 +    void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
876 +    {
877 +        m_assembler.divd(dest, op1, op2);
878 +    }
879 +
880 +    void divDouble(Address src, FPRegisterID dest)
881 +    {
882 +        loadDouble(src, fpTempRegister);
883 +        m_assembler.divd(dest, dest, fpTempRegister);
884 +    }
885 +
886 +    void negateDouble(FPRegisterID src, FPRegisterID dest)
887 +    {
888 +        m_assembler.negd(dest, src);
889 +    }
890 +
891      void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
892      {
893          m_assembler.mtc1(src, fpTempRegister);
894 @@ -2117,6 +2504,8 @@ public:
895  
896      Jump branchEqual(RegisterID rs, RegisterID rt)
897      {
898 +        m_assembler.nop();
899 +        m_assembler.nop();
900          m_assembler.appendJump();
901          m_assembler.beq(rs, rt, 0);
902          m_assembler.nop();
903 @@ -2126,6 +2515,8 @@ public:
904  
905      Jump branchNotEqual(RegisterID rs, RegisterID rt)
906      {
907 +        m_assembler.nop();
908 +        m_assembler.nop();
909          m_assembler.appendJump();
910          m_assembler.bne(rs, rt, 0);
911          m_assembler.nop();
912 @@ -2192,11 +2583,33 @@ public:
913      // If the result is not representable as a 32 bit value, branch.
914      // May also branch for some values that are representable in 32 bits
915      // (specifically, in this case, INT_MAX 0x7fffffff).
916 -    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
917 +    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
918 +    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
919 +    {
920 +        m_assembler.truncwd(fpTempRegister, src);
921 +        m_assembler.mfc1(dest, fpTempRegister);
922 +        return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff));
923 +    }
924 +
925 +    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
926 +    {
927 +        m_assembler.truncwd(fpTempRegister, src);
928 +        m_assembler.mfc1(dest, fpTempRegister);
929 +        return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0));
930 +    }
931 +
932 +    // Result is undefined if the value is outside of the integer range.
933 +    void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
934 +    {
935 +        m_assembler.truncwd(fpTempRegister, src);
936 +        m_assembler.mfc1(dest, fpTempRegister);
937 +    }
938 +
939 +    // Result is undefined if src > 2^31
940 +    void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
941      {
942          m_assembler.truncwd(fpTempRegister, src);
943          m_assembler.mfc1(dest, fpTempRegister);
944 -        return branch32(Equal, dest, TrustedImm32(0x7fffffff));
945      }
946  
947      // Convert 'src' to an integer, and places the resulting 'dest'.
948 @@ -2218,28 +2631,43 @@ public:
949  
950      Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
951      {
952 -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
953 -        m_assembler.mtc1(MIPSRegisters::zero, scratch);
954 -        m_assembler.mthc1(MIPSRegisters::zero, scratch);
955 -#else
956 -        m_assembler.mtc1(MIPSRegisters::zero, scratch);
957 -        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
958 -#endif
959 +        m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
960          return branchDouble(DoubleNotEqual, reg, scratch);
961      }
962  
963      Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
964      {
965 -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
966 -        m_assembler.mtc1(MIPSRegisters::zero, scratch);
967 -        m_assembler.mthc1(MIPSRegisters::zero, scratch);
968 -#else
969 -        m_assembler.mtc1(MIPSRegisters::zero, scratch);
970 -        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
971 -#endif
972 +        m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
973          return branchDouble(DoubleEqualOrUnordered, reg, scratch);
974      }
975  
976 +    // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
977 +    static RelationalCondition invert(RelationalCondition cond)
978 +    {
979 +        RelationalCondition r;
980 +        if (cond == Equal)
981 +            r = NotEqual;
982 +        else if (cond == NotEqual)
983 +            r = Equal;
984 +        else if (cond == Above)
985 +            r = BelowOrEqual;
986 +        else if (cond == AboveOrEqual)
987 +            r = Below;
988 +        else if (cond == Below)
989 +            r = AboveOrEqual;
990 +        else if (cond == BelowOrEqual)
991 +            r = Above;
992 +        else if (cond == GreaterThan)
993 +            r = LessThanOrEqual;
994 +        else if (cond == GreaterThanOrEqual)
995 +            r = LessThan;
996 +        else if (cond == LessThan)
997 +            r = GreaterThanOrEqual;
998 +        else if (cond == LessThanOrEqual)
999 +            r = GreaterThan;
1000 +        return r;
1001 +    }
1002 +
1003      void nop()
1004      {
1005          m_assembler.nop();
1006 @@ -2252,12 +2680,12 @@ public:
1007  
1008      static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
1009      {
1010 -        RELEASE_ASSERT_NOT_REACHED();
1011 +        MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
1012      }
1013      
1014      static ptrdiff_t maxJumpReplacementSize()
1015      {
1016 -        RELEASE_ASSERT_NOT_REACHED();
1017 +        MIPSAssembler::maxJumpReplacementSize();
1018          return 0;
1019      }
1020  
1021 diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
1022 index fa0f5e0..573d8dc 100644
1023 --- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
1024 +++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
1025 @@ -93,6 +93,23 @@ public:
1026      }
1027  #endif
1028  
1029 +#if CPU(MIPS)
1030 +    ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg)
1031 +    {
1032 +        move(returnAddressRegister, reg);
1033 +    }
1034 +
1035 +    ALWAYS_INLINE void restoreReturnAddressBeforeReturn(RegisterID reg)
1036 +    {
1037 +        move(reg, returnAddressRegister);
1038 +    }
1039 +
1040 +    ALWAYS_INLINE void restoreReturnAddressBeforeReturn(Address address)
1041 +    {
1042 +        loadPtr(address, returnAddressRegister);
1043 +    }
1044 +#endif
1045 +
1046      void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, GPRReg to)
1047      {
1048          loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
1049 @@ -193,7 +210,7 @@ public:
1050          move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
1051          storePtr(TrustedImmPtr(scratchSize), GPRInfo::regT0);
1052  
1053 -#if CPU(X86_64) || CPU(ARM)
1054 +#if CPU(X86_64) || CPU(ARM) || CPU(MIPS)
1055          move(TrustedImmPtr(buffer), GPRInfo::argumentGPR2);
1056          move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
1057          move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1058 diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
1059 index 8adde05..3d99f6f 100644
1060 --- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
1061 +++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h
1062 @@ -576,6 +576,39 @@ public:
1063          poke(GPRInfo::nonArgGPR0);
1064      }
1065  #endif // CPU(ARM_HARDFP)
1066 +#elif CPU(MIPS)
1067 +    ALWAYS_INLINE void setupArguments(FPRReg arg1)
1068 +    {
1069 +        moveDouble(arg1, FPRInfo::argumentFPR0);
1070 +    }
1071 +
1072 +    ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2)
1073 +    {
1074 +        if (arg2 != FPRInfo::argumentFPR0) {
1075 +            moveDouble(arg1, FPRInfo::argumentFPR0);
1076 +            moveDouble(arg2, FPRInfo::argumentFPR1);
1077 +        } else if (arg1 != FPRInfo::argumentFPR1) {
1078 +            moveDouble(arg2, FPRInfo::argumentFPR1);
1079 +            moveDouble(arg1, FPRInfo::argumentFPR0);
1080 +        } else {
1081 +            // Swap arg1, arg2.
1082 +            swapDouble(FPRInfo::argumentFPR0, FPRInfo::argumentFPR1);
1083 +        }
1084 +    }
1085 +
1086 +    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2)
1087 +    {
1088 +        assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1);
1089 +        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1090 +        poke(arg2, 4);
1091 +    }
1092 +
1093 +    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
1094 +    {
1095 +        setupStubArguments(arg1, arg2);
1096 +        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1097 +        poke(arg3, 4);
1098 +    }
1099  #else
1100  #error "DFG JIT not supported on this platform."
1101  #endif
1102 @@ -803,119 +836,126 @@ public:
1103      // These methods are suitable for any calling convention that provides for
1104      // exactly 4 argument registers, e.g. ARMv7.
1105  #if NUMBER_OF_ARGUMENT_REGISTERS == 4
1106 +
1107 +#if CPU(MIPS)
1108 +#define POKE_ARGUMENT_OFFSET 4
1109 +#else
1110 +#define POKE_ARGUMENT_OFFSET 0
1111 +#endif
1112 +
1113      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
1114      {
1115 -        poke(arg4);
1116 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1117          setupArgumentsWithExecState(arg1, arg2, arg3);
1118      }
1119  
1120      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4)
1121      {
1122 -        poke(arg4);
1123 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1124          setupArgumentsWithExecState(arg1, arg2, arg3);
1125      }
1126  
1127      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4)
1128      {
1129 -        poke(arg4);
1130 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1131          setupArgumentsWithExecState(arg1, arg2, arg3);
1132      }
1133  
1134      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
1135      {
1136 -        poke(arg5, 1);
1137 -        poke(arg4);
1138 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1139 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1140          setupArgumentsWithExecState(arg1, arg2, arg3);
1141      }
1142  
1143      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4)
1144      {
1145 -        poke(arg4);
1146 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1147          setupArgumentsWithExecState(arg1, arg2, arg3);
1148      }
1149  
1150      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4)
1151      {
1152 -        poke(arg4);
1153 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1154          setupArgumentsWithExecState(arg1, arg2, arg3);
1155      }
1156  
1157      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
1158      {
1159 -        poke(arg4);
1160 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1161          setupArgumentsWithExecState(arg1, arg2, arg3);
1162      }
1163  
1164      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
1165      {
1166 -        poke(arg5, 1);
1167 -        poke(arg4);
1168 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1169 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1170          setupArgumentsWithExecState(arg1, arg2, arg3);
1171      }
1172  
1173      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4)
1174      {
1175 -        poke(arg4);
1176 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1177          setupArgumentsWithExecState(arg1, arg2, arg3);
1178      }
1179  
1180      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4)
1181      {
1182 -        poke(arg4);
1183 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1184          setupArgumentsWithExecState(arg1, arg2, arg3);
1185      }
1186  
1187      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImmPtr arg4)
1188      {
1189 -        poke(arg4);
1190 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1191          setupArgumentsWithExecState(arg1, arg2, arg3);
1192      }
1193  
1194      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
1195      {
1196 -        poke(arg4);
1197 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1198          setupArgumentsWithExecState(arg1, arg2, arg3);
1199      }
1200  
1201      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
1202      {
1203 -        poke(arg5, 1);
1204 -        poke(arg4);
1205 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1206 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1207          setupArgumentsWithExecState(arg1, arg2, arg3);
1208      }
1209  
1210      ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, TrustedImm32 arg5)
1211      {
1212 -        poke(arg5, 1);
1213 -        poke(arg4);
1214 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1215 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1216          setupArgumentsWithExecState(arg1, arg2, arg3);
1217      }
1218  
1219      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5)
1220      {
1221 -        poke(arg5, 1);
1222 -        poke(arg4);
1223 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1224 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1225          setupArgumentsWithExecState(arg1, arg2, arg3);
1226      }
1227  
1228      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, TrustedImm32 arg5)
1229      {
1230 -        poke(arg5, 1);
1231 -        poke(arg4);
1232 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1233 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1234          setupArgumentsWithExecState(arg1, arg2, arg3);
1235      }
1236  
1237      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
1238      {
1239 -        poke(arg5, 1);
1240 -        poke(arg4);
1241 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1242 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1243          setupArgumentsWithExecState(arg1, arg2, arg3);
1244      }
1245  
1246      ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5)
1247      {
1248 -        poke(arg5, 1);
1249 -        poke(arg4);
1250 +        poke(arg5, POKE_ARGUMENT_OFFSET + 1);
1251 +        poke(arg4, POKE_ARGUMENT_OFFSET);
1252          setupArgumentsWithExecState(arg1, arg2, arg3);
1253      }
1254  
1255 diff --git a/Source/JavaScriptCore/dfg/DFGFPRInfo.h b/Source/JavaScriptCore/dfg/DFGFPRInfo.h
1256 index 17aaa7d..e18ec06 100644
1257 --- a/Source/JavaScriptCore/dfg/DFGFPRInfo.h
1258 +++ b/Source/JavaScriptCore/dfg/DFGFPRInfo.h
1259 @@ -164,6 +164,74 @@ public:
1260  
1261  #endif
1262  
1263 +#if CPU(MIPS)
1264 +
1265 +class FPRInfo {
1266 +public:
1267 +    typedef FPRReg RegisterType;
1268 +    static const unsigned numberOfRegisters = 6;
1269 +
1270 +    // Temporary registers.
1271 +    static const FPRReg fpRegT0 = MIPSRegisters::f0;
1272 +    static const FPRReg fpRegT1 = MIPSRegisters::f4;
1273 +    static const FPRReg fpRegT2 = MIPSRegisters::f6;
1274 +    static const FPRReg fpRegT3 = MIPSRegisters::f8;
1275 +    static const FPRReg fpRegT4 = MIPSRegisters::f10;
1276 +    static const FPRReg fpRegT5 = MIPSRegisters::f18;
1277 +
1278 +    static const FPRReg returnValueFPR = MIPSRegisters::f0;
1279 +
1280 +    static const FPRReg argumentFPR0 = MIPSRegisters::f12;
1281 +    static const FPRReg argumentFPR1 = MIPSRegisters::f14;
1282 +
1283 +    static FPRReg toRegister(unsigned index)
1284 +    {
1285 +        static const FPRReg registerForIndex[numberOfRegisters] = {
1286 +            fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 };
1287 +
1288 +        ASSERT(index < numberOfRegisters);
1289 +        return registerForIndex[index];
1290 +    }
1291 +
1292 +    static unsigned toIndex(FPRReg reg)
1293 +    {
1294 +        ASSERT(reg != InvalidFPRReg);
1295 +        ASSERT(reg < 20);
1296 +        static const unsigned indexForRegister[20] = {
1297 +            0, InvalidIndex, InvalidIndex, InvalidIndex,
1298 +            1, InvalidIndex, 2, InvalidIndex,
1299 +            3, InvalidIndex, 4, InvalidIndex,
1300 +            InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
1301 +            InvalidIndex, InvalidIndex, 5, InvalidIndex,
1302 +        };
1303 +        unsigned result = indexForRegister[reg];
1304 +        ASSERT(result != InvalidIndex);
1305 +        return result;
1306 +    }
1307 +
1308 +    static const char* debugName(FPRReg reg)
1309 +    {
1310 +        ASSERT(reg != InvalidFPRReg);
1311 +        ASSERT(reg < 32);
1312 +        static const char* nameForRegister[32] = {
1313 +            "f0", "f1", "f2", "f3",
1314 +            "f4", "f5", "f6", "f7",
1315 +            "f8", "f9", "f10", "f11",
1316 +            "f12", "f13", "f14", "f15"
1317 +            "f16", "f17", "f18", "f19"
1318 +            "f20", "f21", "f22", "f23"
1319 +            "f24", "f25", "f26", "f27"
1320 +            "f28", "f29", "f30", "f31"
1321 +        };
1322 +        return nameForRegister[reg];
1323 +    }
1324 +private:
1325 +
1326 +    static const unsigned InvalidIndex = 0xffffffff;
1327 +};
1328 +
1329 +#endif
1330 +
1331  typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
1332  
1333  } } // namespace JSC::DFG
1334 diff --git a/Source/JavaScriptCore/dfg/DFGGPRInfo.h b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
1335 index 3d07556..aa634cd 100644
1336 --- a/Source/JavaScriptCore/dfg/DFGGPRInfo.h
1337 +++ b/Source/JavaScriptCore/dfg/DFGGPRInfo.h
1338 @@ -461,6 +461,73 @@ private:
1339  
1340  #endif
1341  
1342 +#if CPU(MIPS)
1343 +#define NUMBER_OF_ARGUMENT_REGISTERS 4
1344 +
1345 +class GPRInfo {
1346 +public:
1347 +    typedef GPRReg RegisterType;
1348 +    static const unsigned numberOfRegisters = 6;
1349 +
1350 +    // Temporary registers.
1351 +    static const GPRReg regT0 = MIPSRegisters::v0;
1352 +    static const GPRReg regT1 = MIPSRegisters::v1;
1353 +    static const GPRReg regT2 = MIPSRegisters::t4;
1354 +    static const GPRReg regT3 = MIPSRegisters::t5;
1355 +    static const GPRReg regT4 = MIPSRegisters::t6;
1356 +    static const GPRReg regT5 = MIPSRegisters::t7;
1357 +    // These registers match the baseline JIT.
1358 +    static const GPRReg cachedResultRegister = regT0;
1359 +    static const GPRReg cachedResultRegister2 = regT1;
1360 +    static const GPRReg callFrameRegister = MIPSRegisters::s0;
1361 +    // These constants provide the names for the general purpose argument & return value registers.
1362 +    static const GPRReg argumentGPR0 = MIPSRegisters::a0;
1363 +    static const GPRReg argumentGPR1 = MIPSRegisters::a1;
1364 +    static const GPRReg argumentGPR2 = MIPSRegisters::a2;
1365 +    static const GPRReg argumentGPR3 = MIPSRegisters::a3;
1366 +    static const GPRReg nonArgGPR0 = regT2;
1367 +    static const GPRReg nonArgGPR1 = regT3;
1368 +    static const GPRReg nonArgGPR2 = regT4;
1369 +    static const GPRReg returnValueGPR = regT0;
1370 +    static const GPRReg returnValueGPR2 = regT1;
1371 +    static const GPRReg nonPreservedNonReturnGPR = regT5;
1372 +
1373 +    static GPRReg toRegister(unsigned index)
1374 +    {
1375 +        ASSERT(index < numberOfRegisters);
1376 +        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5 };
1377 +        return registerForIndex[index];
1378 +    }
1379 +
1380 +    static unsigned toIndex(GPRReg reg)
1381 +    {
1382 +        ASSERT(reg != InvalidGPRReg);
1383 +        ASSERT(reg < 16);
1384 +        static const unsigned indexForRegister[16] = { InvalidIndex, InvalidIndex, 0, 1, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, 2, 3, 4, 5 };
1385 +        unsigned result = indexForRegister[reg];
1386 +        ASSERT(result != InvalidIndex);
1387 +        return result;
1388 +    }
1389 +
1390 +    static const char* debugName(GPRReg reg)
1391 +    {
1392 +        ASSERT(reg != InvalidGPRReg);
1393 +        ASSERT(reg < 16);
1394 +        static const char* nameForRegister[16] = {
1395 +            "zero", "at", "v0", "v1",
1396 +            "a0", "a1", "a2", "a3",
1397 +            "t0", "t1", "t2", "t3",
1398 +            "t4", "t5", "t6", "t7"
1399 +        };
1400 +        return nameForRegister[reg];
1401 +    }
1402 +private:
1403 +
1404 +    static const unsigned InvalidIndex = 0xffffffff;
1405 +};
1406 +
1407 +#endif
1408 +
1409  typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
1410  
1411  } } // namespace JSC::DFG
1412 diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
1413 index ea33f38..247274b 100644
1414 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
1415 +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
1416 @@ -1241,7 +1241,7 @@ public:
1417  
1418  // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
1419  // To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary.
1420 -#if COMPILER_SUPPORTS(EABI) && CPU(ARM)
1421 +#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS)
1422  #define EABI_32BIT_DUMMY_ARG      TrustedImm32(0),
1423  #else
1424  #define EABI_32BIT_DUMMY_ARG
1425 @@ -1691,7 +1691,7 @@ public:
1426      }
1427  #endif
1428      
1429 -#if !defined(NDEBUG) && !CPU(ARM)
1430 +#if !defined(NDEBUG) && !CPU(ARM) && !CPU(MIPS)
1431      void prepareForExternalCall()
1432      {
1433          // We're about to call out to a "native" helper function. The helper
1434 diff --git a/Source/JavaScriptCore/jit/JSInterfaceJIT.h b/Source/JavaScriptCore/jit/JSInterfaceJIT.h
1435 index 7fdeaf0..48ad6b2 100644
1436 --- a/Source/JavaScriptCore/jit/JSInterfaceJIT.h
1437 +++ b/Source/JavaScriptCore/jit/JSInterfaceJIT.h
1438 @@ -125,6 +125,10 @@ namespace JSC {
1439          static const RegisterID cachedResultRegister = MIPSRegisters::v0;
1440          static const RegisterID firstArgumentRegister = MIPSRegisters::a0;
1441          
1442 +#if ENABLE(VALUE_PROFILER)
1443 +        static const RegisterID bucketCounterRegister = MIPSRegisters::s3;
1444 +#endif
1445 +
1446          // regT0 must be v0 for returning a 32-bit value.
1447          static const RegisterID regT0 = MIPSRegisters::v0;
1448          
1449 diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
1450 index 5d47ab9..c02f336 100644
1451 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h
1452 +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
1453 @@ -141,14 +141,18 @@ namespace JSC {
1454              return result;
1455          }
1456  
1457 -        static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; }
1458 +        static size_t allocationSize(size_t bufferSize) { return sizeof(ScratchBuffer) + bufferSize; }
1459          void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
1460          size_t activeLength() const { return m_activeLength; };
1461          size_t* activeLengthPtr() { return &m_activeLength; };
1462          void* dataBuffer() { return m_buffer; }
1463  
1464          size_t m_activeLength;
1465 +#if CPU(MIPS) && (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == 2)
1466 +        void* m_buffer[0] __attribute__((aligned(8)));
1467 +#else
1468          void* m_buffer[0];
1469 +#endif
1470      };
1471  #if COMPILER(MSVC)
1472  #pragma warning(pop)
1473 diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h
1474 index 1698247..2d90359 100644
1475 --- a/Source/WTF/wtf/Platform.h
1476 +++ b/Source/WTF/wtf/Platform.h
1477 @@ -818,6 +818,10 @@
1478  #if CPU(ARM_TRADITIONAL)
1479  #define ENABLE_DFG_JIT 1
1480  #endif
1481 +/* Enable the DFG JIT on MIPS. */
1482 +#if CPU(MIPS)
1483 +#define ENABLE_DFG_JIT 1
1484 +#endif
1485  #endif
1486  
1487  /* If the jit is not available, enable the LLInt C Loop: */
1488 -- 
1489 1.8.3.2
1490