JavaScriptCore/ChangeLog

 12010-03-02 Chao-ying Fu <fu@mips.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 MIPS JIT Supports
 6 https://bugs.webkit.org/show_bug.cgi?id=30144
 7
 8 The following changes enable MIPS YARR and YARR_JIT.
 9
 10 * assembler/AbstractMacroAssembler.h:
 11 (JSC::AbstractMacroAssembler::Imm32::Imm32):
 12 * assembler/MIPSAssembler.h: Added.
 13 (JSC::MIPSRegisters::):
 14 (JSC::MIPSAssembler::MIPSAssembler):
 15 (JSC::MIPSAssembler::):
 16 (JSC::MIPSAssembler::JmpSrc::JmpSrc):
 17 (JSC::MIPSAssembler::JmpDst::JmpDst):
 18 (JSC::MIPSAssembler::JmpDst::isUsed):
 19 (JSC::MIPSAssembler::JmpDst::used):
 20 (JSC::MIPSAssembler::emitInst):
 21 (JSC::MIPSAssembler::nop):
 22 (JSC::MIPSAssembler::loadDelayNop):
 23 (JSC::MIPSAssembler::copDelayNop):
 24 (JSC::MIPSAssembler::move):
 25 (JSC::MIPSAssembler::li):
 26 (JSC::MIPSAssembler::lui):
 27 (JSC::MIPSAssembler::addiu):
 28 (JSC::MIPSAssembler::addu):
 29 (JSC::MIPSAssembler::subu):
 30 (JSC::MIPSAssembler::mult):
 31 (JSC::MIPSAssembler::mfhi):
 32 (JSC::MIPSAssembler::mflo):
 33 (JSC::MIPSAssembler::mul):
 34 (JSC::MIPSAssembler::andInsn):
 35 (JSC::MIPSAssembler::andi):
 36 (JSC::MIPSAssembler::nor):
 37 (JSC::MIPSAssembler::orInsn):
 38 (JSC::MIPSAssembler::ori):
 39 (JSC::MIPSAssembler::xorInsn):
 40 (JSC::MIPSAssembler::xori):
 41 (JSC::MIPSAssembler::slt):
 42 (JSC::MIPSAssembler::sltu):
 43 (JSC::MIPSAssembler::sltiu):
 44 (JSC::MIPSAssembler::sll):
 45 (JSC::MIPSAssembler::sllv):
 46 (JSC::MIPSAssembler::sra):
 47 (JSC::MIPSAssembler::srav):
 48 (JSC::MIPSAssembler::lw):
 49 (JSC::MIPSAssembler::lwl):
 50 (JSC::MIPSAssembler::lwr):
 51 (JSC::MIPSAssembler::lhu):
 52 (JSC::MIPSAssembler::sw):
 53 (JSC::MIPSAssembler::jr):
 54 (JSC::MIPSAssembler::jalr):
 55 (JSC::MIPSAssembler::jal):
 56 (JSC::MIPSAssembler::bkpt):
 57 (JSC::MIPSAssembler::bgez):
 58 (JSC::MIPSAssembler::bltz):
 59 (JSC::MIPSAssembler::beq):
 60 (JSC::MIPSAssembler::bne):
 61 (JSC::MIPSAssembler::bc1t):
 62 (JSC::MIPSAssembler::bc1f):
 63 (JSC::MIPSAssembler::newJmpSrc):
 64 (JSC::MIPSAssembler::appendJump):
 65 (JSC::MIPSAssembler::addd):
 66 (JSC::MIPSAssembler::subd):
 67 (JSC::MIPSAssembler::muld):
 68 (JSC::MIPSAssembler::lwc1):
 69 (JSC::MIPSAssembler::ldc1):
 70 (JSC::MIPSAssembler::swc1):
 71 (JSC::MIPSAssembler::sdc1):
 72 (JSC::MIPSAssembler::mtc1):
 73 (JSC::MIPSAssembler::mfc1):
 74 (JSC::MIPSAssembler::truncwd):
 75 (JSC::MIPSAssembler::cvtdw):
 76 (JSC::MIPSAssembler::ceqd):
 77 (JSC::MIPSAssembler::cngtd):
 78 (JSC::MIPSAssembler::cnged):
 79 (JSC::MIPSAssembler::cltd):
 80 (JSC::MIPSAssembler::cled):
 81 (JSC::MIPSAssembler::cueqd):
 82 (JSC::MIPSAssembler::coled):
 83 (JSC::MIPSAssembler::coltd):
 84 (JSC::MIPSAssembler::culed):
 85 (JSC::MIPSAssembler::cultd):
 86 (JSC::MIPSAssembler::label):
 87 (JSC::MIPSAssembler::align):
 88 (JSC::MIPSAssembler::getRelocatedAddress):
 89 (JSC::MIPSAssembler::getDifferenceBetweenLabels):
 90 (JSC::MIPSAssembler::size):
 91 (JSC::MIPSAssembler::executableCopy):
 92 (JSC::MIPSAssembler::getCallReturnOffset):
 93 (JSC::MIPSAssembler::linkJump):
 94 (JSC::MIPSAssembler::linkCall):
 95 (JSC::MIPSAssembler::linkPointer):
 96 (JSC::MIPSAssembler::relinkJump):
 97 (JSC::MIPSAssembler::relinkCall):
 98 (JSC::MIPSAssembler::repatchInt32):
 99 (JSC::MIPSAssembler::repatchPointer):
 100 (JSC::MIPSAssembler::repatchLoadPtrToLEA):
 101 (JSC::MIPSAssembler::relocateJumps):
 102 (JSC::MIPSAssembler::linkWithOffset):
 103 (JSC::MIPSAssembler::linkCallInternal):
 104 * assembler/MacroAssembler.h:
 105 * assembler/MacroAssemblerMIPS.h: Added.
 106 (JSC::MacroAssemblerMIPS::MacroAssemblerMIPS):
 107 (JSC::MacroAssemblerMIPS::):
 108 (JSC::MacroAssemblerMIPS::add32):
 109 (JSC::MacroAssemblerMIPS::and32):
 110 (JSC::MacroAssemblerMIPS::lshift32):
 111 (JSC::MacroAssemblerMIPS::mul32):
 112 (JSC::MacroAssemblerMIPS::not32):
 113 (JSC::MacroAssemblerMIPS::or32):
 114 (JSC::MacroAssemblerMIPS::rshift32):
 115 (JSC::MacroAssemblerMIPS::sub32):
 116 (JSC::MacroAssemblerMIPS::xor32):
 117 (JSC::MacroAssemblerMIPS::load32):
 118 (JSC::MacroAssemblerMIPS::load32WithUnalignedHalfWords):
 119 (JSC::MacroAssemblerMIPS::load32WithAddressOffsetPatch):
 120 (JSC::MacroAssemblerMIPS::loadPtrWithPatchToLEA):
 121 (JSC::MacroAssemblerMIPS::loadPtrWithAddressOffsetPatch):
 122 (JSC::MacroAssemblerMIPS::load16):
 123 (JSC::MacroAssemblerMIPS::store32WithAddressOffsetPatch):
 124 (JSC::MacroAssemblerMIPS::store32):
 125 (JSC::MacroAssemblerMIPS::supportsFloatingPoint):
 126 (JSC::MacroAssemblerMIPS::supportsFloatingPointTruncate):
 127 (JSC::MacroAssemblerMIPS::pop):
 128 (JSC::MacroAssemblerMIPS::push):
 129 (JSC::MacroAssemblerMIPS::move):
 130 (JSC::MacroAssemblerMIPS::swap):
 131 (JSC::MacroAssemblerMIPS::signExtend32ToPtr):
 132 (JSC::MacroAssemblerMIPS::zeroExtend32ToPtr):
 133 (JSC::MacroAssemblerMIPS::branch32):
 134 (JSC::MacroAssemblerMIPS::branch32WithUnalignedHalfWords):
 135 (JSC::MacroAssemblerMIPS::branch16):
 136 (JSC::MacroAssemblerMIPS::branchTest32):
 137 (JSC::MacroAssemblerMIPS::jump):
 138 (JSC::MacroAssemblerMIPS::branchAdd32):
 139 (JSC::MacroAssemblerMIPS::branchMul32):
 140 (JSC::MacroAssemblerMIPS::branchSub32):
 141 (JSC::MacroAssemblerMIPS::breakpoint):
 142 (JSC::MacroAssemblerMIPS::nearCall):
 143 (JSC::MacroAssemblerMIPS::call):
 144 (JSC::MacroAssemblerMIPS::ret):
 145 (JSC::MacroAssemblerMIPS::set32):
 146 (JSC::MacroAssemblerMIPS::setTest32):
 147 (JSC::MacroAssemblerMIPS::moveWithPatch):
 148 (JSC::MacroAssemblerMIPS::branchPtrWithPatch):
 149 (JSC::MacroAssemblerMIPS::storePtrWithPatch):
 150 (JSC::MacroAssemblerMIPS::tailRecursiveCall):
 151 (JSC::MacroAssemblerMIPS::makeTailRecursiveCall):
 152 (JSC::MacroAssemblerMIPS::loadDouble):
 153 (JSC::MacroAssemblerMIPS::storeDouble):
 154 (JSC::MacroAssemblerMIPS::addDouble):
 155 (JSC::MacroAssemblerMIPS::subDouble):
 156 (JSC::MacroAssemblerMIPS::mulDouble):
 157 (JSC::MacroAssemblerMIPS::convertInt32ToDouble):
 158 (JSC::MacroAssemblerMIPS::insertRelaxationWords):
 159 (JSC::MacroAssemblerMIPS::branchTrue):
 160 (JSC::MacroAssemblerMIPS::branchFalse):
 161 (JSC::MacroAssemblerMIPS::branchEqual):
 162 (JSC::MacroAssemblerMIPS::branchNotEqual):
 163 (JSC::MacroAssemblerMIPS::branchDouble):
 164 (JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32):
 165 (JSC::MacroAssemblerMIPS::linkCall):
 166 (JSC::MacroAssemblerMIPS::repatchCall):
 167 * jit/ExecutableAllocator.h:
 168 (JSC::ExecutableAllocator::cacheFlush):
 169 * wtf/Platform.h:
 170 * yarr/RegexJIT.cpp:
 171 (JSC::Yarr::RegexGenerator::generateEnter):
 172 (JSC::Yarr::RegexGenerator::generateReturn):
 173
11742010-03-02 Oliver Hunt <oliver@apple.com>
2175
3176 Reviewed by NOBODY (Build fix).
55415

JavaScriptCore/assembler/AbstractMacroAssembler.h

