wtf/Platform.h

236236#define WTF_PLATFORM_BIG_ENDIAN 1
237237#endif
238238
 239/* PLATFORM(MIPS) */
 240/* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now. */
 241#if (defined(mips) || defined(__mips__)) && defined(_ABIO32)
 242#define WTF_PLATFORM_MIPS 1
 243#if defined(__MIPSEB__)
 244#define WTF_PLATFORM_BIG_ENDIAN 1
 245#endif
 246#endif /* MIPS */
 247
239248/* PLATFORM(ARM) */
240249#define PLATFORM_ARM_ARCH(N) (PLATFORM(ARM) && ARM_ARCH_VERSION >= N)
241250

748757#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
749758#if PLATFORM(X86_64) && (PLATFORM(DARWIN) || PLATFORM(LINUX) || PLATFORM(WIN_OS))
750759#define WTF_USE_JSVALUE64 1
751 #elif PLATFORM(ARM) || PLATFORM(PPC64)
 760#elif PLATFORM(ARM) || PLATFORM(PPC64) || PLATFORM(MIPS)
752761#define WTF_USE_JSVALUE32 1
753762#elif PLATFORM(WIN_OS) && COMPILER(MINGW)
754763/* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg

796805 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
797806#elif PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX)
798807 #define ENABLE_JIT 1
 808#elif PLATFORM(MIPS) && PLATFORM(LINUX)
 809 #define ENABLE_JIT 0
 810 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0
799811#endif
800812#endif /* PLATFORM(QT) */
801813

850862#if (PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \
851863 || (PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MSVC)) \
852864 || (PLATFORM(X86) && PLATFORM(LINUX) && GCC_VERSION >= 40100) \
853  || (PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX))
 865 || (PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX)) \
 866 || (PLATFORM(MIPS) && PLATFORM(LINUX))
854867#define ENABLE_YARR 1
855868#define ENABLE_YARR_JIT 1
856869#endif
51552

yarr/RegexJIT.cpp

5454 static const RegisterID regT1 = ARMRegisters::r6;
5555
5656 static const RegisterID returnRegister = ARMRegisters::r0;
 57#elif PLATFORM(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 PLATFORM(X86)
5868 static const RegisterID input = X86Registers::eax;
5969 static const RegisterID index = X86Registers::edx;

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

13301342 pop(ARMRegisters::r6);
13311343 pop(ARMRegisters::r5);
13321344 pop(ARMRegisters::r4);
 1345#elif PLATFORM(MIPS)
 1346 // Do nothing
13331347#endif
13341348 ret();
13351349 }
51552

assembler/MacroAssembler.h

3838#include "MacroAssemblerARM.h"
3939namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
4040
 41#elif PLATFORM(MIPS)
 42#include "MacroAssemblerMIPS.h"
 43namespace JSC { typedef MacroAssemblerMIPS MacroAssemblerBase; };
 44
