2  * Copyright (C) 2009 Apple Inc. All rights reserved. 
   3  * Copyright (C) 2009 University of Szeged 
   5  * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved. 
   7  * Redistribution and use in source and binary forms, with or without 
   8  * modification, are permitted provided that the following conditions 
  10  * 1. Redistributions of source code must retain the above copyright 
  11  *    notice, this list of conditions and the following disclaimer. 
  12  * 2. Redistributions in binary form must reproduce the above copyright 
  13  *    notice, this list of conditions and the following disclaimer in the 
  14  *    documentation and/or other materials provided with the distribution. 
  16  * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY 
  17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR 
  20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
  21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
  22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
  23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
  24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
  25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
  26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  29 #ifndef MIPSAssembler_h 
  30 #define MIPSAssembler_h 
  32 #if ENABLE(ASSEMBLER) && CPU(MIPS) 
  34 #include "AssemblerBuffer.h" 
  35 #include "JITCompilationEffort.h" 
  36 #include <wtf/Assertions.h> 
  37 #include <wtf/SegmentedVector.h> 
  41 typedef uint32_t MIPSWord
; 
  43 namespace MIPSRegisters 
{ 
 146 } // namespace MIPSRegisters 
 148 class MIPSAssembler 
{ 
 150     typedef MIPSRegisters::RegisterID RegisterID
; 
 151     typedef MIPSRegisters::FPRegisterID FPRegisterID
; 
 152     typedef SegmentedVector
<AssemblerLabel
, 64> Jumps
; 
 154     static RegisterID 
firstRegister() { return MIPSRegisters::r0
; } 
 155     static RegisterID 
lastRegister() { return MIPSRegisters::r31
; } 
 157     static FPRegisterID 
firstFPRegister() { return MIPSRegisters::f0
; } 
 158     static FPRegisterID 
lastFPRegister() { return MIPSRegisters::f31
; } 
 161         : m_indexOfLastWatchpoint(INT_MIN
) 
 162         , m_indexOfTailOfLastWatchpoint(INT_MIN
) 
 166     AssemblerBuffer
& buffer() { return m_buffer
; } 
 168     // MIPS instruction opcode field position 
 180     void emitInst(MIPSWord op
) 
 182         void* oldBase 
= m_buffer
.data(); 
 186         void* newBase 
= m_buffer
.data(); 
 187         if (oldBase 
!= newBase
) 
 188             relocateJumps(oldBase
, newBase
); 
 193         emitInst(0x00000000); 
 198         emitInst(0x0000000f); 
 201     /* Need to insert one load data delay nop for mips1.  */ 
 209     /* Need to insert one coprocessor access delay nop for mips1.  */ 
 217     void move(RegisterID rd
, RegisterID rs
) 
 220         emitInst(0x00000021 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
)); 
 223     /* Set an immediate value to a register.  This may generate 1 or 2 
 225     void li(RegisterID dest
, int imm
) 
 227         if (imm 
>= -32768 && imm 
<= 32767) 
 228             addiu(dest
, MIPSRegisters::zero
, imm
); 
 229         else if (imm 
>= 0 && imm 
< 65536) 
 230             ori(dest
, MIPSRegisters::zero
, imm
); 
 232             lui(dest
, imm 
>> 16); 
 234                 ori(dest
, dest
, imm
); 
 238     void lui(RegisterID rt
, int imm
) 
 240         emitInst(0x3c000000 | (rt 
<< OP_SH_RT
) | (imm 
& 0xffff)); 
 243     void addiu(RegisterID rt
, RegisterID rs
, int imm
) 
 245         emitInst(0x24000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 248     void addu(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 250         emitInst(0x00000021 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 253     void subu(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 255         emitInst(0x00000023 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 258     void mult(RegisterID rs
, RegisterID rt
) 
 260         emitInst(0x00000018 | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 263     void div(RegisterID rs
, RegisterID rt
) 
 265         emitInst(0x0000001a | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 268     void mfhi(RegisterID rd
) 
 270         emitInst(0x00000010 | (rd 
<< OP_SH_RD
)); 
 273     void mflo(RegisterID rd
) 
 275         emitInst(0x00000012 | (rd 
<< OP_SH_RD
)); 
 278     void mul(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 280 #if WTF_MIPS_ISA_AT_LEAST(32)  
 281         emitInst(0x70000002 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 288     void andInsn(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 290         emitInst(0x00000024 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 293     void andi(RegisterID rt
, RegisterID rs
, int imm
) 
 295         emitInst(0x30000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 298     void nor(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 300         emitInst(0x00000027 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 303     void orInsn(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 305         emitInst(0x00000025 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 308     void ori(RegisterID rt
, RegisterID rs
, int imm
) 
 310         emitInst(0x34000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 313     void xorInsn(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 315         emitInst(0x00000026 | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 318     void xori(RegisterID rt
, RegisterID rs
, int imm
) 
 320         emitInst(0x38000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 323     void slt(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 325         emitInst(0x0000002a | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 328     void sltu(RegisterID rd
, RegisterID rs
, RegisterID rt
) 
 330         emitInst(0x0000002b | (rd 
<< OP_SH_RD
) | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
)); 
 333     void sltiu(RegisterID rt
, RegisterID rs
, int imm
) 
 335         emitInst(0x2c000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 338     void sll(RegisterID rd
, RegisterID rt
, int shamt
) 
 340         emitInst(0x00000000 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | ((shamt 
& 0x1f) << OP_SH_SHAMT
)); 
 343     void sllv(RegisterID rd
, RegisterID rt
, RegisterID rs
) 
 345         emitInst(0x00000004 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
)); 
 348     void sra(RegisterID rd
, RegisterID rt
, int shamt
) 
 350         emitInst(0x00000003 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | ((shamt 
& 0x1f) << OP_SH_SHAMT
)); 
 353     void srav(RegisterID rd
, RegisterID rt
, RegisterID rs
) 
 355         emitInst(0x00000007 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
)); 
 358     void srl(RegisterID rd
, RegisterID rt
, int shamt
) 
 360         emitInst(0x00000002 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | ((shamt 
& 0x1f) << OP_SH_SHAMT
)); 
 363     void srlv(RegisterID rd
, RegisterID rt
, RegisterID rs
) 
 365         emitInst(0x00000006 | (rd 
<< OP_SH_RD
) | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
)); 
 368     void lb(RegisterID rt
, RegisterID rs
, int offset
) 
 370         emitInst(0x80000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 374     void lbu(RegisterID rt
, RegisterID rs
, int offset
) 
 376         emitInst(0x90000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 380     void lw(RegisterID rt
, RegisterID rs
, int offset
) 
 382         emitInst(0x8c000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 386     void lwl(RegisterID rt
, RegisterID rs
, int offset
) 
 388         emitInst(0x88000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 392     void lwr(RegisterID rt
, RegisterID rs
, int offset
) 
 394         emitInst(0x98000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 398     void lh(RegisterID rt
, RegisterID rs
, int offset
) 
 400         emitInst(0x84000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 404     void lhu(RegisterID rt
, RegisterID rs
, int offset
) 
 406         emitInst(0x94000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 410     void sb(RegisterID rt
, RegisterID rs
, int offset
) 
 412         emitInst(0xa0000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 415     void sh(RegisterID rt
, RegisterID rs
, int offset
) 
 417         emitInst(0xa4000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 420     void sw(RegisterID rt
, RegisterID rs
, int offset
) 
 422         emitInst(0xac000000 | (rt 
<< OP_SH_RT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 425     void jr(RegisterID rs
) 
 427         emitInst(0x00000008 | (rs 
<< OP_SH_RS
)); 
 430     void jalr(RegisterID rs
) 
 432         emitInst(0x0000f809 | (rs 
<< OP_SH_RS
)); 
 437         emitInst(0x0c000000); 
 442         int value 
= 512; /* BRK_BUG */ 
 443         emitInst(0x0000000d | ((value 
& 0x3ff) << OP_SH_CODE
)); 
 446     void bgez(RegisterID rs
, int imm
) 
 448         emitInst(0x04010000 | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 451     void bltz(RegisterID rs
, int imm
) 
 453         emitInst(0x04000000 | (rs 
<< OP_SH_RS
) | (imm 
& 0xffff)); 
 456     void beq(RegisterID rs
, RegisterID rt
, int imm
) 
 458         emitInst(0x10000000 | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
) | (imm 
& 0xffff)); 
 461     void bne(RegisterID rs
, RegisterID rt
, int imm
) 
 463         emitInst(0x14000000 | (rs 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
) | (imm 
& 0xffff)); 
 468         emitInst(0x45010000); 
 473         emitInst(0x45000000); 
 478         m_jumps