@@public:
173173 struct Imm32 {
174174 explicit Imm32(int32_t value)
175175 : m_value(value)
176 #if CPU(ARM)
 176#if CPU(ARM) || CPU(MIPS)
177177 , m_isPointer(false)
178178#endif
179179 {

@@public:
182182#if !CPU(X86_64)
183183 explicit Imm32(ImmPtr ptr)
184184 : m_value(ptr.asIntptr())
185 #if CPU(ARM)
 185#if CPU(ARM) || CPU(MIPS)
186186 , m_isPointer(true)
187187#endif
188188 {

@@public:
190190#endif
191191
192192 int32_t m_value;
193 #if CPU(ARM)
 193#if CPU(ARM) || CPU(MIPS)
194194 // We rely on being able to regenerate code to recover exception handling
195195 // information. Since ARMv7 supports 16-bit immediates there is a danger
196196 // that if pointer values change the layout of the generated code will change.
197197 // To avoid this problem, always generate pointers (and thus Imm32s constructed
198198 // from ImmPtrs) with a code sequence that is able to represent any pointer
199199 // value - don't use a more compact form in these cases.
 200 // Same for MIPS.
200201 bool m_isPointer;
201202#endif
202203 };
55195

JavaScriptCore/assembler/MIPSAssembler.h

 1/*
 2 * Copyright (C) 2009 Apple Inc. All rights reserved.
 3 * Copyright (C) 2009 University of Szeged
 4 * All rights reserved.
 5 * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
 6 *
 7 * Redistribution and use in source and binary forms, with or without
 8 * modification, are permitted provided that the following conditions
 9 * are met:
 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.
 15 *
 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.
 27 */
 28
 29#ifndef MIPSAssembler_h
 30#define MIPSAssembler_h
 31
 32#include <wtf/Platform.h>
 33
 34#if ENABLE(ASSEMBLER) && CPU(MIPS)
 35
 36#include "AssemblerBuffer.h"
 37#include <wtf/Assertions.h>
 38#include <wtf/SegmentedVector.h>
 39
 40namespace JSC {
 41
 42typedef uint32_t MIPSWord;
 43
 44namespace MIPSRegisters {
 45typedef enum {
 46 r0 = 0,
 47 r1,
 48 r2,
 49 r3,
 50 r4,
 51 r5,
 52 r6,
 53 r7,
 54 r8,
 55 r9,
 56 r10,
 57 r11,
 58 r12,
 59 r13,
 60 r14,
 61 r15,
 62 r16,
 63 r17,
 64 r18,
 65 r19,
 66 r20,
 67 r21,
 68 r22,
 69 r23,
 70 r24,
 71 r25,
 72 r26,
 73 r27,
 74 r28,
 75 r29,
 76 r30,
 77 r31,
 78 zero = r0,
 79 at = r1,
 80 v0 = r2,
 81 v1 = r3,
 82 a0 = r4,
 83 a1 = r5,
 84 a2 = r6,
 85 a3 = r7,
 86 t0 = r8,
 87 t1 = r9,
 88 t2 = r10,
 89 t3 = r11,
 90 t4 = r12,
 91 t5 = r13,
 92 t6 = r14,
 93 t7 = r15,
 94 s0 = r16,
 95 s1 = r17,
 96 s2 = r18,
 97 s3 = r19,
 98 s4 = r20,
 99 s5 = r21,
 100 s6 = r22,
 101 s7 = r23,
 102 t8 = r24,
 103 t9 = r25,
 104 k0 = r26,
 105 k1 = r27,
 106 gp = r28,
 107 sp = r29,
 108 fp = r30,
 109 ra = r31
 110} RegisterID;
 111
 112typedef enum {
 113 f0,
 114 f1,
 115 f2,
 116 f3,
 117 f4,
 118 f5,
 119 f6,
 120 f7,
 121 f8,
 122 f9,
 123 f10,
 124 f11,
 125 f12,
 126 f13,
 127 f14,
 128 f15,
 129 f16,
 130 f17,
 131 f18,
 132 f19,
 133 f20,
 134 f21,
 135 f22,
 136 f23,
 137 f24,
 138 f25,
 139 f26,
 140 f27,
 141 f28,
 142 f29,
 143 f30,
 144 f31
 145} FPRegisterID;
 146
 147} // namespace MIPSRegisters
 148
 149class MIPSAssembler {
 150public:
 151 typedef MIPSRegisters::RegisterID RegisterID;
 152 typedef MIPSRegisters::FPRegisterID FPRegisterID;
 153 typedef SegmentedVector<int, 64> Jumps;
 154
 155 MIPSAssembler()
 156 {
 157 }
 158
 159 // MIPS instruction opcode field position
 160 enum {
 161 OP_SH_RD = 11,
 162 OP_SH_RT = 16,
 163 OP_SH_RS = 21,
 164 OP_SH_SHAMT = 6,
 165 OP_SH_CODE = 16,
 166 OP_SH_FD = 6,
 167 OP_SH_FS = 11,
 168 OP_SH_FT = 16
 169 };
 170
 171 class JmpSrc {
 172 friend class MIPSAssembler;
 173 public:
 174 JmpSrc()
 175 : m_offset(-1)
 176 {
 177 }
 178
 179 private:
 180 JmpSrc(int offset)
 181 : m_offset(offset)
 182 {
 183 }
 184
 185 int m_offset;
 186 };
 187
 188 class JmpDst {
 189 friend class MIPSAssembler;
 190 public:
 191 JmpDst()
 192 : m_offset(-1)
 193 , m_used(false)
 194 {
 195 }
 196
 197 bool isUsed() const { return m_used; }
 198 void used() { m_used = true; }
 199 private:
 200 JmpDst(int offset)
 201 : m_offset(offset)
 202 , m_used(false)
 203 {
 204 ASSERT(m_offset == offset);
 205 }
 206
 207 int m_offset : 31;
 208 int m_used : 1;
 209 };
 210
 211 void emitInst(MIPSWord op)
 212 {
 213 void* oldBase = m_buffer.data();
 214
 215 m_buffer.putInt(op);
 216
 217 void* newBase = m_buffer.data();
 218 if (oldBase != newBase)
 219 relocateJumps(oldBase, newBase);
 220 }
 221
 222 void nop()
 223 {
 224 emitInst(0x00000000);
 225 }
 226
 227 /* Need to insert one load data delay nop for mips1. */
 228 void loadDelayNop()
 229 {
 230#if WTF_MIPS_ISA(1)
 231 nop();
 232#endif
 233 }
 234
 235 /* Need to insert one coprocessor access delay nop for mips1. */
 236 void copDelayNop()
 237 {
 238#if WTF_MIPS_ISA(1)
 239 nop();
 240#endif
 241 }
 242
 243 void move(RegisterID rd, RegisterID rs)
 244 {
 245 /* addu */
 246 emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS));
 247 }
 248
 249 /* Set an immediate value to a register. This may generate 1 or 2
 250 instructions. */
 251 void li(RegisterID dest, int imm)
 252 {
 253 if (imm >= -32768 && imm <= 32767)
 254 addiu(dest, MIPSRegisters::zero, imm);
 255 else if (imm >= 0 && imm < 65536)
 256 ori(dest, MIPSRegisters::zero, imm);
 257 else {
 258 lui(dest, imm >> 16);
 259 if (imm & 0xffff)
 260 ori(dest, dest, imm);
 261 }
 262 }
 263
 264 void lui(RegisterID rt, int imm)
 265 {
 266 emitInst(0x3c000000 | (rt << OP_SH_RT) | (imm & 0xffff));
 267 }
 268
 269 void addiu(RegisterID rt, RegisterID rs, int imm)
 270 {
 271 emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 272 | (imm & 0xffff));
 273 }
 274
 275 void addu(RegisterID rd, RegisterID rs, RegisterID rt)
 276 {
 277 emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 278 | (rt << OP_SH_RT));
 279 }
 280
 281 void subu(RegisterID rd, RegisterID rs, RegisterID rt)
 282 {
 283 emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 284 | (rt << OP_SH_RT));
 285 }
 286
 287 void mult(RegisterID rs, RegisterID rt)
 288 {
 289 emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
 290 }
 291
 292 void mfhi(RegisterID rd)
 293 {
 294 emitInst(0x00000010 | (rd << OP_SH_RD));
 295 }
 296
 297 void mflo(RegisterID rd)
 298 {
 299 emitInst(0x00000012 | (rd << OP_SH_RD));
 300 }
 301
 302 void mul(RegisterID rd, RegisterID rs, RegisterID rt)
 303 {
 304#if WTF_MIPS_ISA_AT_LEAST(32)
 305 emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 306 | (rt << OP_SH_RT));
 307#else
 308 mult(rs, rt);
 309 mflo(rd);
 310#endif
 311 }
 312
 313 void andInsn(RegisterID rd, RegisterID rs, RegisterID rt)
 314 {
 315 emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 316 | (rt << OP_SH_RT));
 317 }
 318
 319 void andi(RegisterID rt, RegisterID rs, int imm)
 320 {
 321 emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 322 | (imm & 0xffff));
 323 }
 324
 325 void nor(RegisterID rd, RegisterID rs, RegisterID rt)
 326 {
 327 emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 328 | (rt << OP_SH_RT));
 329 }
 330
 331 void orInsn(RegisterID rd, RegisterID rs, RegisterID rt)
 332 {
 333 emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 334 | (rt << OP_SH_RT));
 335 }
 336
 337 void ori(RegisterID rt, RegisterID rs, int imm)
 338 {
 339 emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 340 | (imm & 0xffff));
 341 }
 342
 343 void xorInsn(RegisterID rd, RegisterID rs, RegisterID rt)
 344 {
 345 emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 346 | (rt << OP_SH_RT));
 347 }
 348
 349 void xori(RegisterID rt, RegisterID rs, int imm)
 350 {
 351 emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 352 | (imm & 0xffff));
 353 }
 354
 355 void slt(RegisterID rd, RegisterID rs, RegisterID rt)
 356 {
 357 emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 358 | (rt << OP_SH_RT));
 359 }
 360
 361 void sltu(RegisterID rd, RegisterID rs, RegisterID rt)
 362 {
 363 emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 364 | (rt << OP_SH_RT));
 365 }
 366
 367 void sltiu(RegisterID rt, RegisterID rs, int imm)
 368 {
 369 emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 370 | (imm & 0xffff));
 371 }
 372
 373 void sll(RegisterID rd, RegisterID rt, int shamt)
 374 {
 375 emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 376 | ((shamt & 0x1f) << OP_SH_SHAMT));
 377 }
 378
 379 void sllv(RegisterID rd, RegisterID rt, int rs)
 380 {
 381 emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 382 | (rs << OP_SH_RS));
 383 }
 384
 385 void sra(RegisterID rd, RegisterID rt, int shamt)
 386 {
 387 emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 388 | ((shamt & 0x1f) << OP_SH_SHAMT));
 389 }
 390
 391 void srav(RegisterID rd, RegisterID rt, RegisterID rs)
 392 {
 393 emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 394 | (rs << OP_SH_RS));
 395 }
 396
 397 void lw(RegisterID rt, RegisterID rs, int offset)
 398 {
 399 emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 400 | (offset & 0xffff));
 401 loadDelayNop();
 402 }
 403
 404 void lwl(RegisterID rt, RegisterID rs, int offset)
 405 {
 406 emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 407 | (offset & 0xffff));
 408 loadDelayNop();
 409 }
 410
 411 void lwr(RegisterID rt, RegisterID rs, int offset)
 412 {
 413 emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 414 | (offset & 0xffff));
 415 loadDelayNop();
 416 }
 417
 418 void lhu(RegisterID rt, RegisterID rs, int offset)
 419 {
 420 emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 421 | (offset & 0xffff));
 422 loadDelayNop();
 423 }
 424
 425 void sw(RegisterID rt, RegisterID rs, int offset)
 426 {
 427 emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 428 | (offset & 0xffff));
 429 }
 430
 431 void jr(RegisterID rs)
 432 {
 433 emitInst(0x00000008 | (rs << OP_SH_RS));
 434 }
 435
 436 void jalr(RegisterID rs)
 437 {
 438 emitInst(0x0000f809 | (rs << OP_SH_RS));
 439 }
 440
 441 void jal()
 442 {
 443 emitInst(0x0c000000);
 444 }
 445
 446 void bkpt()
 447 {
 448 int value = 512; /* BRK_BUG */
 449 emitInst(0x0000000d | ((value & 0x3ff) << OP_SH_CODE));
 450 }
 451
 452 void bgez(RegisterID rs, int imm)
 453 {
 454 emitInst(0x04010000 | (rs << OP_SH_RS) | (imm & 0xffff));
 455 }
 456
 457 void bltz(RegisterID rs, int imm)
 458 {
 459 emitInst(0x04000000 | (rs << OP_SH_RS) | (imm & 0xffff));
 460 }
 461
 462 void beq(RegisterID rs, RegisterID rt, int imm)
 463 {
 464 emitInst(0x10000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
 465 }
 466
 467 void bne(RegisterID rs, RegisterID rt, int imm)
 468 {
 469 emitInst(0x14000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
 470 }
 471
 472 void bc1t()
 473 {
 474 emitInst(0x45010000);
 475 }
 476
 477 void bc1f()
 478 {
 479 emitInst(0x45000000);
 480 }
 481
 482 JmpSrc newJmpSrc()
 483 {
 484 return JmpSrc(m_buffer.size());
 485 }
 486
 487 void appendJump()
 488 {
 489 m_jumps.append(m_buffer.size());
 490 }
 491
 492 void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 493 {
 494 emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 495 | (ft << OP_SH_FT));
 496 }
 497
 498 void subd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 499 {
 500 emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 501 | (ft << OP_SH_FT));
 502 }
 503
 504 void muld(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 505 {
 506 emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 507 | (ft << OP_SH_FT));
 508 }
 509
 510 void lwc1(FPRegisterID ft, RegisterID rs, int offset)
 511 {
 512 emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 513 | (offset & 0xffff));
 514 copDelayNop();
 515 }
 516
 517 void ldc1(FPRegisterID ft, RegisterID rs, int offset)
 518 {
 519 emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 520 | (offset & 0xffff));
 521 }
 522
 523 void swc1(FPRegisterID ft, RegisterID rs, int offset)
 524 {
 525 emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 526 | (offset & 0xffff));
 527 }
 528
 529 void sdc1(FPRegisterID ft, RegisterID rs, int offset)
 530 {
 531 emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 532 | (offset & 0xffff));
 533 }
 534
 535 void mtc1(RegisterID rt, FPRegisterID fs)
 536 {
 537 emitInst(0x44800000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
 538 copDelayNop();
 539 }
 540
 541 void mfc1(RegisterID rt, FPRegisterID fs)
 542 {
 543 emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
 544 copDelayNop();
 545 }
 546
 547 void truncwd(FPRegisterID fd, FPRegisterID fs)
 548 {
 549 emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
 550 }
 551
 552 void cvtdw(FPRegisterID fd, FPRegisterID fs)
 553 {
 554 emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
 555 }
 556
 557 void ceqd(FPRegisterID fs, FPRegisterID ft)
 558 {
 559 emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 560 copDelayNop();
 561 }
 562
 563 void cngtd(FPRegisterID fs, FPRegisterID ft)
 564 {
 565 emitInst(0x4620003f | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 566 copDelayNop();
 567 }
 568
 569 void cnged(FPRegisterID fs, FPRegisterID ft)
 570 {
 571 emitInst(0x4620003d | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 572 copDelayNop();
 573 }
 574
 575 void cltd(FPRegisterID fs, FPRegisterID ft)
 576 {
 577 emitInst(0x4620003c | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 578 copDelayNop();
 579 }
 580
 581 void cled(FPRegisterID fs, FPRegisterID ft)
 582 {
 583 emitInst(0x4620003e | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 584 copDelayNop();
 585 }
 586
 587 void cueqd(FPRegisterID fs, FPRegisterID ft)
 588 {
 589 emitInst(0x46200033 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 590 copDelayNop();
 591 }
 592
 593 void coled(FPRegisterID fs, FPRegisterID ft)
 594 {
 595 emitInst(0x46200036 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 596 copDelayNop();
 597 }
 598
 599 void coltd(FPRegisterID fs, FPRegisterID ft)
 600 {
 601 emitInst(0x46200034 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 602 copDelayNop();
 603 }
 604
 605 void culed(FPRegisterID fs, FPRegisterID ft)
 606 {
 607 emitInst(0x46200037 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 608 copDelayNop();
 609 }
 610
 611 void cultd(FPRegisterID fs, FPRegisterID ft)
 612 {
 613 emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 614 copDelayNop();
 615 }
 616
 617 // General helpers
 618
 619 JmpDst label()
 620 {
 621 return JmpDst(m_buffer.size());
 622 }
 623
 624 JmpDst align(int alignment)
 625 {
 626 while (!m_buffer.isAligned(alignment))
 627 bkpt();
 628
 629 return label();
 630 }
 631
 632 static void* getRelocatedAddress(void* code, JmpSrc jump)
 633 {
 634 ASSERT(jump.m_offset != -1);
 635 void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + jump.m_offset);
 636 return b;
 637 }
 638
 639 static void* getRelocatedAddress(void* code, JmpDst label)
 640 {
 641 void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + label.m_offset);
 642 return b;
 643 }
 644
 645 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
 646 {
 647 return to.m_offset - from.m_offset;
 648 }
 649
 650 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
 651 {
 652 return to.m_offset - from.m_offset;
 653 }
 654
 655 static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to)
 656 {
 657 return to.m_offset - from.m_offset;
 658 }
 659
 660 // Assembler admin methods:
 661
 662 size_t size() const
 663 {
 664 return m_buffer.size();
 665 }
 666
 667 void* executableCopy(ExecutablePool* allocator)
 668 {
 669 void *result = m_buffer.executableCopy(allocator);
 670 if (!result)
 671 return 0;
 672
 673 relocateJumps(m_buffer.data(), result);
 674 return result;
 675 }
 676
 677 static unsigned getCallReturnOffset(JmpSrc call)
 678 {
 679 // The return address is after a call and a delay slot instruction
 680 return call.m_offset;
 681 }
 682
 683 // Linking & patching:
 684 //
 685 // 'link' and 'patch' methods are for use on unprotected code - such as the code
 686 // within the AssemblerBuffer, and code being patched by the patch buffer. Once
 687 // code has been finalized it is (platform support permitting) within a non-
 688 // writable region of memory; to modify the code in an execute-only execuable
 689 // pool the 'repatch' and 'relink' methods should be used.
 690
 691 void linkJump(JmpSrc from, JmpDst to)
 692 {
 693 ASSERT(to.m_offset != -1);
 694 ASSERT(from.m_offset != -1);
 695 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset);
 696 MIPSWord* toPos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset);
 697
 698 ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
 699 insn = insn - 6;
 700 linkWithOffset(insn, toPos);
 701 }
 702
 703 static void linkJump(void* code, JmpSrc from, void* to)
 704 {
 705 ASSERT(from.m_offset != -1);
 706 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 707
 708 ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
 709 insn = insn - 6;
 710 linkWithOffset(insn, to);
 711 }
 712
 713 static void linkCall(void* code, JmpSrc from, void* to)
 714 {
 715 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 716 linkCallInternal(insn, to);
 717 }
 718
 719 static void linkPointer(void* code, JmpDst from, void* to)
 720 {
 721 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 722 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 723 *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 724 insn++;
 725 ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
 726 *insn = (*insn & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 727 }
 728
 729 static void relinkJump(void* from, void* to)
 730 {
 731 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 732
 733 ASSERT(!(*(insn - 1)) && !(*(insn - 5)));
 734 insn = insn - 6;
 735 int flushSize = linkWithOffset(insn, to);
 736
 737 ExecutableAllocator::cacheFlush(insn, flushSize);
 738 }
 739
 740 static void relinkCall(void* from, void* to)
 741 {
 742 void* start;
 743 int size = linkCallInternal(from, to);
 744 if (size == sizeof(MIPSWord))
 745 start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 2 * sizeof(MIPSWord));
 746 else
 747 start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
 748
 749 ExecutableAllocator::cacheFlush(start, size);
 750 }
 751
 752 static void repatchInt32(void* from, int32_t to)
 753 {
 754 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 755 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 756 *insn = (*insn & 0xffff0000) | ((to >> 16) & 0xffff);
 757 insn++;
 758 ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
 759 *insn = (*insn & 0xffff0000) | (to & 0xffff);
 760 insn--;
 761 ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
 762 }
 763
 764 static void repatchPointer(void* from, void* to)
 765 {
 766 repatchInt32(from, reinterpret_cast<int32_t>(to));
 767 }
 768
 769 static void repatchLoadPtrToLEA(void* from)
 770 {
 771 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 772 insn = insn + 3;
 773 ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw
 774 /* lw -> addiu */
 775 *insn = 0x24000000 | (*insn & 0x03ffffff);
 776
 777 ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
 778 }
 779
 780private:
 781
 782 /* Update each jump in the buffer of newBase. */
 783 void relocateJumps(void* oldBase, void* newBase)
 784 {
 785 // Check each jump
 786 for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
 787 int pos = *iter;
 788 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(newBase) + pos);
 789 insn = insn + 2;
 790 // Need to make sure we have 5 valid instructions after pos
 791 if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord))
 792 continue;
 793
 794 if ((*insn & 0xfc000000) == 0x08000000) { // j
 795 int offset = *insn & 0x03ffffff;
 796 int oldInsnAddress = (int)insn - (int)newBase + (int)oldBase;
 797 int topFourBits = (oldInsnAddress + 4) >> 28;
 798 int oldTargetAddress = (topFourBits << 28) | (offset << 2);
 799 int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
 800 int newInsnAddress = (int)insn;
 801 if (((newInsnAddress + 4) >> 28) == (newTargetAddress >> 28))
 802 *insn = 0x08000000 | ((newTargetAddress >> 2) & 0x3ffffff);
 803 else {
 804 /* lui */
 805 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
 806 /* ori */
 807 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
 808 /* jr */
 809 *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
 810 }
 811 } else if ((*insn & 0xffe00000) == 0x3c000000) { // lui
 812 int high = (*insn & 0xffff) << 16;
 813 int low = *(insn + 1) & 0xffff;
 814 int oldTargetAddress = high | low;
 815 int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
 816 /* lui */
 817 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
 818 /* ori */
 819 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
 820 }
 821 }
 822 }
 823
 824 static int linkWithOffset(MIPSWord* insn, void* to)
 825 {
 826 ASSERT((*insn & 0xfc000000) == 0x10000000 // beq
 827 || (*insn & 0xfc000000) == 0x14000000 // bne
 828 || (*insn & 0xffff0000) == 0x45010000 // bc1t
 829 || (*insn & 0xffff0000) == 0x45000000); // bc1f
 830 intptr_t diff = (reinterpret_cast<intptr_t>(to)
 831 - reinterpret_cast<intptr_t>(insn) - 4) >> 2;
 832
 833 if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) {
 834 /*
 835 Convert the sequence:
 836 beq $2, $3, target
 837 nop
 838 b 1f
 839 nop
 840 nop
 841 nop
 842 1:
 843
 844 to the new sequence if possible:
 845 bne $2, $3, 1f
 846 nop
 847 j target
 848 nop
 849 nop
 850 nop
 851 1:
 852
 853 OR to the new sequence:
 854 bne $2, $3, 1f
 855 nop
 856 lui $25, target >> 16
 857 ori $25, $25, target & 0xffff
 858 jr $25
 859 nop
 860 1:
 861
 862 Note: beq/bne/bc1t are converted to bne/beq/bc1f.
 863 */
 864
 865 if (*(insn + 2) == 0x10000003) {
 866 if ((*insn & 0xfc000000) == 0x10000000) // beq
 867 *insn = (*insn & 0x03ff0000) | 0x14000005; // bne
 868 else if ((*insn & 0xfc000000) == 0x14000000) // bne
 869 *insn = (*insn & 0x03ff0000) | 0x10000005; // beq
 870 else if ((*insn & 0xffff0000) == 0x45010000) // bc1t
 871 *insn = 0x45000005; // bc1f
 872 else
 873 ASSERT(0);
 874 }
 875
 876 insn = insn + 2;
 877 if ((reinterpret_cast<intptr_t>(insn) + 4) >> 28
 878 == reinterpret_cast<intptr_t>(to) >> 28) {
 879 *insn = 0x08000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
 880 *(insn + 1) = 0;
 881 return 4 * sizeof(MIPSWord);
 882 }
 883
 884 intptr_t newTargetAddress = reinterpret_cast<intptr_t>(to);
 885 /* lui */
 886 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
 887 /* ori */
 888 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
 889 /* jr */
 890 *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
 891 return 5 * sizeof(MIPSWord);
 892 }
 893
 894 *insn = (*insn & 0xffff0000) | (diff & 0xffff);
 895 return sizeof(MIPSWord);
 896 }
 897
 898 static int linkCallInternal(void* from, void* to)
 899 {
 900 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 901 insn = insn - 4;
 902
 903 if ((*(insn + 2) & 0xfc000000) == 0x0c000000) { // jal
 904 if ((reinterpret_cast<intptr_t>(from) - 4) >> 28
 905 == reinterpret_cast<intptr_t>(to) >> 28) {
 906 *(insn + 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
 907 return sizeof(MIPSWord);
 908 }
 909
 910 /* lui $25, (to >> 16) & 0xffff */
 911 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 912 /* ori $25, $25, to & 0xffff */
 913 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 914 /* jalr $25 */
 915 *(insn + 2) = 0x0000f809 | (MIPSRegisters::t9 << OP_SH_RS);
 916 return 3 * sizeof(MIPSWord);
 917 }
 918
 919 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 920 ASSERT((*(insn + 1) & 0xfc000000) == 0x34000000); // ori
 921
 922 /* lui */
 923 *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 924 /* ori */
 925 *(insn + 1) = (*(insn + 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 926 return 2 * sizeof(MIPSWord);
 927 }
 928
 929 AssemblerBuffer m_buffer;
 930 Jumps m_jumps;
 931};
 932
 933} // namespace JSC
 934
 935#endif // ENABLE(ASSEMBLER) && CPU(MIPS)
 936
 937#endif // MIPSAssembler_h
0

JavaScriptCore/assembler/MacroAssembler.h

@@namespace JSC { typedef MacroAssemblerAR
3838#include "MacroAssemblerARM.h"
3939namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
4040
 41#elif CPU(MIPS)
 42#include "MacroAssemblerMIPS.h"
 43namespace JSC {
 44typedef MacroAssemblerMIPS MacroAssemblerBase;
 45};
 46
4147#elif CPU(X86)
4248#include "MacroAssemblerX86.h"
4349namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
55195

JavaScriptCore/assembler/MacroAssemblerMIPS.h

 1/*
 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
 3 * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
 4 *
 5 * Redistribution and use in source and binary forms, with or without
 6 * modification, are permitted provided that the following conditions
 7 * are met:
 8 * 1. Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * 2. Redistributions in binary form must reproduce the above copyright
 11 * notice, this list of conditions and the following disclaimer in the
 12 * documentation and/or other materials provided with the distribution.
 13 *
 14 * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 25 */
 26
 27#ifndef MacroAssemblerMIPS_h
 28#define MacroAssemblerMIPS_h
 29
 30#include <wtf/Platform.h>
 31
 32#if ENABLE(ASSEMBLER) && CPU(MIPS)
 33
 34#include "AbstractMacroAssembler.h"
 35#include "MIPSAssembler.h"
 36
 37namespace JSC {
 38
 39class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
 40public:
 41
 42 MacroAssemblerMIPS()
 43 : m_fixedWidth(false)
 44 {
 45 }
 46
 47 static const Scale ScalePtr = TimesFour;
 48
 49 // For storing immediate number
 50 static const RegisterID immTempRegister = MIPSRegisters::t0;
 51 // For storing data loaded from the memory
 52 static const RegisterID dataTempRegister = MIPSRegisters::t1;
 53 // For storing address base
 54 static const RegisterID addrTempRegister = MIPSRegisters::t2;
 55 // For storing compare result
 56 static const RegisterID cmpTempRegister = MIPSRegisters::t3;
 57
 58 // FP temp register
 59 static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
 60
 61 enum Condition {
 62 Equal,
 63 NotEqual,
 64 Above,
 65 AboveOrEqual,
 66 Below,
 67 BelowOrEqual,
 68 GreaterThan,
 69 GreaterThanOrEqual,
 70 LessThan,
 71 LessThanOrEqual,
 72 Overflow,
 73 Signed,
 74 Zero,
 75 NonZero
 76 };
 77
 78 enum DoubleCondition {
 79 DoubleEqual,
 80 DoubleNotEqual,
 81 DoubleGreaterThan,
 82 DoubleGreaterThanOrEqual,
 83 DoubleLessThan,
 84 DoubleLessThanOrEqual,
 85 DoubleEqualOrUnordered,
 86 DoubleNotEqualOrUnordered,
 87 DoubleGreaterThanOrUnordered,
 88 DoubleGreaterThanOrEqualOrUnordered,
 89 DoubleLessThanOrUnordered,
 90 DoubleLessThanOrEqualOrUnordered
 91 };
 92
 93 static const RegisterID stackPointerRegister = MIPSRegisters::sp;
 94 static const RegisterID returnAddressRegister = MIPSRegisters::ra;
 95
 96 // Integer arithmetic operations:
 97 //
 98 // Operations are typically two operand - operation(source, srcDst)
 99 // For many operations the source may be an Imm32, the srcDst operand
 100 // may often be a memory location (explictly described using an Address
 101 // object).
 102
 103 void add32(RegisterID src, RegisterID dest)
 104 {
 105 m_assembler.addu(dest, dest, src);
 106 }
 107
 108 void add32(Imm32 imm, RegisterID dest)
 109 {
 110 add32(imm, dest, dest);
 111 }
 112
 113 void add32(Imm32 imm, RegisterID src, RegisterID dest)
 114 {
 115 if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
 116 && !m_fixedWidth) {
 117 /*
 118 addiu dest, src, imm
 119 */
 120 m_assembler.addiu(dest, src, imm.m_value);
 121 } else {
 122 /*
 123 li immTemp, imm
 124 addu dest, src, immTemp
 125 */
 126 move(imm, immTempRegister);
 127 m_assembler.addu(dest, src, immTempRegister);
 128 }
 129 }
 130
 131 void add32(Imm32 imm, Address address)
 132 {
 133 if (address.offset >= -32768 && address.offset <= 32767
 134 && !m_fixedWidth) {
 135 /*
 136 lw dataTemp, offset(base)
 137 li immTemp, imm
 138 addu dataTemp, dataTemp, immTemp
 139 sw dataTemp, offset(base)
 140 */
 141 m_assembler.lw(dataTempRegister, address.base, address.offset);
 142 if (!imm.m_isPointer
 143 && imm.m_value >= -32768 && imm.m_value <= 32767
 144 && !m_fixedWidth)
 145 m_assembler.addiu(dataTempRegister, dataTempRegister,
 146 imm.m_value);
 147 else {
 148 move(imm, immTempRegister);
 149 m_assembler.addu(dataTempRegister, dataTempRegister,
 150 immTempRegister);
 151 }
 152 m_assembler.sw(dataTempRegister, address.base, address.offset);
 153 } else {
 154 /*
 155 lui addrTemp, (offset + 0x8000) >> 16
 156 addu addrTemp, addrTemp, base
 157 lw dataTemp, (offset & 0xffff)(addrTemp)
 158 li immtemp, imm
 159 addu dataTemp, dataTemp, immTemp
 160 sw dataTemp, (offset & 0xffff)(addrTemp)
 161 */
 162 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 163 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 164 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
 165
 166 if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
 167 m_assembler.addiu(dataTempRegister, dataTempRegister,
 168 imm.m_value);
 169 else {
 170 move(imm, immTempRegister);
 171 m_assembler.addu(dataTempRegister, dataTempRegister,
 172 immTempRegister);
 173 }
 174 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
 175 }
 176 }
 177
 178 void add32(Address src, RegisterID dest)
 179 {
 180 load32(src, dataTempRegister);
 181 add32(dataTempRegister, dest);
 182 }
 183
 184 void add32(RegisterID src, Address dest)
 185 {
 186 if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
 187 /*
 188 lw dataTemp, offset(base)
 189 addu dataTemp, dataTemp, src
 190 sw dataTemp, offset(base)
 191 */
 192 m_assembler.lw(dataTempRegister, dest.base, dest.offset);
 193 m_assembler.addu(dataTempRegister, dataTempRegister, src);
 194 m_assembler.sw(dataTempRegister, dest.base, dest.offset);
 195 } else {
 196 /*
 197 lui addrTemp, (offset + 0x8000) >> 16
 198 addu addrTemp, addrTemp, base
 199 lw dataTemp, (offset & 0xffff)(addrTemp)
 200 addu dataTemp, dataTemp, src
 201 sw dataTemp, (offset & 0xffff)(addrTemp)
 202 */
 203 m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16);
 204 m_assembler.addu(addrTempRegister, addrTempRegister, dest.base);
 205 m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset);
 206 m_assembler.addu(dataTempRegister, dataTempRegister, src);
 207 m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset);
 208 }
 209 }
 210
 211 void add32(Imm32 imm, AbsoluteAddress address)
 212 {
 213 /*
 214 li addrTemp, address
 215 li immTemp, imm
 216 lw dataTemp, 0(addrTemp)
 217 addu dataTemp, dataTemp, immTemp
 218 sw dataTemp, 0(addrTemp)
 219 */
 220 move(ImmPtr(address.m_ptr), addrTempRegister);
 221 m_assembler.lw(dataTempRegister, addrTempRegister, 0);
 222 if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
 223 && !m_fixedWidth)
 224 m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
 225 else {
 226 move(imm, immTempRegister);
 227 m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
 228 }
 229 m_assembler.sw(dataTempRegister, addrTempRegister, 0);
 230 }
 231
 232 void and32(RegisterID src, RegisterID dest)
 233 {
 234 m_assembler.andInsn(dest, dest, src);
 235 }
 236
 237 void and32(Imm32 imm, RegisterID dest)
 238 {
 239 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
 240 move(MIPSRegisters::zero, dest);
 241 else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
 242 && !m_fixedWidth)
 243 m_assembler.andi(dest, dest, imm.m_value);
 244 else {
 245 /*
 246 li immTemp, imm
 247 and dest, dest, immTemp
 248 */
 249 move(imm, immTempRegister);
 250 m_assembler.andInsn(dest, dest, immTempRegister);
 251 }
 252 }
 253
 254 void lshift32(Imm32 imm, RegisterID dest)
 255 {
 256 m_assembler.sll(dest, dest, imm.m_value);
 257 }
 258
 259 void lshift32(RegisterID shiftAmount, RegisterID dest)
 260 {
 261 m_assembler.sllv(dest, dest, shiftAmount);
 262 }
 263
 264 void mul32(RegisterID src, RegisterID dest)
 265 {
 266 m_assembler.mul(dest, dest, src);
 267 }
 268
 269 void mul32(Imm32 imm, RegisterID src, RegisterID dest)
 270 {
 271 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
 272 move(MIPSRegisters::zero, dest);
 273 else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth)
 274 move(src, dest);
 275 else {
 276 /*
 277 li dataTemp, imm
 278 mul dest, src, dataTemp
 279 */
 280 move(imm, dataTempRegister);
 281 m_assembler.mul(dest, src, dataTempRegister);
 282 }
 283 }
 284
 285 void not32(RegisterID srcDest)
 286 {
 287 m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
 288 }
 289
 290 void or32(RegisterID src, RegisterID dest)
 291 {
 292 m_assembler.orInsn(dest, dest, src);
 293 }
 294
 295 void or32(Imm32 imm, RegisterID dest)
 296 {
 297 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
 298 return;
 299
 300 if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
 301 && !m_fixedWidth) {
 302 m_assembler.ori(dest, dest, imm.m_value);
 303 return;
 304 }
 305
 306 /*
 307 li dataTemp, imm
 308 or dest, dest, dataTemp
 309 */
 310 move(imm, dataTempRegister);
 311 m_assembler.orInsn(dest, dest, dataTempRegister);
 312 }
 313
 314 void rshift32(RegisterID shiftAmount, RegisterID dest)
 315 {
 316 m_assembler.srav(dest, dest, shiftAmount);
 317 }
 318
 319 void rshift32(Imm32 imm, RegisterID dest)
 320 {
 321 m_assembler.sra(dest, dest, imm.m_value);
 322 }
 323
 324 void sub32(RegisterID src, RegisterID dest)
 325 {
 326 m_assembler.subu(dest, dest, src);
 327 }
 328
 329 void sub32(Imm32 imm, RegisterID dest)
 330 {
 331 if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
 332 && !m_fixedWidth) {
 333 /*
 334 addiu dest, src, imm
 335 */
 336 m_assembler.addiu(dest, dest, -imm.m_value);
 337 } else {
 338 /*
 339 li immTemp, imm
 340 subu dest, src, immTemp
 341 */
 342 move(imm, immTempRegister);
 343 m_assembler.subu(dest, dest, immTempRegister);
 344 }
 345 }
 346
 347 void sub32(Imm32 imm, Address address)
 348 {
 349 if (address.offset >= -32768 && address.offset <= 32767
 350 && !m_fixedWidth) {
 351 /*
 352 lw dataTemp, offset(base)
 353 li immTemp, imm
 354 subu dataTemp, dataTemp, immTemp
 355 sw dataTemp, offset(base)
 356 */
 357 m_assembler.lw(dataTempRegister, address.base, address.offset);
 358 if (!imm.m_isPointer
 359 && imm.m_value >= -32767 && imm.m_value <= 32768
 360 && !m_fixedWidth)
 361 m_assembler.addiu(dataTempRegister, dataTempRegister,
 362 -imm.m_value);
 363 else {
 364 move(imm, immTempRegister);
 365 m_assembler.subu(dataTempRegister, dataTempRegister,
 366 immTempRegister);
 367 }
 368 m_assembler.sw(dataTempRegister, address.base, address.offset);
 369 } else {
 370 /*
 371 lui addrTemp, (offset + 0x8000) >> 16
 372 addu addrTemp, addrTemp, base
 373 lw dataTemp, (offset & 0xffff)(addrTemp)
 374 li immtemp, imm
 375 subu dataTemp, dataTemp, immTemp
 376 sw dataTemp, (offset & 0xffff)(addrTemp)
 377 */
 378 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 379 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 380 m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
 381
 382 if (!imm.m_isPointer
 383 && imm.m_value >= -32767 && imm.m_value <= 32768
 384 && !m_fixedWidth)
 385 m_assembler.addiu(dataTempRegister, dataTempRegister,
 386 -imm.m_value);
 387 else {
 388 move(imm, immTempRegister);
 389 m_assembler.subu(dataTempRegister, dataTempRegister,
 390 immTempRegister);
 391 }
 392 m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
 393 }
 394 }
 395
 396 void sub32(Address src, RegisterID dest)
 397 {
 398 load32(src, dataTempRegister);
 399 sub32(dataTempRegister, dest);
 400 }
 401
 402 void sub32(Imm32 imm, AbsoluteAddress address)
 403 {
 404 /*
 405 li addrTemp, address
 406 li immTemp, imm
 407 lw dataTemp, 0(addrTemp)
 408 subu dataTemp, dataTemp, immTemp
 409 sw dataTemp, 0(addrTemp)
 410 */
 411 move(ImmPtr(address.m_ptr), addrTempRegister);
 412 m_assembler.lw(dataTempRegister, addrTempRegister, 0);
 413
 414 if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
 415 && !m_fixedWidth) {
 416 m_assembler.addiu(dataTempRegister, dataTempRegister,
 417 -imm.m_value);
 418 } else {
 419 move(imm, immTempRegister);
 420 m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
 421 }
 422 m_assembler.sw(dataTempRegister, addrTempRegister, 0);
 423 }
 424
 425 void xor32(RegisterID src, RegisterID dest)
 426 {
 427 m_assembler.xorInsn(dest, dest, src);
 428 }
 429
 430 void xor32(Imm32 imm, RegisterID dest)
 431 {
 432 /*
 433 li immTemp, imm
 434 xor dest, dest, immTemp
 435 */
 436 move(imm, immTempRegister);
 437 m_assembler.xorInsn(dest, dest, immTempRegister);
 438 }
 439
 440 // Memory access operations:
 441 //
 442 // Loads are of the form load(address, destination) and stores of the form
 443 // store(source, address). The source for a store may be an Imm32. Address
 444 // operand objects to loads and store will be implicitly constructed if a
 445 // register is passed.
 446
 447 void load32(ImplicitAddress address, RegisterID dest)
 448 {
 449 if (address.offset >= -32768 && address.offset <= 32767
 450 && !m_fixedWidth)
 451 m_assembler.lw(dest, address.base, address.offset);
 452 else {
 453 /*
 454 lui addrTemp, (offset + 0x8000) >> 16
 455 addu addrTemp, addrTemp, base
 456 lw dest, (offset & 0xffff)(addrTemp)
 457 */
 458 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 459 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 460 m_assembler.lw(dest, addrTempRegister, address.offset);
 461 }
 462 }
 463
 464 void load32(BaseIndex address, RegisterID dest)
 465 {
 466 if (address.offset >= -32768 && address.offset <= 32767
 467 && !m_fixedWidth) {
 468 /*
 469 sll addrTemp, address.index, address.scale
 470 addu addrTemp, addrTemp, address.base
 471 lw dest, address.offset(addrTemp)
 472 */
 473 m_assembler.sll(addrTempRegister, address.index, address.scale);
 474 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 475 m_assembler.lw(dest, addrTempRegister, address.offset);
 476 } else {
 477 /*
 478 sll addrTemp, address.index, address.scale
 479 addu addrTemp, addrTemp, address.base
 480 lui immTemp, (address.offset + 0x8000) >> 16
 481 addu addrTemp, addrTemp, immTemp
 482 lw dest, (address.offset & 0xffff)(at)
 483 */
 484 m_assembler.sll(addrTempRegister, address.index, address.scale);
 485 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 486 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
 487 m_assembler.addu(addrTempRegister, addrTempRegister,
 488 immTempRegister);
 489 m_assembler.lw(dest, addrTempRegister, address.offset);
 490 }
 491 }
 492
 493 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
 494 {
 495 if (address.offset >= -32768 && address.offset <= 32764
 496 && !m_fixedWidth) {
 497 /*
 498 sll addrTemp, address.index, address.scale
 499 addu addrTemp, addrTemp, address.base
 500 (Big-Endian)
 501 lwl dest, address.offset(addrTemp)
 502 lwr dest, address.offset+3(addrTemp)
 503 (Little-Endian)
 504 lwl dest, address.offset+3(addrTemp)
 505 lwr dest, address.offset(addrTemp)
 506 */
 507 m_assembler.sll(addrTempRegister, address.index, address.scale);
 508 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 509#if CPU(BIG_ENDIAN)
 510 m_assembler.lwl(dest, addrTempRegister, address.offset);
 511 m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
 512#else
 513 m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
 514 m_assembler.lwr(dest, addrTempRegister, address.offset);
 515
 516#endif
 517 } else {
 518 /*
 519 sll addrTemp, address.index, address.scale
 520 addu addrTemp, addrTemp, address.base
 521 lui immTemp, address.offset >> 16
 522 ori immTemp, immTemp, address.offset & 0xffff
 523 addu addrTemp, addrTemp, immTemp
 524 (Big-Endian)
 525 lw dest, 0(at)
 526 lw dest, 3(at)
 527 (Little-Endian)
 528 lw dest, 3(at)
 529 lw dest, 0(at)
 530 */
 531 m_assembler.sll(addrTempRegister, address.index, address.scale);
 532 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 533 m_assembler.lui(immTempRegister, address.offset >> 16);
 534 m_assembler.ori(immTempRegister, immTempRegister, address.offset);
 535 m_assembler.addu(addrTempRegister, addrTempRegister,
 536 immTempRegister);
 537#if CPU(BIG_ENDIAN)
 538 m_assembler.lwl(dest, addrTempRegister, 0);
 539 m_assembler.lwr(dest, addrTempRegister, 3);
 540#else
 541 m_assembler.lwl(dest, addrTempRegister, 3);
 542 m_assembler.lwr(dest, addrTempRegister, 0);
 543#endif
 544 }
 545 }
 546
 547 void load32(void* address, RegisterID dest)
 548 {
 549 /*
 550 li addrTemp, address
 551 lw dest, 0(addrTemp)
 552 */
 553 move(ImmPtr(address), addrTempRegister);
 554 m_assembler.lw(dest, addrTempRegister, 0);
 555 }
 556
 557 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
 558 {
 559 m_fixedWidth = true;
 560 /*
 561 lui addrTemp, address.offset >> 16
 562 ori addrTemp, addrTemp, address.offset & 0xffff
 563 addu addrTemp, addrTemp, address.base
 564 lw dest, 0(addrTemp)
 565 */
 566 DataLabel32 dataLabel(this);
 567 move(Imm32(address.offset), addrTempRegister);
 568 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 569 m_assembler.lw(dest, addrTempRegister, 0);
 570 m_fixedWidth = false;
 571 return dataLabel;
 572 }
 573
 574 Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
 575 {
 576 m_fixedWidth = true;
 577 /*
 578 lui addrTemp, address.offset >> 16
 579 ori addrTemp, addrTemp, address.offset & 0xffff
 580 addu addrTemp, addrTemp, address.base
 581 lw dest, 0(addrTemp)
 582 */
 583 Label label(this);
 584 move(Imm32(address.offset), addrTempRegister);
 585 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 586 m_assembler.lw(dest, addrTempRegister, 0);
 587 m_fixedWidth = false;
 588 return label;
 589 }
 590
 591 Label loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
 592 {
 593 return loadPtrWithPatchToLEA(address, dest);
 594 }
 595
 596 /* Need to use zero-extened load half-word for load16. */
 597 void load16(BaseIndex address, RegisterID dest)
 598 {
 599 if (address.offset >= -32768 && address.offset <= 32767
 600 && !m_fixedWidth) {
 601 /*
 602 sll addrTemp, address.index, address.scale
 603 addu addrTemp, addrTemp, address.base
 604 lhu dest, address.offset(addrTemp)
 605 */
 606 m_assembler.sll(addrTempRegister, address.index, address.scale);
 607 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 608 m_assembler.lhu(dest, addrTempRegister, address.offset);
 609 } else {
 610 /*
 611 sll addrTemp, address.index, address.scale
 612 addu addrTemp, addrTemp, address.base
 613 lui immTemp, (address.offset + 0x8000) >> 16
 614 addu addrTemp, addrTemp, immTemp
 615 lhu dest, (address.offset & 0xffff)(addrTemp)
 616 */
 617 m_assembler.sll(addrTempRegister, address.index, address.scale);
 618 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 619 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
 620 m_assembler.addu(addrTempRegister, addrTempRegister,
 621 immTempRegister);
 622 m_assembler.lhu(dest, addrTempRegister, address.offset);
 623 }
 624 }
 625
 626 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
 627 {
 628 m_fixedWidth = true;
 629 /*
 630 lui addrTemp, address.offset >> 16
 631 ori addrTemp, addrTemp, address.offset & 0xffff
 632 addu addrTemp, addrTemp, address.base
 633 sw src, 0(addrTemp)
 634 */
 635 DataLabel32 dataLabel(this);
 636 move(Imm32(address.offset), addrTempRegister);
 637 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 638 m_assembler.sw(src, addrTempRegister, 0);
 639 m_fixedWidth = false;
 640 return dataLabel;
 641 }
 642
 643 void store32(RegisterID src, ImplicitAddress address)
 644 {
 645 if (address.offset >= -32768 && address.offset <= 32767
 646 && !m_fixedWidth)
 647 m_assembler.sw(src, address.base, address.offset);
 648 else {
 649 /*
 650 lui addrTemp, (offset + 0x8000) >> 16
 651 addu addrTemp, addrTemp, base
 652 sw src, (offset & 0xffff)(addrTemp)
 653 */
 654 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 655 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 656 m_assembler.sw(src, addrTempRegister, address.offset);
 657 }
 658 }
 659
 660 void store32(RegisterID src, BaseIndex address)
 661 {
 662 if (address.offset >= -32768 && address.offset <= 32767
 663 && !m_fixedWidth) {
 664 /*
 665 sll addrTemp, address.index, address.scale
 666 addu addrTemp, addrTemp, address.base
 667 sw src, address.offset(addrTemp)
 668 */
 669 m_assembler.sll(addrTempRegister, address.index, address.scale);
 670 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 671 m_assembler.sw(src, addrTempRegister, address.offset);
 672 } else {
 673 /*
 674 sll addrTemp, address.index, address.scale
 675 addu addrTemp, addrTemp, address.base
 676 lui immTemp, (address.offset + 0x8000) >> 16
 677 addu addrTemp, addrTemp, immTemp
 678 sw src, (address.offset & 0xffff)(at)
 679 */
 680 m_assembler.sll(addrTempRegister, address.index, address.scale);
 681 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 682 m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
 683 m_assembler.addu(addrTempRegister, addrTempRegister,
 684 immTempRegister);
 685 m_assembler.sw(src, addrTempRegister, address.offset);
 686 }
 687 }
 688
 689 void store32(Imm32 imm, ImplicitAddress address)
 690 {
 691 if (address.offset >= -32768 && address.offset <= 32767
 692 && !m_fixedWidth) {
 693 if (!imm.m_isPointer && !imm.m_value)
 694 m_assembler.sw(MIPSRegisters::zero, address.base,
 695 address.offset);
 696 else {
 697 move(imm, immTempRegister);
 698 m_assembler.sw(immTempRegister, address.base, address.offset);
 699 }
 700 } else {
 701 /*
 702 lui addrTemp, (offset + 0x8000) >> 16
 703 addu addrTemp, addrTemp, base
 704 sw immTemp, (offset & 0xffff)(addrTemp)
 705 */
 706 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 707 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 708 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
 709 m_assembler.sw(MIPSRegisters::zero, addrTempRegister,
 710 address.offset);
 711 else {
 712 move(imm, immTempRegister);
 713 m_assembler.sw(immTempRegister, addrTempRegister,
 714 address.offset);
 715 }
 716 }
 717 }
 718
 719 void store32(RegisterID src, void* address)
 720 {
 721 /*
 722 li addrTemp, address
 723 sw src, 0(addrTemp)
 724 */
 725 move(ImmPtr(address), addrTempRegister);
 726 m_assembler.sw(src, addrTempRegister, 0);
 727 }
 728
 729 void store32(Imm32 imm, void* address)
 730 {
 731 /*
 732 li immTemp, imm
 733 li addrTemp, address
 734 sw src, 0(addrTemp)
 735 */
 736 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
 737 move(ImmPtr(address), addrTempRegister);
 738 m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
 739 } else {
 740 move(imm, immTempRegister);
 741 move(ImmPtr(address), addrTempRegister);
 742 m_assembler.sw(immTempRegister, addrTempRegister, 0);
 743 }
 744 }
 745
 746 // Floating-point operations:
 747
 748 bool supportsFloatingPoint() const
 749 {
 750#if WTF_MIPS_DOUBLE_FLOAT
 751 return true;
 752#else
 753 return false;
 754#endif
 755 }
 756
 757 bool supportsFloatingPointTruncate() const
 758 {
 759#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
 760 return true;
 761#else
 762 return false;
 763#endif
 764 }
 765
 766 // Stack manipulation operations:
 767 //
 768 // The ABI is assumed to provide a stack abstraction to memory,
 769 // containing machine word sized units of data. Push and pop
 770 // operations add and remove a single register sized unit of data
 771 // to or from the stack. Peek and poke operations read or write
 772 // values on the stack, without moving the current stack position.
 773
 774 void pop(RegisterID dest)
 775 {
 776 m_assembler.lw(dest, MIPSRegisters::sp, 0);
 777 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
 778 }
 779
 780 void push(RegisterID src)
 781 {
 782 m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
 783 m_assembler.sw(src, MIPSRegisters::sp, 0);
 784 }
 785
 786 void push(Address address)
 787 {
 788 load32(address, dataTempRegister);
 789 push(dataTempRegister);
 790 }
 791
 792 void push(Imm32 imm)
 793 {
 794 move(imm, immTempRegister);
 795 push(immTempRegister);
 796 }
 797
 798 // Register move operations:
 799 //
 800 // Move values in registers.
 801
 802 void move(Imm32 imm, RegisterID dest)
 803 {
 804 if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
 805 move(MIPSRegisters::zero, dest);
 806 else if (imm.m_isPointer || m_fixedWidth) {
 807 m_assembler.lui(dest, imm.m_value >> 16);
 808 m_assembler.ori(dest, dest, imm.m_value);
 809 } else
 810 m_assembler.li(dest, imm.m_value);
 811 }
 812
 813 void move(RegisterID src, RegisterID dest)
 814 {
 815 if (src != dest || m_fixedWidth)
 816 m_assembler.move(dest, src);
 817 }
 818
 819 void move(ImmPtr imm, RegisterID dest)
 820 {
 821 move(Imm32(imm), dest);
 822 }
 823
 824 void swap(RegisterID reg1, RegisterID reg2)
 825 {
 826 move(reg1, immTempRegister);
 827 move(reg2, reg1);
 828 move(immTempRegister, reg2);
 829 }
 830
 831 void signExtend32ToPtr(RegisterID src, RegisterID dest)
 832 {
 833 if (src != dest || m_fixedWidth)
 834 move(src, dest);
 835 }
 836
 837 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
 838 {
 839 if (src != dest || m_fixedWidth)
 840 move(src, dest);
 841 }
 842
 843 // Forwards / external control flow operations:
 844 //
 845 // This set of jump and conditional branch operations return a Jump
 846 // object which may linked at a later point, allow forwards jump,
 847 // or jumps that will require external linkage (after the code has been
 848 // relocated).
 849 //
 850 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
 851 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
 852 // used (representing the names 'below' and 'above').
 853 //
 854 // Operands to the comparision are provided in the expected order, e.g.
 855 // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
 856 // treated as a signed 32bit value, is less than or equal to 5.
 857 //
 858 // jz and jnz test whether the first operand is equal to zero, and take
 859 // an optional second operand of a mask under which to perform the test.
 860
 861 Jump branch32(Condition cond, RegisterID left, RegisterID right)
 862 {
 863 if (cond == Equal || cond == Zero)
 864 return branchEqual(left, right);
 865 if (cond == NotEqual || cond == NonZero)
 866 return branchNotEqual(left, right);
 867 if (cond == Above) {
 868 m_assembler.sltu(cmpTempRegister, right, left);
 869 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 870 }
 871 if (cond == AboveOrEqual) {
 872 m_assembler.sltu(cmpTempRegister, left, right);
 873 return branchEqual(cmpTempRegister, MIPSRegisters::zero);
 874 }
 875 if (cond == Below) {
 876 m_assembler.sltu(cmpTempRegister, left, right);
 877 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 878 }
 879 if (cond == BelowOrEqual) {
 880 m_assembler.sltu(cmpTempRegister, right, left);
 881 return branchEqual(cmpTempRegister, MIPSRegisters::zero);
 882 }
 883 if (cond == GreaterThan) {
 884 m_assembler.slt(cmpTempRegister, right, left);
 885 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 886 }
 887 if (cond == GreaterThanOrEqual) {
 888 m_assembler.slt(cmpTempRegister, left, right);
 889 return branchEqual(cmpTempRegister, MIPSRegisters::zero);
 890 }
 891 if (cond == LessThan) {
 892 m_assembler.slt(cmpTempRegister, left, right);
 893 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 894 }
 895 if (cond == LessThanOrEqual) {
 896 m_assembler.slt(cmpTempRegister, right, left);
 897 return branchEqual(cmpTempRegister, MIPSRegisters::zero);
 898 }
 899 if (cond == Overflow) {
 900 /*
 901 xor cmpTemp, left, right
 902 bgez No_overflow, cmpTemp # same sign bit -> no overflow
 903 nop
 904 subu cmpTemp, left, right
 905 xor cmpTemp, cmpTemp, left
 906 bgez No_overflow, cmpTemp # same sign bit -> no overflow
 907 nop
 908 b Overflow
 909 nop
 910 nop
 911 nop
 912 nop
 913 nop
 914 No_overflow:
 915 */
 916 m_assembler.xorInsn(cmpTempRegister, left, right);
 917 m_assembler.bgez(cmpTempRegister, 11);
 918 m_assembler.nop();
 919 m_assembler.subu(cmpTempRegister, left, right);
 920 m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
 921 m_assembler.bgez(cmpTempRegister, 7);
 922 m_assembler.nop();
 923 return jump();
 924 }
 925 if (cond == Signed) {
 926 m_assembler.subu(cmpTempRegister, left, right);
 927 // Check if the result is negative.
 928 m_assembler.slt(cmpTempRegister, cmpTempRegister,
 929 MIPSRegisters::zero);
 930 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 931 }
 932 ASSERT(0);
 933
 934 return Jump();
 935 }
 936
 937 Jump branch32(Condition cond, RegisterID left, Imm32 right)
 938 {
 939 move(right, immTempRegister);
 940 return branch32(cond, left, immTempRegister);
 941 }
 942
 943 Jump branch32(Condition cond, RegisterID left, Address right)
 944 {
 945 load32(right, dataTempRegister);
 946 return branch32(cond, left, dataTempRegister);
 947 }
 948
 949 Jump branch32(Condition cond, Address left, RegisterID right)
 950 {
 951 load32(left, dataTempRegister);
 952 return branch32(cond, dataTempRegister, right);
 953 }
 954
 955 Jump branch32(Condition cond, Address left, Imm32 right)
 956 {
 957 load32(left, dataTempRegister);
 958 move(right, immTempRegister);
 959 return branch32(cond, dataTempRegister, immTempRegister);
 960 }
 961
 962 Jump branch32(Condition cond, BaseIndex left, Imm32 right)
 963 {
 964 load32(left, dataTempRegister);
 965 // Be careful that the previous load32() uses immTempRegister.
 966 // So, we need to put move() after load32().
 967 move(right, immTempRegister);
 968 return branch32(cond, dataTempRegister, immTempRegister);
 969 }
 970
 971 Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
 972 {
 973 load32WithUnalignedHalfWords(left, dataTempRegister);
 974 // Be careful that the previous load32WithUnalignedHalfWords()
 975 // uses immTempRegister.
 976 // So, we need to put move() after load32WithUnalignedHalfWords().
 977 move(right, immTempRegister);
 978 return branch32(cond, dataTempRegister, immTempRegister);
 979 }
 980
 981 Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
 982 {
 983 load32(left.m_ptr, dataTempRegister);
 984 return branch32(cond, dataTempRegister, right);
 985 }
 986
 987 Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
 988 {
 989 load32(left.m_ptr, dataTempRegister);
 990 move(right, immTempRegister);
 991 return branch32(cond, dataTempRegister, immTempRegister);
 992 }
 993
 994 Jump branch16(Condition cond, BaseIndex left, RegisterID right)
 995 {
 996 load16(left, dataTempRegister);
 997 return branch32(cond, dataTempRegister, right);
 998 }
 999
 1000 Jump branch16(Condition cond, BaseIndex left, Imm32 right)
 1001 {
 1002 ASSERT(!(right.m_value & 0xFFFF0000));
 1003 load16(left, dataTempRegister);
 1004 // Be careful that the previous load16() uses immTempRegister.
 1005 // So, we need to put move() after load16().
 1006 move(right, immTempRegister);
 1007 return branch32(cond, dataTempRegister, immTempRegister);
 1008 }
 1009
 1010 Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
 1011 {
 1012 ASSERT((cond == Zero) || (cond == NonZero));
 1013 m_assembler.andInsn(cmpTempRegister, reg, mask);
 1014 if (cond == Zero)
 1015 return branchEqual(cmpTempRegister, MIPSRegisters::zero);
 1016 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 1017 }
 1018
 1019 Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
 1020 {
 1021 ASSERT((cond == Zero) || (cond == NonZero));
 1022 if (mask.m_value == -1 && !m_fixedWidth) {
 1023 if (cond == Zero)
 1024 return branchEqual(reg, MIPSRegisters::zero);
 1025 return branchNotEqual(reg, MIPSRegisters::zero);
 1026 }
 1027 move(mask, immTempRegister);
 1028 return branchTest32(cond, reg, immTempRegister);
 1029 }
 1030
 1031 Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
 1032 {
 1033 load32(address, dataTempRegister);
 1034 return branchTest32(cond, dataTempRegister, mask);
 1035 }
 1036
 1037 Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
 1038 {
 1039 load32(address, dataTempRegister);
 1040 return branchTest32(cond, dataTempRegister, mask);
 1041 }
 1042
 1043 Jump jump()
 1044 {
 1045 return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
 1046 }
 1047
 1048 void jump(RegisterID target)
 1049 {
 1050 m_assembler.jr(target);
 1051 m_assembler.nop();
 1052 }
 1053
 1054 void jump(Address address)
 1055 {
 1056 m_fixedWidth = true;
 1057 load32(address, MIPSRegisters::t9);
 1058 m_assembler.jr(MIPSRegisters::t9);
 1059 m_assembler.nop();
 1060 m_fixedWidth = false;
 1061 }
 1062
 1063 // Arithmetic control flow operations:
 1064 //
 1065 // This set of conditional branch operations branch based
 1066 // on the result of an arithmetic operation. The operation
 1067 // is performed as normal, storing the result.
 1068 //
 1069 // * jz operations branch if the result is zero.
 1070 // * jo operations branch if the (signed) arithmetic
 1071 // operation caused an overflow to occur.
 1072
 1073 Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
 1074 {
 1075 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 1076 if (cond == Overflow) {
 1077 /*
 1078 move dest, dataTemp
 1079 xor cmpTemp, dataTemp, src
 1080 bltz cmpTemp, No_overflow # diff sign bit -> no overflow
 1081 addu dest, dataTemp, src
 1082 xor cmpTemp, dest, dataTemp
 1083 bgez cmpTemp, No_overflow # same sign big -> no overflow
 1084 nop
 1085 b Overflow
 1086 nop
 1087 nop
 1088 nop
 1089 nop
 1090 nop
 1091 No_overflow:
 1092 */
 1093 move(dest, dataTempRegister);
 1094 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
 1095 m_assembler.bltz(cmpTempRegister, 10);
 1096 m_assembler.addu(dest, dataTempRegister, src);
 1097 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
 1098 m_assembler.bgez(cmpTempRegister, 7);
 1099 m_assembler.nop();
 1100 return jump();
 1101 }
 1102 if (cond == Signed) {
 1103 add32(src, dest);
 1104 // Check if dest is negative.
 1105 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
 1106 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 1107 }
 1108 if (cond == Zero) {
 1109 add32(src, dest);
 1110 return branchEqual(dest, MIPSRegisters::zero);
 1111 }
 1112 if (cond == NonZero) {
 1113 add32(src, dest);
 1114 return branchNotEqual(dest, MIPSRegisters::zero);
 1115 }
 1116 ASSERT(0);
 1117 return Jump();
 1118 }
 1119
 1120 Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
 1121 {
 1122 move(imm, immTempRegister);
 1123 return branchAdd32(cond, immTempRegister, dest);
 1124 }
 1125
 1126 Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
 1127 {
 1128 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 1129 if (cond == Overflow) {
 1130 /*
 1131 mult src, dest
 1132 mfhi dataTemp
 1133 mflo dest
 1134 sra addrTemp, dest, 31
 1135 beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
 1136 nop
 1137 b Overflow
 1138 nop
 1139 nop
 1140 nop
 1141 nop
 1142 nop
 1143 No_overflow:
 1144 */
 1145 m_assembler.mult(src, dest);
 1146 m_assembler.mfhi(dataTempRegister);
 1147 m_assembler.mflo(dest);
 1148 m_assembler.sra(addrTempRegister, dest, 31);
 1149 m_assembler.beq(dataTempRegister, addrTempRegister, 7);
 1150 m_assembler.nop();
 1151 return jump();
 1152 }
 1153 if (cond == Signed) {
 1154 mul32(src, dest);
 1155 // Check if dest is negative.
 1156 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
 1157 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 1158 }
 1159 if (cond == Zero) {
 1160 mul32(src, dest);
 1161 return branchEqual(dest, MIPSRegisters::zero);
 1162 }
 1163 if (cond == NonZero) {
 1164 mul32(src, dest);
 1165 return branchNotEqual(dest, MIPSRegisters::zero);
 1166 }
 1167 ASSERT(0);
 1168 return Jump();
 1169 }
 1170
 1171 Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
 1172 {
 1173 move(imm, immTempRegister);
 1174 move(src, dest);
 1175 return branchMul32(cond, immTempRegister, dest);
 1176 }
 1177
 1178 Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
 1179 {
 1180 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 1181 if (cond == Overflow) {
 1182 /*
 1183 move dest, dataTemp
 1184 xor cmpTemp, dataTemp, src
 1185 bgez cmpTemp, No_overflow # same sign bit -> no overflow
 1186 subu dest, dataTemp, src
 1187 xor cmpTemp, dest, dataTemp
 1188 bgez cmpTemp, No_overflow # same sign bit -> no overflow
 1189 nop
 1190 b Overflow
 1191 nop
 1192 nop
 1193 nop
 1194 nop
 1195 nop
 1196 No_overflow:
 1197 */
 1198 move(dest, dataTempRegister);
 1199 m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
 1200 m_assembler.bgez(cmpTempRegister, 10);
 1201 m_assembler.subu(dest, dataTempRegister, src);
 1202 m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
 1203 m_assembler.bgez(cmpTempRegister, 7);
 1204 m_assembler.nop();
 1205 return jump();
 1206 }
 1207 if (cond == Signed) {
 1208 sub32(src, dest);
 1209 // Check if dest is negative.
 1210 m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
 1211 return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
 1212 }
 1213 if (cond == Zero) {
 1214 sub32(src, dest);
 1215 return branchEqual(dest, MIPSRegisters::zero);
 1216 }
 1217 if (cond == NonZero) {
 1218 sub32(src, dest);
 1219 return branchNotEqual(dest, MIPSRegisters::zero);
 1220 }
 1221 ASSERT(0);
 1222 return Jump();
 1223 }
 1224
 1225 Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
 1226 {
 1227 move(imm, immTempRegister);
 1228 return branchSub32(cond, immTempRegister, dest);
 1229 }
 1230
 1231 // Miscellaneous operations:
 1232
 1233 void breakpoint()
 1234 {
 1235 m_assembler.bkpt();
 1236 }
 1237
 1238 Call nearCall()
 1239 {
 1240 /* We need two words for relaxation. */
 1241 m_assembler.nop();
 1242 m_assembler.nop();
 1243 m_assembler.jal();
 1244 m_assembler.nop();
 1245 return Call(m_assembler.newJmpSrc(), Call::LinkableNear);
 1246 }
 1247
 1248 Call call()
 1249 {
 1250 m_assembler.lui(MIPSRegisters::t9, 0);
 1251 m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
 1252 m_assembler.jalr(MIPSRegisters::t9);
 1253 m_assembler.nop();
 1254 return Call(m_assembler.newJmpSrc(), Call::Linkable);
 1255 }
 1256
 1257 Call call(RegisterID target)
 1258 {
 1259 m_assembler.jalr(target);
 1260 m_assembler.nop();
 1261 return Call(m_assembler.newJmpSrc(), Call::None);
 1262 }
 1263
 1264 Call call(Address address)
 1265 {
 1266 m_fixedWidth = true;
 1267 load32(address, MIPSRegisters::t9);
 1268 m_assembler.jalr(MIPSRegisters::t9);
 1269 m_assembler.nop();
 1270 m_fixedWidth = false;
 1271 return Call(m_assembler.newJmpSrc(), Call::None);
 1272 }
 1273
 1274 void ret()
 1275 {
 1276 m_assembler.jr(MIPSRegisters::ra);
 1277 m_assembler.nop();
 1278 }
 1279
 1280 void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
 1281 {
 1282 if (cond == Equal || cond == Zero) {
 1283 m_assembler.xorInsn(dest, left, right);
 1284 m_assembler.sltiu(dest, dest, 1);
 1285 } else if (cond == NotEqual || cond == NonZero) {
 1286 m_assembler.xorInsn(dest, left, right);
 1287 m_assembler.sltu(dest, MIPSRegisters::zero, dest);
 1288 } else if (cond == Above)
 1289 m_assembler.sltu(dest, right, left);
 1290 else if (cond == AboveOrEqual) {
 1291 m_assembler.sltu(dest, left, right);
 1292 m_assembler.xori(dest, dest, 1);
 1293 } else if (cond == Below)
 1294 m_assembler.sltu(dest, left, right);
 1295 else if (cond == BelowOrEqual) {
 1296 m_assembler.sltu(dest, right, left);
 1297 m_assembler.xori(dest, dest, 1);
 1298 } else if (cond == GreaterThan)
 1299 m_assembler.slt(dest, right, left);
 1300 else if (cond == GreaterThanOrEqual) {
 1301 m_assembler.slt(dest, left, right);
 1302 m_assembler.xori(dest, dest, 1);
 1303 } else if (cond == LessThan)
 1304 m_assembler.slt(dest, left, right);
 1305 else if (cond == LessThanOrEqual) {
 1306 m_assembler.slt(dest, right, left);
 1307 m_assembler.xori(dest, dest, 1);
 1308 } else if (cond == Overflow) {
 1309 /*
 1310 xor cmpTemp, left, right
 1311 bgez Done, cmpTemp # same sign bit -> no overflow
 1312 move dest, 0
 1313 subu cmpTemp, left, right
 1314 xor cmpTemp, cmpTemp, left # diff sign bit -> overflow
 1315 slt dest, cmpTemp, 0
 1316 Done:
 1317 */
 1318 m_assembler.xorInsn(cmpTempRegister, left, right);
 1319 m_assembler.bgez(cmpTempRegister, 4);
 1320 m_assembler.move(dest, MIPSRegisters::zero);
 1321 m_assembler.subu(cmpTempRegister, left, right);
 1322 m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
 1323 m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero);
 1324 } else if (cond == Signed) {
 1325 m_assembler.subu(dest, left, right);
 1326 // Check if the result is negative.
 1327 m_assembler.slt(dest, dest, MIPSRegisters::zero);
 1328 }
 1329 }
 1330
 1331 void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
 1332 {
 1333 move(right, immTempRegister);
 1334 set32(cond, left, immTempRegister, dest);
 1335 }
 1336
 1337 void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
 1338 {
 1339 ASSERT((cond == Zero) || (cond == NonZero));
 1340 load32(address, dataTempRegister);
 1341 if (mask.m_value == -1 && !m_fixedWidth) {
 1342 if (cond == Zero)
 1343 m_assembler.sltiu(dest, dataTempRegister, 1);
 1344 else
 1345 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
 1346 } else {
 1347 move(mask, immTempRegister);
 1348 m_assembler.andInsn(cmpTempRegister, dataTempRegister,
 1349 immTempRegister);
 1350 if (cond == Zero)
 1351 m_assembler.sltiu(dest, cmpTempRegister, 1);
 1352 else
 1353 m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
 1354 }
 1355 }
 1356
 1357 DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest)
 1358 {
 1359 m_fixedWidth = true;
 1360 DataLabel32 label(this);
 1361 move(imm, dest);
 1362 m_fixedWidth = false;
 1363 return label;
 1364 }
 1365
 1366 DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
 1367 {
 1368 m_fixedWidth = true;
 1369 DataLabelPtr label(this);
 1370 move(initialValue, dest);
 1371 m_fixedWidth = false;
 1372 return label;
 1373 }
 1374
 1375 Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
 1376 {
 1377 m_fixedWidth = true;
 1378 dataLabel = moveWithPatch(initialRightValue, immTempRegister);
 1379 Jump temp = branch32(cond, left, immTempRegister);
 1380 m_fixedWidth = false;
 1381 return temp;
 1382 }
 1383
 1384 Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
 1385 {
 1386 m_fixedWidth = true;
 1387 load32(left, dataTempRegister);
 1388 dataLabel = moveWithPatch(initialRightValue, immTempRegister);
 1389 Jump temp = branch32(cond, dataTempRegister, immTempRegister);
 1390 m_fixedWidth = false;
 1391 return temp;
 1392 }
 1393
 1394 DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
 1395 {
 1396 m_fixedWidth = true;
 1397 DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
 1398 store32(dataTempRegister, address);
 1399 m_fixedWidth = false;
 1400 return dataLabel;
 1401 }
 1402
 1403 DataLabelPtr storePtrWithPatch(ImplicitAddress address)
 1404 {
 1405 return storePtrWithPatch(ImmPtr(0), address);
 1406 }
 1407
 1408 Call tailRecursiveCall()
 1409 {
 1410 // Like a normal call, but don't update the returned address register
 1411 m_fixedWidth = true;
 1412 move(Imm32(0), MIPSRegisters::t9);
 1413 m_assembler.jr(MIPSRegisters::t9);
 1414 m_assembler.nop();
 1415 m_fixedWidth = false;
 1416 return Call(m_assembler.newJmpSrc(), Call::Linkable);
 1417 }
 1418
 1419 Call makeTailRecursiveCall(Jump oldJump)
 1420 {
 1421 oldJump.link(this);
 1422 return tailRecursiveCall();
 1423 }
 1424
 1425 void loadDouble(ImplicitAddress address, FPRegisterID dest)
 1426 {
 1427#if WTF_MIPS_ISA(1)
 1428 /*
 1429 li addrTemp, address.offset
 1430 addu addrTemp, addrTemp, base
 1431 lwc1 dest, 0(addrTemp)
 1432 lwc1 dest+1, 4(addrTemp)
 1433 */
 1434 move(Imm32(address.offset), addrTempRegister);
 1435 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 1436 m_assembler.lwc1(dest, addrTempRegister, 0);
 1437 m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
 1438#else
 1439 if (address.offset >= -32768 && address.offset <= 32767
 1440 && !m_fixedWidth) {
 1441 m_assembler.ldc1(dest, address.base, address.offset);
 1442 } else {
 1443 /*
 1444 lui addrTemp, (offset + 0x8000) >> 16
 1445 addu addrTemp, addrTemp, base
 1446 ldc1 dest, (offset & 0xffff)(addrTemp)
 1447 */
 1448 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 1449 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 1450 m_assembler.ldc1(dest, addrTempRegister, address.offset);
 1451 }
 1452#endif
 1453 }
 1454
 1455 void storeDouble(FPRegisterID src, ImplicitAddress address)
 1456 {
 1457#if WTF_MIPS_ISA(1)
 1458 /*
 1459 li addrTemp, address.offset
 1460 addu addrTemp, addrTemp, base
 1461 swc1 dest, 0(addrTemp)
 1462 swc1 dest+1, 4(addrTemp)
 1463 */
 1464 move(Imm32(address.offset), addrTempRegister);
 1465 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 1466 m_assembler.swc1(src, addrTempRegister, 0);
 1467 m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
 1468#else
 1469 if (address.offset >= -32768 && address.offset <= 32767
 1470 && !m_fixedWidth)
 1471 m_assembler.sdc1(src, address.base, address.offset);
 1472 else {
 1473 /*
 1474 lui addrTemp, (offset + 0x8000) >> 16
 1475 addu addrTemp, addrTemp, base
 1476 sdc1 src, (offset & 0xffff)(addrTemp)
 1477 */
 1478 m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
 1479 m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
 1480 m_assembler.sdc1(src, addrTempRegister, address.offset);
 1481 }
 1482#endif
 1483 }
 1484
 1485 void addDouble(FPRegisterID src, FPRegisterID dest)
 1486 {
 1487 m_assembler.addd(dest, dest, src);
 1488 }
 1489
 1490 void addDouble(Address src, FPRegisterID dest)
 1491 {
 1492 loadDouble(src, fpTempRegister);
 1493 m_assembler.addd(dest, dest, fpTempRegister);
 1494 }
 1495
 1496 void subDouble(FPRegisterID src, FPRegisterID dest)
 1497 {
 1498 m_assembler.subd(dest, dest, src);
 1499 }
 1500
 1501 void subDouble(Address src, FPRegisterID dest)
 1502 {
 1503 loadDouble(src, fpTempRegister);
 1504 m_assembler.subd(dest, dest, fpTempRegister);
 1505 }
 1506
 1507 void mulDouble(FPRegisterID src, FPRegisterID dest)
 1508 {
 1509 m_assembler.muld(dest, dest, src);
 1510 }
 1511
 1512 void mulDouble(Address src, FPRegisterID dest)
 1513 {
 1514 loadDouble(src, fpTempRegister);
 1515 m_assembler.muld(dest, dest, fpTempRegister);
 1516 }
 1517
 1518 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
 1519 {
 1520 m_assembler.mtc1(src, fpTempRegister);
 1521 m_assembler.cvtdw(dest, fpTempRegister);
 1522 }
 1523
 1524 void insertRelaxationWords()
 1525 {
 1526 /* We need four words for relaxation. */
 1527 m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
 1528 m_assembler.nop();
 1529 m_assembler.nop();
 1530 m_assembler.nop();
 1531 }
 1532
 1533 Jump branchTrue()
 1534 {
 1535 m_assembler.appendJump();
 1536 m_assembler.bc1t();
 1537 m_assembler.nop();
 1538 insertRelaxationWords();
 1539 return Jump(m_assembler.newJmpSrc());
 1540 }
 1541
 1542 Jump branchFalse()
 1543 {
 1544 m_assembler.appendJump();
 1545 m_assembler.bc1f();
 1546 m_assembler.nop();
 1547 insertRelaxationWords();
 1548 return Jump(m_assembler.newJmpSrc());
 1549 }
 1550
 1551 Jump branchEqual(RegisterID rs, RegisterID rt)
 1552 {
 1553 m_assembler.appendJump();
 1554 m_assembler.beq(rs, rt, 0);
 1555 m_assembler.nop();
 1556 insertRelaxationWords();
 1557 return Jump(m_assembler.newJmpSrc());
 1558 }
 1559
 1560 Jump branchNotEqual(RegisterID rs, RegisterID rt)
 1561 {
 1562 m_assembler.appendJump();
 1563 m_assembler.bne(rs, rt, 0);
 1564 m_assembler.nop();
 1565 insertRelaxationWords();
 1566 return Jump(m_assembler.newJmpSrc());
 1567 }
 1568
 1569 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
 1570 {
 1571 if (cond == DoubleEqual) {
 1572 m_assembler.ceqd(left, right);
 1573 return branchTrue();
 1574 }
 1575 if (cond == DoubleNotEqual) {
 1576 m_assembler.ceqd(left, right);
 1577 return branchFalse(); // false
 1578 }
 1579 if (cond == DoubleGreaterThan) {
 1580 m_assembler.cngtd(left, right);
 1581 return branchFalse(); // false
 1582 }
 1583 if (cond == DoubleGreaterThanOrEqual) {
 1584 m_assembler.cnged(right, left);
 1585 return branchFalse(); // false
 1586 }
 1587 if (cond == DoubleLessThan) {
 1588 m_assembler.cltd(left, right);
 1589 return branchTrue();
 1590 }
 1591 if (cond == DoubleLessThanOrEqual) {
 1592 m_assembler.cled(left, right);
 1593 return branchTrue();
 1594 }
 1595 if (cond == DoubleEqualOrUnordered) {
 1596 m_assembler.cueqd(left, right);
 1597 return branchTrue();
 1598 }
 1599 if (cond == DoubleGreaterThanOrUnordered) {
 1600 m_assembler.coled(left, right);
 1601 return branchFalse(); // false
 1602 }
 1603 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
 1604 m_assembler.coltd(left, right);
 1605 return branchFalse(); // false
 1606 }
 1607 if (cond == DoubleLessThanOrUnordered) {
 1608 m_assembler.cultd(left, right);
 1609 return branchTrue();
 1610 }
 1611 if (cond == DoubleLessThanOrEqualOrUnordered) {
 1612 m_assembler.culed(left, right);
 1613 return branchTrue();
 1614 }
 1615 ASSERT(0);
 1616
 1617 return Jump();
 1618 }
 1619
 1620 // Truncates 'src' to an integer, and places the resulting 'dest'.
 1621 // If the result is not representable as a 32 bit value, branch.
 1622 // May also branch for some values that are representable in 32 bits
 1623 // (specifically, in this case, INT_MAX 0x7fffffff).
 1624 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
 1625 {
 1626 m_assembler.truncwd(fpTempRegister, src);
 1627 m_assembler.mfc1(dest, fpTempRegister);
 1628 return branch32(Equal, dest, Imm32(0x7fffffff));
 1629 }
 1630
 1631private:
 1632 // If m_fixedWidth is true, we will generate a fixed number of instructions.
 1633 // Otherwise, we can emit any number of instructions.
 1634 bool m_fixedWidth;
 1635
 1636 friend class LinkBuffer;
 1637 friend class RepatchBuffer;
 1638
 1639 static void linkCall(void* code, Call call, FunctionPtr function)
 1640 {
 1641 MIPSAssembler::linkCall(code, call.m_jmp, function.value());
 1642 }
 1643
 1644 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
 1645 {
 1646 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
 1647 }
 1648
 1649 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
 1650 {
 1651 MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
 1652 }
 1653
 1654};
 1655
 1656}
 1657
 1658#endif // ENABLE(ASSEMBLER) && CPU(MIPS)
 1659
 1660#endif // MacroAssemblerMIPS_h
