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