4145#elif PLATFORM(X86)
4246#include "MacroAssemblerX86.h"
4347namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
51552

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) 2009 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#include <wtf/SegmentedVector.h>
 34
 35#if ENABLE(ASSEMBLER) && PLATFORM(MIPS)
 36
 37#include "AssemblerBuffer.h"
 38#include <wtf/Assertions.h>
 39
 40namespace JSC {
 41
 42typedef uint32_t MIPSWord;
 43
 44namespace MIPSRegisters {
 45 typedef 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
 112 typedef 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* old_base = m_buffer.data();
 214
 215 m_buffer.putInt(op);
 216
 217 void* new_base = m_buffer.data();
 218 if (old_base != new_base) {
 219 relocateJumps(old_base, new_base);
 220 }
 221 }
 222
 223 void nop()
 224 {
 225 emitInst(0x00000000);
 226 }
 227
 228 /* Need to insert one load data delay nop for mips1. */
 229 void loadDelayNop()
 230 {
 231#if __mips == 1
 232 nop();
 233#endif
 234 }
 235
 236 /* Need to insert one coprocessor access delay nop for mips1. */
 237 void copDelayNop()
 238 {
 239#if __mips == 1
 240 nop();
 241#endif
 242 }
 243
 244 void move(RegisterID rd, RegisterID rs)
 245 {
 246#if defined(_ABIO32)
 247 /* addu */
 248 emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS));
 249#else
 250 /* daddu */
 251 emitInst(0x0000002d | (rd << OP_SH_RD) | (rs << OP_SH_RS));
 252#endif
 253 }
 254
 255 /* Set an immediate value to a register. This may generate 1 or 2
 256 instructions. */
 257 void li(RegisterID dest, int imm)
 258 {
 259 if (imm >= -32768 && imm <= 32767)
 260 addiu(dest, MIPSRegisters::zero, imm);
 261 else if (imm >= 0 && imm < 65536)
 262 ori(dest, MIPSRegisters::zero, imm);
 263 else {
 264 lui(dest, imm >> 16);
 265 if (imm & 0xffff)
 266 ori(dest, dest, imm);
 267 }
 268 }
 269
 270 void lui(RegisterID rt, int imm)
 271 {
 272 emitInst(0x3c000000 | (rt << OP_SH_RT) | (imm & 0xffff));
 273 }
 274
 275 void addiu(RegisterID rt, RegisterID rs, int imm)
 276 {
 277 emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 278 | (imm & 0xffff));
 279 }
 280
 281 void addu(RegisterID rd, RegisterID rs, RegisterID rt)
 282 {
 283 emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 284 | (rt << OP_SH_RT));
 285 }
 286
 287 void subu(RegisterID rd, RegisterID rs, RegisterID rt)
 288 {
 289 emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 290 | (rt << OP_SH_RT));
 291 }
 292
 293 void mult(RegisterID rs, RegisterID rt)
 294 {
 295 emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
 296 }
 297
 298 void mfhi(RegisterID rd)
 299 {
 300 emitInst(0x00000010 | (rd << OP_SH_RD));
 301 }
 302
 303 void mflo(RegisterID rd)
 304 {
 305 emitInst(0x00000012 | (rd << OP_SH_RD));
 306 }
 307
 308 void mul(RegisterID rd, RegisterID rs, RegisterID rt)
 309 {
 310#if __mips >= 32
 311 emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 312 | (rt << OP_SH_RT));
 313#else
 314 mult(rs, rt);
 315 mflo(rd);
 316#endif
 317 }
 318
 319 void and_insn(RegisterID rd, RegisterID rs, RegisterID rt)
 320 {
 321 emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 322 | (rt << OP_SH_RT));
 323 }
 324
 325 void andi(RegisterID rt, RegisterID rs, int imm)
 326 {
 327 emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 328 | (imm & 0xffff));
 329 }
 330
 331 void nor(RegisterID rd, RegisterID rs, RegisterID rt)
 332 {
 333 emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 334 | (rt << OP_SH_RT));
 335 }
 336
 337 void or_insn(RegisterID rd, RegisterID rs, RegisterID rt)
 338 {
 339 emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 340 | (rt << OP_SH_RT));
 341 }
 342
 343 void ori(RegisterID rt, RegisterID rs, int imm)
 344 {
 345 emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 346 | (imm & 0xffff));
 347 }
 348
 349 void xor_insn(RegisterID rd, RegisterID rs, RegisterID rt)
 350 {
 351 emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 352 | (rt << OP_SH_RT));
 353 }
 354
 355 void xori(RegisterID rt, RegisterID rs, int imm)
 356 {
 357 emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 358 | (imm & 0xffff));
 359 }
 360
 361 void slt(RegisterID rd, RegisterID rs, RegisterID rt)
 362 {
 363 emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 364 | (rt << OP_SH_RT));
 365 }
 366
 367 void sltu(RegisterID rd, RegisterID rs, RegisterID rt)
 368 {
 369 emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS)
 370 | (rt << OP_SH_RT));
 371 }
 372
 373 void sltiu(RegisterID rt, RegisterID rs, int imm)
 374 {
 375 emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 376 | (imm & 0xffff));
 377 }
 378
 379 void sll(RegisterID rd, RegisterID rt, int shamt)
 380 {
 381 emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 382 | ((shamt & 0x1f) << OP_SH_SHAMT));
 383 }
 384
 385 void sllv(RegisterID rd, RegisterID rt, int rs)
 386 {
 387 emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 388 | (rs << OP_SH_RS));
 389 }
 390
 391 void sra(RegisterID rd, RegisterID rt, int shamt)
 392 {
 393 emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 394 | ((shamt & 0x1f) << OP_SH_SHAMT));
 395 }
 396
 397 void srav(RegisterID rd, RegisterID rt, RegisterID rs)
 398 {
 399 emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
 400 | (rs << OP_SH_RS));
 401 }
 402
 403 void lw(RegisterID rt, RegisterID rs, int offset)
 404 {
 405 emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 406 | (offset & 0xffff));
 407 loadDelayNop();
 408 }
 409
 410 void lwl(RegisterID rt, RegisterID rs, int offset)
 411 {
 412 emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 413 | (offset & 0xffff));
 414 loadDelayNop();
 415 }
 416
 417 void lwr(RegisterID rt, RegisterID rs, int offset)
 418 {
 419 emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 420 | (offset & 0xffff));
 421 loadDelayNop();
 422 }
 423
 424 void lhu(RegisterID rt, RegisterID rs, int offset)
 425 {
 426 emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 427 | (offset & 0xffff));
 428 loadDelayNop();
 429 }
 430
 431 void sw(RegisterID rt, RegisterID rs, int offset)
 432 {
 433 emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
 434 | (offset & 0xffff));
 435 }
 436
 437 void jr(RegisterID rs)
 438 {
 439 emitInst(0x00000008 | (rs << OP_SH_RS));
 440 }
 441
 442 void jalr(RegisterID rs)
 443 {
 444 emitInst(0x0000f809 | (rs << OP_SH_RS));
 445 }
 446
 447 void jal()
 448 {
 449 emitInst(0x0c000000);
 450 }
 451
 452 void bkpt()
 453 {
 454 int value = 512; /* BRK_BUG */
 455 emitInst(0x0000000d | ((value & 0x3ff) << OP_SH_CODE));
 456 }
 457
 458 void bgez(RegisterID rs, int imm)
 459 {
 460 emitInst(0x04010000 | (rs << OP_SH_RS) | (imm & 0xffff));
 461 }
 462
 463 void bltz(RegisterID rs, int imm)
 464 {
 465 emitInst(0x04000000 | (rs << OP_SH_RS) | (imm & 0xffff));
 466 }
 467
 468 void beq(RegisterID rs, RegisterID rt, int imm)
 469 {
 470 emitInst(0x10000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
 471 }
 472
 473 void bne(RegisterID rs, RegisterID rt, int imm)
 474 {
 475 emitInst(0x14000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
 476 }
 477
 478 void bc1t()
 479 {
 480 emitInst(0x45010000);
 481 }
 482
 483 void bc1f()
 484 {
 485 emitInst(0x45000000);
 486 }
 487
 488 JmpSrc newJmpSrc()
 489 {
 490 return JmpSrc(m_buffer.size());
 491 }
 492
 493 void appendJump()
 494 {
 495 m_jumps.append(m_buffer.size());
 496 }
 497
 498 void add_d(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 499 {
 500 emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 501 | (ft << OP_SH_FT));
 502 }
 503
 504 void sub_d(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 505 {
 506 emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 507 | (ft << OP_SH_FT));
 508 }
 509
 510 void mul_d(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
 511 {
 512 emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
 513 | (ft << OP_SH_FT));
 514 }
 515
 516 void lwc1(FPRegisterID ft, RegisterID rs, int offset)
 517 {
 518 emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 519 | (offset & 0xffff));
 520 copDelayNop();
 521 }
 522
 523 void ldc1(FPRegisterID ft, RegisterID rs, int offset)
 524 {
 525 emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 526 | (offset & 0xffff));
 527 }
 528
 529 void swc1(FPRegisterID ft, RegisterID rs, int offset)
 530 {
 531 emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 532 | (offset & 0xffff));
 533 }
 534
 535 void sdc1(FPRegisterID ft, RegisterID rs, int offset)
 536 {
 537 emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
 538 | (offset & 0xffff));
 539 }
 540
 541 void mtc1(RegisterID rt, FPRegisterID fs)
 542 {
 543 emitInst(0x44800000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
 544 copDelayNop();
 545 }
 546
 547 void mfc1(RegisterID rt, FPRegisterID fs)
 548 {
 549 emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
 550 copDelayNop();
 551 }
 552
 553 void trunc_w_d(FPRegisterID fd, FPRegisterID fs)
 554 {
 555 emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
 556 }
 557
 558 void cvt_d_w(FPRegisterID fd, FPRegisterID fs)
 559 {
 560 emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
 561 }
 562
 563 void c_eq_d(FPRegisterID fs, FPRegisterID ft)
 564 {
 565 emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 566 copDelayNop();
 567 }
 568
 569 void c_ngt_d(FPRegisterID fs, FPRegisterID ft)
 570 {
 571 emitInst(0x4620003f | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 572 copDelayNop();
 573 }
 574
 575 void c_nge_d(FPRegisterID fs, FPRegisterID ft)
 576 {
 577 emitInst(0x4620003d | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 578 copDelayNop();
 579 }
 580
 581 void c_lt_d(FPRegisterID fs, FPRegisterID ft)
 582 {
 583 emitInst(0x4620003c | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 584 copDelayNop();
 585 }
 586
 587 void c_le_d(FPRegisterID fs, FPRegisterID ft)
 588 {
 589 emitInst(0x4620003e | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 590 copDelayNop();
 591 }
 592
 593 void c_ueq_d(FPRegisterID fs, FPRegisterID ft)
 594 {
 595 emitInst(0x46200033 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 596 copDelayNop();
 597 }
 598
 599 void c_ole_d(FPRegisterID fs, FPRegisterID ft)
 600 {
 601 emitInst(0x46200036 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 602 copDelayNop();
 603 }
 604
 605 void c_olt_d(FPRegisterID fs, FPRegisterID ft)
 606 {
 607 emitInst(0x46200034 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 608 copDelayNop();
 609 }
 610
 611 void c_ule_d(FPRegisterID fs, FPRegisterID ft)
 612 {
 613 emitInst(0x46200037 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 614 copDelayNop();
 615 }
 616
 617 void c_ult_d(FPRegisterID fs, FPRegisterID ft)
 618 {
 619 emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
 620 copDelayNop();
 621 }
 622
 623 // General helpers
 624
 625 JmpDst label()
 626 {
 627 return JmpDst(m_buffer.size());
 628 }
 629
 630 JmpDst align(int alignment)
 631 {
 632 while (!m_buffer.isAligned(alignment))
 633 bkpt();
 634
 635 return label();
 636 }
 637
 638 static void* getRelocatedAddress(void* code, JmpSrc jump)
 639 {
 640 ASSERT(jump.m_offset != -1);
 641 void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + jump.m_offset);
 642 return b;
 643 }
 644
 645 static void* getRelocatedAddress(void* code, JmpDst label)
 646 {
 647 void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + label.m_offset);
 648 return b;
 649 }
 650
 651 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
 652 {
 653 return to.m_offset - from.m_offset;
 654 }
 655
 656 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
 657 {
 658 return to.m_offset - from.m_offset;
 659 }
 660
 661 static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to)
 662 {
 663 return to.m_offset - from.m_offset;
 664 }
 665
 666 // Assembler admin methods:
 667
 668 size_t size() const
 669 {
 670 return m_buffer.size();
 671 }
 672
 673 void* executableCopy(ExecutablePool* allocator)
 674 {
 675 void *result = m_buffer.executableCopy(allocator);
 676 if (!result)
 677 return 0;
 678
 679 relocateJumps(m_buffer.data(), result);
 680 return result;
 681 }
 682
 683 static unsigned getCallReturnOffset(JmpSrc call)
 684 {
 685 // The return address is after a call and a delay slot instruction
 686 return call.m_offset;
 687 }
 688
 689 // Linking & patching:
 690 //
 691 // 'link' and 'patch' methods are for use on unprotected code - such as the code
 692 // within the AssemblerBuffer, and code being patched by the patch buffer. Once
 693 // code has been finalized it is (platform support permitting) within a non-
 694 // writable region of memory; to modify the code in an execute-only execuable
 695 // pool the 'repatch' and 'relink' methods should be used.
 696
 697 void linkJump(JmpSrc from, JmpDst to)
 698 {
 699 ASSERT(to.m_offset != -1);
 700 ASSERT(from.m_offset != -1);
 701 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset);
 702 MIPSWord* to_pos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset);
 703
 704 ASSERT(*(insn - 1) == 0 && *(insn - 2) == 0 && *(insn - 3) == 0 && *(insn - 5) == 0);
 705 insn = insn - 6;
 706 linkWithOffset(insn, to_pos);
 707 }
 708
 709 static void linkJump(void* code, JmpSrc from, void* to)
 710 {
 711 ASSERT(from.m_offset != -1);
 712 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 713
 714 ASSERT(*(insn - 1) == 0 && *(insn - 2) == 0 && *(insn - 3) == 0 && *(insn - 5) == 0);
 715 insn = insn - 6;
 716 linkWithOffset(insn, to);
 717 }
 718
 719 static void linkCall(void* code, JmpSrc from, void* to)
 720 {
 721 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 722 linkCallInternal(insn, to);
 723 }
 724
 725 static void linkPointer(void* code, JmpDst from, void* to)
 726 {
 727 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 728 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 729 *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 730 insn++;
 731 ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
 732 *insn = (*insn & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 733 }
 734
 735 static void relinkJump(void* from, void* to)
 736 {
 737 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 738
 739 ASSERT(*(insn - 1) == 0 && *(insn - 5) == 0);
 740 insn = insn - 6;
 741 int flush_size = linkWithOffset(insn, to);
 742
 743 ExecutableAllocator::cacheFlush(insn, flush_size);
 744 }
 745
 746 static void relinkCall(void* from, void* to)
 747 {
 748 void* start;
 749 int size = linkCallInternal(from, to);
 750 if (size == sizeof(MIPSWord))
 751 start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 2 * sizeof(MIPSWord));
 752 else
 753 start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
 754
 755 ExecutableAllocator::cacheFlush(start, size);
 756 }
 757
 758 static void repatchInt32(void* from, int32_t to)
 759 {
 760 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 761 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 762 *insn = (*insn & 0xffff0000) | ((to >> 16) & 0xffff);
 763 insn++;
 764 ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
 765 *insn = (*insn & 0xffff0000) | (to & 0xffff);
 766 insn--;
 767 ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
 768 }
 769
 770 static void repatchPointer(void* from, void* to)
 771 {
 772 repatchInt32(from, reinterpret_cast<int32_t>(to));
 773 }
 774
 775 static void repatchLoadPtrToLEA(void* from)
 776 {
 777 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 778 insn = insn + 3;
 779 ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw
 780 /* lw -> addiu */
 781 *insn = 0x24000000 | (*insn & 0x03ffffff);
 782
 783 ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
 784 }
 785
 786private:
 787
 788 /* Update each jump in the buffer of new_base. */
 789 void relocateJumps(void* old_base, void* new_base)
 790 {
 791 // Check each jump
 792 for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
 793 int pos = *iter;
 794 MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(new_base) + pos);
 795 insn = insn + 2;
 796 // Need to make sure we have 5 valid instructions after pos
 797 if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord))
 798 continue;
 799
 800 if ((*insn & 0xfc000000) == 0x08000000) { // j
 801 int offset = *insn & 0x03ffffff;
 802 int old_insn_address = (int)insn - (int)new_base + (int)old_base;
 803 int top_four_bits = (old_insn_address + 4) >> 28;
 804 int old_target_address = (top_four_bits << 28) | (offset << 2);
 805 int new_target_address = old_target_address - (int)old_base + (int)new_base;
 806 int new_insn_address = (int)insn;
 807 if (((new_insn_address + 4) >> 28) == (new_target_address >> 28)) {
 808 *insn = 0x08000000 | ((new_target_address >> 2) & 0x3ffffff);
 809 } else {
 810 /* lui */
 811 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((new_target_address >> 16) & 0xffff);
 812 /* ori */
 813 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (new_target_address & 0xffff);
 814 /* jr */
 815 *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
 816 }
 817 } else if ((*insn & 0xffe00000) == 0x3c000000) { // lui
 818 int high = (*insn & 0xffff) << 16;
 819 int low = *(insn + 1) & 0xffff;
 820 int old_target_address = high | low;
 821 int new_target_address = old_target_address - (int)old_base + (int)new_base;
 822 /* lui */
 823 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((new_target_address >> 16) & 0xffff);
 824 /* ori */
 825 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (new_target_address & 0xffff);
 826 }
 827 }
 828 }
 829
 830 static int linkWithOffset(MIPSWord* insn, void* to)
 831 {
 832 ASSERT((*insn & 0xfc000000) == 0x10000000 // beq
 833 || (*insn & 0xfc000000) == 0x14000000 // bne
 834 || (*insn & 0xffff0000) == 0x45010000 // bc1t
 835 || (*insn & 0xffff0000) == 0x45000000); // bc1f
 836 intptr_t diff = (reinterpret_cast<intptr_t>(to)
 837 - reinterpret_cast<intptr_t>(insn) - 4) >> 2;
 838
 839 if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) {
 840 /*
 841 Convert the sequence:
 842 beq $2, $3, target
 843 nop
 844 b 1f
 845 nop
 846 nop
 847 nop
 848 1:
 849
 850 to the new sequence if possible:
 851 bne $2, $3, 1f
 852 nop
 853 j target
 854 nop
 855 nop
 856 nop
 857 1:
 858
 859 OR to the new sequence:
 860 bne $2, $3, 1f
 861 nop
 862 lui $25, target >> 16
 863 ori $25, $25, target & 0xffff
 864 jr $25
 865 nop
 866 1:
 867
 868 Note: beq/bne/bc1t are converted to bne/beq/bc1f.
 869 */
 870
 871 if (*(insn + 2) == 0x10000003) {
 872 if ((*insn & 0xfc000000) == 0x10000000) // beq
 873 *insn = (*insn & 0x03ff0000) | 0x14000005; // bne
 874 else if ((*insn & 0xfc000000) == 0x14000000) // bne
 875 *insn = (*insn & 0x03ff0000) | 0x10000005; // beq
 876 else if ((*insn & 0xffff0000) == 0x45010000) // bc1t
 877 *insn = 0x45000005; // bc1f
 878 else
 879 ASSERT(0);
 880 }
 881
 882 insn = insn + 2;
 883 if ((reinterpret_cast<intptr_t>(insn) + 4) >> 28
 884 == reinterpret_cast<intptr_t>(to) >> 28) {
 885 *insn = 0x08000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
 886 *(insn + 1) = 0;
 887 return 4 * sizeof(MIPSWord);
 888 }
 889
 890 intptr_t new_target_address = reinterpret_cast<intptr_t>(to);
 891 /* lui */
 892 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((new_target_address >> 16) & 0xffff);
 893 /* ori */
 894 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (new_target_address & 0xffff);
 895 /* jr */
 896 *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
 897 return 5 * sizeof(MIPSWord);
 898 }
 899
 900 *insn = (*insn & 0xffff0000) | (diff & 0xffff);
 901 return sizeof(MIPSWord);
 902 }
 903
 904 static int linkCallInternal(void* from, void* to)
 905 {
 906 MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
 907 insn = insn - 4;
 908
 909 if ((*(insn + 2) & 0xfc000000) == 0x0c000000) { // jal
 910 if ((reinterpret_cast<intptr_t>(from) - 4) >> 28
 911 == reinterpret_cast<intptr_t>(to) >> 28) {
 912 *(insn + 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
 913 return sizeof(MIPSWord);
 914 }
 915
 916 /* lui $25, (to >> 16) & 0xffff */
 917 *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 918 /* ori $25, $25, to & 0xffff */
 919 *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 920 /* jalr $25 */
 921 *(insn + 2) = 0x0000f809 | (MIPSRegisters::t9 << OP_SH_RS);
 922 return 3 * sizeof(MIPSWord);
 923 }
 924
 925 ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
 926 ASSERT((*(insn + 1) & 0xfc000000) == 0x34000000); // ori
 927
 928 /* lui */
 929 *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
 930 /* ori */
 931 *(insn + 1) = (*(insn + 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
 932 return 2 * sizeof(MIPSWord);
 933 }
 934
 935 AssemblerBuffer m_buffer;
 936 Jumps m_jumps;
 937};
 938
 939} // namespace JSC
 940
 941#endif // ENABLE(ASSEMBLER) && PLATFORM(MIPS)
 942
 943#endif // MIPSAssembler_h
0

assembler/AbstractMacroAssembler.h

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

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

190190#endif
191191
192192 int32_t m_value;
193 #if PLATFORM(ARM)
 193#if PLATFORM(ARM) || PLATFORM(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 };
51552

assembler/MacroAssemblerMIPS.h

 1/*
 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
 3 * Copyright (C) 2009 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) && PLATFORM(MIPS)
 33
 34#include "MIPSAssembler.h"
 35#include "AbstractMacroAssembler.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.and_insn(dest, dest, src);
 235 }
 236
 237 void and32(Imm32 imm, RegisterID dest)
 238 {
 239 if (!imm.m_isPointer && imm.m_value == 0 && !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.and_insn(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 shift_amount, RegisterID dest)
 260 {
 261 m_assembler.sllv(dest, dest, shift_amount);
 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 == 0 && !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.or_insn(dest, dest, src);
 293 }
 294
 295 void or32(Imm32 imm, RegisterID dest)
 296 {
 297 if (!imm.m_isPointer && imm.m_value == 0 && !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.or_insn(dest, dest, dataTempRegister);
 312 }
 313
 314 void rshift32(RegisterID shift_amount, RegisterID dest)
 315 {
 316 m_assembler.srav(dest, dest, shift_amount);
 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.xor_insn(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.xor_insn(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 defined(__MIPSEB__)
 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 defined(__MIPSEB__)
 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 == 0)
 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 == 0 && !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 == 0 && !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 defined(__mips_hard_float) && !defined(__mips_single_float)
 751 return true;
 752#else
 753 return false;
 754#endif
 755 }
 756
 757 bool supportsFloatingPointTruncate() const
 758 {
 759#if defined(__mips_hard_float) && !defined(__mips_single_float) && (__mips > 1)
 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 == 0 && !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.xor_insn(cmpTempRegister, left, right);
 917 m_assembler.bgez(cmpTempRegister, 11);
 918 m_assembler.nop();
 919 m_assembler.subu(cmpTempRegister, left, right);
 920 m_assembler.xor_insn(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.and_insn(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.xor_insn(cmpTempRegister, dataTempRegister, src);
 1095 m_assembler.bltz(cmpTempRegister, 10);
 1096 m_assembler.addu(dest, dataTempRegister, src);
 1097 m_assembler.xor_insn(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.xor_insn(cmpTempRegister, dataTempRegister, src);
 1200 m_assembler.bgez(cmpTempRegister, 10);
 1201 m_assembler.subu(dest, dataTempRegister, src);
 1202 m_assembler.xor_insn(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.xor_insn(dest, left, right);
 1284 m_assembler.sltiu(dest, dest, 1);
 1285 } else if (cond == NotEqual || cond == NonZero) {
 1286 m_assembler.xor_insn(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.xor_insn(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.xor_insn(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.and_insn(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 __mips == 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 __mips == 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.add_d(dest, dest, src);
 1488 }
 1489
 1490 void addDouble(Address src, FPRegisterID dest)
 1491 {
 1492 loadDouble(src, fpTempRegister);
 1493 m_assembler.add_d(dest, dest, fpTempRegister);
 1494 }
 1495
 1496 void subDouble(FPRegisterID src, FPRegisterID dest)
 1497 {
 1498 m_assembler.sub_d(dest, dest, src);
 1499 }
 1500
 1501 void subDouble(Address src, FPRegisterID dest)
 1502 {
 1503 loadDouble(src, fpTempRegister);
 1504 m_assembler.sub_d(dest, dest, fpTempRegister);
 1505 }
 1506
 1507 void mulDouble(FPRegisterID src, FPRegisterID dest)
 1508 {
 1509 m_assembler.mul_d(dest, dest, src);
 1510 }
 1511
 1512 void mulDouble(Address src, FPRegisterID dest)
 1513 {
 1514 loadDouble(src, fpTempRegister);
 1515 m_assembler.mul_d(dest, dest, fpTempRegister);
 1516 }
 1517
 1518 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
 1519 {
 1520 m_assembler.mtc1(src, fpTempRegister);
 1521 m_assembler.cvt_d_w(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.c_eq_d(left, right);
 1573 return branchTrue();
 1574 }
 1575 if (cond == DoubleNotEqual) {
 1576 m_assembler.c_eq_d(left, right);
 1577 return branchFalse(); // false
 1578 }
 1579 if (cond == DoubleGreaterThan) {
 1580 m_assembler.c_ngt_d(left, right);
 1581 return branchFalse(); // false
 1582 }
 1583 if (cond == DoubleGreaterThanOrEqual) {
 1584 m_assembler.c_nge_d(right, left);
 1585 return branchFalse(); // false
 1586 }
 1587 if (cond == DoubleLessThan) {
 1588 m_assembler.c_lt_d(left, right);
 1589 return branchTrue();
 1590 }
 1591 if (cond == DoubleLessThanOrEqual) {
 1592 m_assembler.c_le_d(left, right);
 1593 return branchTrue();
 1594 }
 1595 if (cond == DoubleEqualOrUnordered) {
 1596 m_assembler.c_ueq_d(left, right);
 1597 return branchTrue();
 1598 }
 1599 if (cond == DoubleGreaterThanOrUnordered) {
 1600 m_assembler.c_ole_d(left, right);
 1601 return branchFalse(); // false
 1602 }
 1603 if (cond == DoubleGreaterThanOrEqualOrUnordered) {
 1604 m_assembler.c_olt_d(left, right);
 1605 return branchFalse(); // false
 1606 }
 1607 if (cond == DoubleLessThanOrUnordered) {
 1608 m_assembler.c_ult_d(left, right);
 1609 return branchTrue();
 1610 }
 1611 if (cond == DoubleLessThanOrEqualOrUnordered) {
 1612 m_assembler.c_ule_d(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.trunc_w_d(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
 1659
 1660#endif // MacroAssemblerMIPS_h
0

jit/ExecutableAllocator.h

4242#include <e32std.h>
4343#endif
4444
 45#if PLATFORM(MIPS) && PLATFORM(LINUX)
 46#include <sys/cachectl.h>
 47#endif
 48
4549#define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
4650#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
4751

183187 static void cacheFlush(void*, size_t)
184188 {
185189 }
 190#elif PLATFORM(MIPS)
 191 static void cacheFlush(void* code, size_t size)
 192 {
 193#if COMPILER(GCC) && (GCC_VERSION >= 40300)
 194#if __mips_isa_rev == 2 && (GCC_VERSION < 40403)
 195 int line_size;
 196 asm ("rdhwr %0, $1" : "=r" (line_size));
 197 //
 198 // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in
 199 // mips_expand_synci_loop that may execute synci one more time.
 200 // "start" points to the fisrt byte of the cache line.
 201 // "end" points to the last byte of the line before the last cache line.
 202 // Because size is always a multiple of 4, this is safe to set
 203 // "end" to the last byte.
 204 //
 205 intptr_t start = reinterpret_cast<intptr_t>(code) & (-line_size);
 206 intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-line_size)) - 1;
 207 __clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end));
 208#else
 209 intptr_t end = reinterpret_cast<intptr_t>(code) + size;
 210 __clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
 211#endif
 212#else
 213 _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
 214#endif
 215 }
186216#elif PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE)
187217 static void cacheFlush(void* code, size_t size)
188218 {
51552