0

JavaScriptCore/jit/ExecutableAllocator.h

4343#include <e32std.h>
4444#endif
4545
 46#if CPU(MIPS) && OS(LINUX)
 47#include <sys/cachectl.h>
 48#endif
 49
4650#if OS(WINCE)
4751// From pkfuncs.h (private header file from the Platform Builder)
4852#define CACHE_SYNC_ALL 0x07F

@@public:
190194 static void cacheFlush(void*, size_t)
191195 {
192196 }
 197#elif CPU(MIPS)
 198 static void cacheFlush(void* code, size_t size)
 199 {
 200#if COMPILER(GCC) && (GCC_VERSION >= 40300)
 201#if WTF_MIPS_ISA_REV(2) && (GCC_VERSION < 40403)
 202 int lineSize;
 203 asm("rdhwr %0, $1" : "=r" (lineSize));
 204 //
 205 // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
 206 // mips_expand_synci_loop that may execute synci one more time.
 207 // "start" points to the fisrt byte of the cache line.
 208 // "end" points to the last byte of the line before the last cache line.
 209 // Because size is always a multiple of 4, this is safe to set
 210 // "end" to the last byte.
 211 //
 212 intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize);
 213 intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1;
 214 __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
 215#else
 216 intptr_t end = reinterpret_cast<intptr_t>(code) + size;
 217 __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
 218#endif
 219#else
 220 _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
 221#endif
 222 }