.append(m_buffer
.label()); 
 481     void addd(FPRegisterID fd
, FPRegisterID fs
, FPRegisterID ft
) 
 483         emitInst(0x46200000 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 486     void subd(FPRegisterID fd
, FPRegisterID fs
, FPRegisterID ft
) 
 488         emitInst(0x46200001 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 491     void muld(FPRegisterID fd
, FPRegisterID fs
, FPRegisterID ft
) 
 493         emitInst(0x46200002 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 496     void divd(FPRegisterID fd
, FPRegisterID fs
, FPRegisterID ft
) 
 498         emitInst(0x46200003 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 501     void lwc1(FPRegisterID ft
, RegisterID rs
, int offset
) 
 503         emitInst(0xc4000000 | (ft 
<< OP_SH_FT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 507     void ldc1(FPRegisterID ft
, RegisterID rs
, int offset
) 
 509         emitInst(0xd4000000 | (ft 
<< OP_SH_FT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 512     void swc1(FPRegisterID ft
, RegisterID rs
, int offset
) 
 514         emitInst(0xe4000000 | (ft 
<< OP_SH_FT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 517     void sdc1(FPRegisterID ft
, RegisterID rs
, int offset
) 
 519         emitInst(0xf4000000 | (ft 
<< OP_SH_FT
) | (rs 
<< OP_SH_RS
) | (offset 
& 0xffff)); 
 522     void mtc1(RegisterID rt
, FPRegisterID fs
) 
 524         emitInst(0x44800000 | (fs 
<< OP_SH_FS
) | (rt 
<< OP_SH_RT
)); 
 528     void mthc1(RegisterID rt
, FPRegisterID fs
) 
 530         emitInst(0x44e00000 | (fs 
<< OP_SH_FS
) | (rt 
<< OP_SH_RT
)); 
 534     void mfc1(RegisterID rt
, FPRegisterID fs
) 
 536         emitInst(0x44000000 | (fs 
<< OP_SH_FS
) | (rt 
<< OP_SH_RT
)); 
 540     void sqrtd(FPRegisterID fd
, FPRegisterID fs
) 
 542         emitInst(0x46200004 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 545     void movd(FPRegisterID fd
, FPRegisterID fs
) 
 547         emitInst(0x46200006 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 550     void negd(FPRegisterID fd
, FPRegisterID fs
) 
 552         emitInst(0x46200007 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 555     void truncwd(FPRegisterID fd
, FPRegisterID fs
) 
 557         emitInst(0x4620000d | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 560     void cvtdw(FPRegisterID fd
, FPRegisterID fs
) 
 562         emitInst(0x46800021 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 565     void cvtds(FPRegisterID fd
, FPRegisterID fs
) 
 567         emitInst(0x46000021 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 570     void cvtwd(FPRegisterID fd
, FPRegisterID fs
) 
 572         emitInst(0x46200024 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 575     void cvtsd(FPRegisterID fd
, FPRegisterID fs
) 
 577         emitInst(0x46200020 | (fd 
<< OP_SH_FD
) | (fs 
<< OP_SH_FS
)); 
 580     void ceqd(FPRegisterID fs
, FPRegisterID ft
) 
 582         emitInst(0x46200032 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 586     void cngtd(FPRegisterID fs
, FPRegisterID ft
) 
 588         emitInst(0x4620003f | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 592     void cnged(FPRegisterID fs
, FPRegisterID ft
) 
 594         emitInst(0x4620003d | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 598     void cltd(FPRegisterID fs
, FPRegisterID ft
) 
 600         emitInst(0x4620003c | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 604     void cled(FPRegisterID fs
, FPRegisterID ft
) 
 606         emitInst(0x4620003e | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 610     void cueqd(FPRegisterID fs
, FPRegisterID ft
) 
 612         emitInst(0x46200033 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 616     void coled(FPRegisterID fs
, FPRegisterID ft
) 
 618         emitInst(0x46200036 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 622     void coltd(FPRegisterID fs
, FPRegisterID ft
) 
 624         emitInst(0x46200034 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 628     void culed(FPRegisterID fs
, FPRegisterID ft
) 
 630         emitInst(0x46200037 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 634     void cultd(FPRegisterID fs
, FPRegisterID ft
) 
 636         emitInst(0x46200035 | (fs 
<< OP_SH_FS
) | (ft 
<< OP_SH_FT
)); 
 642     AssemblerLabel 
labelIgnoringWatchpoints() 
 644         return m_buffer
.label(); 
 647     AssemblerLabel 
labelForWatchpoint() 
 649         AssemblerLabel result 
= m_buffer
.label(); 
 650         if (static_cast<int>(result
.m_offset
) != m_indexOfLastWatchpoint
) 
 652         m_indexOfLastWatchpoint 
= result
.m_offset
; 
 653         m_indexOfTailOfLastWatchpoint 
= result
.m_offset 
+ maxJumpReplacementSize(); 
 657     AssemblerLabel 
label() 
 659         AssemblerLabel result 
= m_buffer
.label(); 
 660         while (UNLIKELY(static_cast<int>(result
.m_offset
) < m_indexOfTailOfLastWatchpoint
)) { 
 662             result 
= m_buffer
.label(); 
 667     AssemblerLabel 
align(int alignment
) 
 669         while (!m_buffer
.isAligned(alignment
)) 
 675     static void* getRelocatedAddress(void* code
, AssemblerLabel label
) 
 677         return reinterpret_cast<void*>(reinterpret_cast<char*>(code
) + label
.m_offset
); 
 680     static int getDifferenceBetweenLabels(AssemblerLabel a
, AssemblerLabel b
) 
 682         return b
.m_offset 
- a
.m_offset
; 
 685     // Assembler admin methods: 
 687     size_t codeSize() const 
 689         return m_buffer
.codeSize(); 
 692     unsigned debugOffset() { return m_buffer
.debugOffset(); } 
 694     // Assembly helpers for moving data between fp and registers. 
 695     void vmov(RegisterID rd1
, RegisterID rd2
, FPRegisterID rn
) 
 697 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 
 702         mfc1(rd2
, FPRegisterID(rn 
+ 1)); 
 706     void vmov(FPRegisterID rd
, RegisterID rn1
, RegisterID rn2
) 
 708 #if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 
 713         mtc1(rn2
, FPRegisterID(rd 
+ 1)); 
 717     static unsigned getCallReturnOffset(AssemblerLabel call
) 
 719         // The return address is after a call and a delay slot instruction 
 720         return call
.m_offset
; 
 723     // Linking & patching: 
 725     // 'link' and 'patch' methods are for use on unprotected code - such as the code 
 726     // within the AssemblerBuffer, and code being patched by the patch buffer. Once 
 727     // code has been finalized it is (platform support permitting) within a non- 
 728     // writable region of memory; to modify the code in an execute-only execuable 
 729     // pool the 'repatch' and 'relink' methods should be used. 
 731     static size_t linkDirectJump(void* code
, void* to
) 
 733         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(code
)); 
 735         int32_t slotAddr 
= reinterpret_cast<int>(insn
) + 4; 
 736         int32_t toAddr 
= reinterpret_cast<int>(to
); 
 738         if ((slotAddr 
& 0xf0000000) != (toAddr 
& 0xf0000000)) { 
 740             *insn 
= 0x3c000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | ((toAddr 
>> 16) & 0xffff); 
 743             *insn 
= 0x34000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | (MIPSRegisters::t9 
<< OP_SH_RS
) | (toAddr 
& 0xffff); 
 746             *insn 
= 0x00000008 | (MIPSRegisters::t9 
<< OP_SH_RS
); 
 748             ops 
= 4 * sizeof(MIPSWord
); 
 751             *insn 
= 0x08000000 | ((toAddr 
& 0x0fffffff) >> 2); 
 753             ops 
= 2 * sizeof(MIPSWord
); 
 760     void linkJump(AssemblerLabel from
, AssemblerLabel to
) 
 763         ASSERT(from
.isSet()); 
 764         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(m_buffer
.data()) + from
.m_offset
); 
 765         MIPSWord
* toPos 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(m_buffer
.data()) + to
.m_offset
); 
 767         ASSERT(!(*(insn 
- 1)) && !(*(insn 
- 2)) && !(*(insn 
- 3)) && !(*(insn 
- 5))); 
 769         linkWithOffset(insn
, toPos
); 
 772     static void linkJump(void* code
, AssemblerLabel from
, void* to
) 
 774         ASSERT(from
.isSet()); 
 775         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(code
) + from
.m_offset
); 
 777         ASSERT(!(*(insn 
- 1)) && !(*(insn 
- 2)) && !(*(insn 
- 3)) && !(*(insn 
- 5))); 
 779         linkWithOffset(insn
, to
); 
 782     static void linkCall(void* code
, AssemblerLabel from
, void* to
) 
 784         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(code
) + from
.m_offset
); 
 785         linkCallInternal(insn
, to
); 
 788     static void linkPointer(void* code
, AssemblerLabel from
, void* to
) 
 790         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(code
) + from
.m_offset
); 
 791         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 792         *insn 
= (*insn 
& 0xffff0000) | ((reinterpret_cast<intptr_t>(to
) >> 16) & 0xffff); 
 794         ASSERT((*insn 
& 0xfc000000) == 0x34000000); // ori 
 795         *insn 
= (*insn 
& 0xffff0000) | (reinterpret_cast<intptr_t>(to
) & 0xffff); 
 798     static void relinkJump(void* from
, void* to
) 
 800         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(from
); 
 802         ASSERT(!(*(insn 
- 1)) && !(*(insn 
- 5))); 
 804         int flushSize 
= linkWithOffset(insn
, to
); 
 806         cacheFlush(insn
, flushSize
); 
 809     static void relinkCall(void* from
, void* to
) 
 812         int size 
= linkCallInternal(from
, to
); 
 813         if (size 
== sizeof(MIPSWord
)) 
 814             start 
= reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from
) - 2 * sizeof(MIPSWord
)); 
 816             start 
= reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from
) - 4 * sizeof(MIPSWord
)); 
 818         cacheFlush(start
, size
); 
 821     static void repatchInt32(void* from
, int32_t to
) 
 823         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(from
); 
 824         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 825         *insn 
= (*insn 
& 0xffff0000) | ((to 
>> 16) & 0xffff); 
 827         ASSERT((*insn 
& 0xfc000000) == 0x34000000); // ori 
 828         *insn 
= (*insn 
& 0xffff0000) | (to 
& 0xffff); 
 830         cacheFlush(insn
, 2 * sizeof(MIPSWord
)); 
 833     static int32_t readInt32(void* from
) 
 835         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(from
); 
 836         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 837         int32_t result 
= (*insn 
& 0x0000ffff) << 16; 
 839         ASSERT((*insn 
& 0xfc000000) == 0x34000000); // ori 
 840         result 
|= *insn 
& 0x0000ffff; 
 844     static void repatchCompact(void* where
, int32_t value
) 
 846         repatchInt32(where
, value
); 
 849     static void repatchPointer(void* from
, void* to
) 
 851         repatchInt32(from
, reinterpret_cast<int32_t>(to
)); 
 854     static void* readPointer(void* from
) 
 856         return reinterpret_cast<void*>(readInt32(from
)); 
 859     static void* readCallTarget(void* from
) 
 861         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(from
); 
 863         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 864         int32_t result 
= (*insn 
& 0x0000ffff) << 16; 
 866         ASSERT((*insn 
& 0xfc000000) == 0x34000000); // ori 
 867         result 
|= *insn 
& 0x0000ffff; 
 868         return reinterpret_cast<void*>(result
); 
 871     static void cacheFlush(void* code
, size_t size
) 
 873         intptr_t end 
= reinterpret_cast<intptr_t>(code
) + size
; 
 874         __builtin___clear_cache(reinterpret_cast<char*>(code
), reinterpret_cast<char*>(end
)); 
 877     static ptrdiff_t maxJumpReplacementSize() 
 879         return sizeof(MIPSWord
) * 4; 
 882     static void revertJumpToMove(void* instructionStart
, RegisterID rt
, int imm
) 
 884         MIPSWord
* insn 
= static_cast<MIPSWord
*>(instructionStart
); 
 885         size_t codeSize 
= 2 * sizeof(MIPSWord
); 
 888         *insn 
= 0x3c000000 | (rt 
<< OP_SH_RT
) | ((imm 
>> 16) & 0xffff); 
 891         *insn 
= 0x34000000 | (rt 
<< OP_SH_RS
) | (rt 
<< OP_SH_RT
) | (imm 
& 0xffff); 
 894         if (*insn 
== 0x03200008) { 
 896             codeSize 
+= sizeof(MIPSWord
); 
 898         cacheFlush(insn
, codeSize
); 
 901     static void replaceWithJump(void* instructionStart
, void* to
) 
 903         ASSERT(!(bitwise_cast
<uintptr_t>(instructionStart
) & 3)); 
 904         ASSERT(!(bitwise_cast
<uintptr_t>(to
) & 3)); 
 905         size_t ops 
= linkDirectJump(instructionStart
, to
); 
 906         cacheFlush(instructionStart
, ops
); 
 909     static void replaceWithLoad(void* instructionStart
) 
 911         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(instructionStart
); 
 912         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 914         ASSERT((*insn 
& 0xfc0007ff) == 0x00000021); // addu 
 916         *insn 
= 0x8c000000 | ((*insn
) & 0x3ffffff); // lw 
 920     static void replaceWithAddressComputation(void* instructionStart
) 
 922         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(instructionStart
); 
 923         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
 925         ASSERT((*insn 
& 0xfc0007ff) == 0x00000021); // addu 
 927         *insn 
= 0x24000000 | ((*insn
) & 0x3ffffff); // addiu 
 931     /* Update each jump in the buffer of newBase.  */ 
 932     void relocateJumps(void* oldBase
, void* newBase
) 
 935         for (Jumps::Iterator iter 
= m_jumps
.begin(); iter 
!= m_jumps
.end(); ++iter
) { 
 936             int pos 
= iter
->m_offset
; 
 937             MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(reinterpret_cast<intptr_t>(newBase
) + pos
); 
 939             // Need to make sure we have 5 valid instructions after pos 
 940             if ((unsigned)pos 
>= m_buffer
.codeSize() - 5 * sizeof(MIPSWord
)) 
 943             if ((*insn 
& 0xfc000000) == 0x08000000) { // j 
 944                 int offset 
= *insn 
& 0x03ffffff; 
 945                 int oldInsnAddress 
= (int)insn 
- (int)newBase 
+ (int)oldBase
; 
 946                 int topFourBits 
= (oldInsnAddress 
+ 4) >> 28; 
 947                 int oldTargetAddress 
= (topFourBits 
<< 28) | (offset 
<< 2); 
 948                 int newTargetAddress 
= oldTargetAddress 
- (int)oldBase 
+ (int)newBase
; 
 949                 int newInsnAddress 
= (int)insn
; 
 950                 if (((newInsnAddress 
+ 4) >> 28) == (newTargetAddress 
>> 28)) 
 951                     *insn 
= 0x08000000 | ((newTargetAddress 
>> 2) & 0x3ffffff); 
 954                     *insn 
= 0x3c000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | ((newTargetAddress 
>> 16) & 0xffff); 
 956                     *(insn 
+ 1) = 0x34000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | (MIPSRegisters::t9 
<< OP_SH_RS
) | (newTargetAddress 
& 0xffff); 
 958                     *(insn 
+ 2) = 0x00000008 | (MIPSRegisters::t9 
<< OP_SH_RS
); 
 960             } else if ((*insn 
& 0xffe00000) == 0x3c000000) { // lui 
 961                 int high 
= (*insn 
& 0xffff) << 16; 
 962                 int low 
= *(insn 
+ 1) & 0xffff; 
 963                 int oldTargetAddress 
= high 
| low
; 
 964                 int newTargetAddress 
= oldTargetAddress 
- (int)oldBase 
+ (int)newBase
; 
 966                 *insn 
= 0x3c000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | ((newTargetAddress 
>> 16) & 0xffff); 
 968                 *(insn 
+ 1) = 0x34000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | (MIPSRegisters::t9 
<< OP_SH_RS
) | (newTargetAddress 
& 0xffff); 
 974     static int linkWithOffset(MIPSWord
* insn
, void* to
) 
 976         ASSERT((*insn 
& 0xfc000000) == 0x10000000 // beq 
 977             || (*insn 
& 0xfc000000) == 0x14000000 // bne 
 978             || (*insn 
& 0xffff0000) == 0x45010000 // bc1t 
 979             || (*insn 
& 0xffff0000) == 0x45000000); // bc1f 
 980         intptr_t diff 
= (reinterpret_cast<intptr_t>(to
) - reinterpret_cast<intptr_t>(insn
) - 4) >> 2; 
 982         if (diff 
< -32768 || diff 
> 32767 || *(insn 
+ 2) != 0x10000003) { 
 984                 Convert the sequence: 
 993                 to the new sequence if possible: 
1002                 OR to the new sequence: 
1005                   lui $25, target >> 16 
1006                   ori $25, $25, target & 0xffff 
1011                 Note: beq/bne/bc1t/bc1f are converted to bne/beq/bc1f/bc1t. 
1014             if (*(insn 
+ 2) == 0x10000003) { 
1015                 if ((*insn 
& 0xfc000000) == 0x10000000) // beq 
1016                     *insn 
= (*insn 
& 0x03ff0000) | 0x14000005; // bne 
1017                 else if ((*insn 
& 0xfc000000) == 0x14000000) // bne 
1018                     *insn 
= (*insn 
& 0x03ff0000) | 0x10000005; // beq 
1019                 else if ((*insn 
& 0xffff0000) == 0x45010000) // bc1t 
1020                     *insn 
= 0x45000005; // bc1f 
1021                 else if ((*insn 
& 0xffff0000) == 0x45000000) // bc1f 
1022                     *insn 
= 0x45010005; // bc1t 
1028             if ((reinterpret_cast<intptr_t>(insn
) + 4) >> 28 
1029                 == reinterpret_cast<intptr_t>(to
) >> 28) { 
1030                 *insn 
= 0x08000000 | ((reinterpret_cast<intptr_t>(to
) >> 2) & 0x3ffffff); 
1032                 return 4 * sizeof(MIPSWord
); 
1035             intptr_t newTargetAddress 
= reinterpret_cast<intptr_t>(to
); 
1037             *insn 
= 0x3c000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | ((newTargetAddress 
>> 16) & 0xffff); 
1039             *(insn 
+ 1) = 0x34000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | (MIPSRegisters::t9 
<< OP_SH_RS
) | (newTargetAddress 
& 0xffff); 
1041             *(insn 
+ 2) = 0x00000008 | (MIPSRegisters::t9 
<< OP_SH_RS
); 
1042             return 5 * sizeof(MIPSWord
); 
1045         *insn 
= (*insn 
& 0xffff0000) | (diff 
& 0xffff); 
1046         return sizeof(MIPSWord
); 
1049     static int linkCallInternal(void* from
, void* to
) 
1051         MIPSWord
* insn 
= reinterpret_cast<MIPSWord
*>(from
); 
1054         if ((*(insn 
+ 2) & 0xfc000000) == 0x0c000000) { // jal 
1055             if ((reinterpret_cast<intptr_t>(from
) - 4) >> 28 
1056                 == reinterpret_cast<intptr_t>(to
) >> 28) { 
1057                 *(insn 
+ 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to
) >> 2) & 0x3ffffff); 
1058                 return sizeof(MIPSWord
); 
1061             /* lui $25, (to >> 16) & 0xffff */ 
1062             *insn 
= 0x3c000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | ((reinterpret_cast<intptr_t>(to
) >> 16) & 0xffff); 
1063             /* ori $25, $25, to & 0xffff */ 
1064             *(insn 
+ 1) = 0x34000000 | (MIPSRegisters::t9 
<< OP_SH_RT
) | (MIPSRegisters::t9 
<< OP_SH_RS
) | (reinterpret_cast<intptr_t>(to
) & 0xffff); 
1066             *(insn 
+ 2) = 0x0000f809 | (MIPSRegisters::t9 
<< OP_SH_RS
); 
1067             return 3 * sizeof(MIPSWord
); 
1070         ASSERT((*insn 
& 0xffe00000) == 0x3c000000); // lui 
1071         ASSERT((*(insn 
+ 1) & 0xfc000000) == 0x34000000); // ori 
1074         *insn 
= (*insn 
& 0xffff0000) | ((reinterpret_cast<intptr_t>(to
) >> 16) & 0xffff); 
1076         *(insn 
+ 1) = (*(insn 
+ 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to
) & 0xffff); 
1077         return 2 * sizeof(MIPSWord
); 
1080     AssemblerBuffer m_buffer
; 
1082     int m_indexOfLastWatchpoint
; 
1083     int m_indexOfTailOfLastWatchpoint
; 
1088 #endif // ENABLE(ASSEMBLER) && CPU(MIPS) 
1090 #endif // MIPSAssembler_h