193223#elif CPU(ARM_THUMB2) && OS(IPHONE_OS)
194224 static void cacheFlush(void* code, size_t size)
195225 {
55195

JavaScriptCore/wtf/Platform.h

104104#define WTF_CPU_IA64 1
105105#endif
106106
 107/* CPU(MIPS) - MIPS 32-bit */
 108/* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now. */
 109#if (defined(mips) || defined(__mips__)) \
 110 && defined(_ABIO32)
 111#define WTF_CPU_MIPS 1
 112#if defined(__MIPSEB__)
 113#define WTF_CPU_BIG_ENDIAN 1
 114#endif
 115#define WTF_MIPS_PIC (defined __PIC__)
 116#define WTF_MIPS_ARCH __mips
 117#define WTF_MIPS_ISA(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH == v)
 118#define WTF_MIPS_ISA_AT_LEAST(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH >= v)
 119#define WTF_MIPS_ARCH_REV __mips_isa_rev
 120#define WTF_MIPS_ISA_REV(v) (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == v)
 121#define WTF_MIPS_DOUBLE_FLOAT (defined __mips_hard_float && !defined __mips_single_float)
 122#endif /* MIPS */
 123
107124/* CPU(PPC) - PowerPC 32-bit */
108125#if defined(__ppc__) \
109126 || defined(__PPC__) \

830847#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
831848#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) || CPU(IA64) || CPU(ALPHA)
832849#define WTF_USE_JSVALUE64 1
833 #elif CPU(ARM) || CPU(PPC64)
 850#elif CPU(ARM) || CPU(PPC64) || CPU(MIPS)
834851#define WTF_USE_JSVALUE32 1
835852#elif OS(WINDOWS) && COMPILER(MINGW)
836853/* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg

@@on MinGW. See https://bugs.webkit.org/sh
950967 || (CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)) \
951968 || (CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100) \
952969 || (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) \
953  || (CPU(ARM_TRADITIONAL) && OS(LINUX))
 970 || (CPU(ARM_TRADITIONAL) && OS(LINUX)) \
 971 || (CPU(MIPS) && OS(LINUX))
954972#define ENABLE_YARR 1
955973#define ENABLE_YARR_JIT 1
956974#endif
55195

JavaScriptCore/yarr/RegexJIT.cpp

@@class RegexGenerator : private MacroAsse
5454 static const RegisterID regT1 = ARMRegisters::r6;
5555
5656 static const RegisterID returnRegister = ARMRegisters::r0;
 57#elif CPU(MIPS)
 58 static const RegisterID input = MIPSRegisters::a0;
 59 static const RegisterID index = MIPSRegisters::a1;
 60 static const RegisterID length = MIPSRegisters::a2;
 61 static const RegisterID output = MIPSRegisters::a3;
 62
 63 static const RegisterID regT0 = MIPSRegisters::t4;
 64 static const RegisterID regT1 = MIPSRegisters::t5;
 65
 66 static const RegisterID returnRegister = MIPSRegisters::v0;
5767#elif CPU(X86)
5868 static const RegisterID input = X86Registers::eax;
5969 static const RegisterID index = X86Registers::edx;

@@class RegexGenerator : private MacroAsse
13131323 push(ARMRegisters::r5);
13141324 push(ARMRegisters::r6);
13151325 move(ARMRegisters::r3, output);
 1326#elif CPU(MIPS)
 1327 // Do nothing.
13161328#endif
13171329 }
13181330

@@class RegexGenerator : private MacroAsse
13301342 pop(ARMRegisters::r6);
13311343 pop(ARMRegisters::r5);
13321344 pop(ARMRegisters::r4);
 1345#elif CPU(MIPS)
 1346 // Do nothing
13331347#endif
13341348 ret();
13351349 }
55195