1 /* 2 * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. 3 * Copyright (C) 2008 Apple 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 APPLE 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 APPLE 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 SH4Assembler_h 28 #define SH4Assembler_h 29 30 #if ENABLE(ASSEMBLER) && CPU(SH4) 31 32 #include "AssemblerBuffer.h" 33 #include "AssemblerBufferWithConstantPool.h" 34 #include <stdarg.h> 35 #include <stdint.h> 36 #include <wtf/Assertions.h> 37 #include <wtf/Vector.h> 38 39 #ifndef NDEBUG 40 #define SH4_ASSEMBLER_TRACING 41 #endif 42 43 namespace JSC { 44 typedef uint16_t SH4Word; 45 46 enum { 47 INVALID_OPCODE = 0xffff, 48 ADD_OPCODE = 0x300c, 49 ADDIMM_OPCODE = 0x7000, 50 ADDC_OPCODE = 0x300e, 51 ADDV_OPCODE = 0x300f, 52 AND_OPCODE = 0x2009, 53 ANDIMM_OPCODE = 0xc900, 54 DIV0_OPCODE = 0x2007, 55 DIV1_OPCODE = 0x3004, 56 BF_OPCODE = 0x8b00, 57 BFS_OPCODE = 0x8f00, 58 BRA_OPCODE = 0xa000, 59 BRAF_OPCODE = 0x0023, 60 NOP_OPCODE = 0x0009, 61 BSR_OPCODE = 0xb000, 62 RTS_OPCODE = 0x000b, 63 BT_OPCODE = 0x8900, 64 BTS_OPCODE = 0x8d00, 65 BSRF_OPCODE = 0x0003, 66 BRK_OPCODE = 0x003b, 67 FTRC_OPCODE = 0xf03d, 68 CMPEQ_OPCODE = 0x3000, 69 CMPEQIMM_OPCODE = 0x8800, 70 CMPGE_OPCODE = 0x3003, 71 CMPGT_OPCODE = 0x3007, 72 CMPHI_OPCODE = 0x3006, 73 CMPHS_OPCODE = 0x3002, 74 CMPPL_OPCODE = 0x4015, 75 CMPPZ_OPCODE = 0x4011, 76 CMPSTR_OPCODE = 0x200c, 77 DT_OPCODE = 0x4010, 78 FCMPEQ_OPCODE = 0xf004, 79 FCMPGT_OPCODE = 0xf005, 80 FMOV_OPCODE = 0xf00c, 81 FADD_OPCODE = 0xf000, 82 FMUL_OPCODE = 0xf002, 83 FSUB_OPCODE = 0xf001, 84 FDIV_OPCODE = 0xf003, 85 FNEG_OPCODE = 0xf04d, 86 JMP_OPCODE = 0x402b, 87 JSR_OPCODE = 0x400b, 88 LDSPR_OPCODE = 0x402a, 89 LDSLPR_OPCODE = 0x4026, 90 MOV_OPCODE = 0x6003, 91 MOVIMM_OPCODE = 0xe000, 92 MOVB_WRITE_RN_OPCODE = 0x2000, 93 MOVB_WRITE_RNDEC_OPCODE = 0x2004, 94 MOVB_WRITE_R0RN_OPCODE = 0x0004, 95 MOVB_WRITE_OFFGBR_OPCODE = 0xc000, 96 MOVB_WRITE_OFFRN_OPCODE = 0x8000, 97 MOVB_READ_RM_OPCODE = 0x6000, 98 MOVB_READ_RMINC_OPCODE = 0x6004, 99 MOVB_READ_R0RM_OPCODE = 0x000c, 100 MOVB_READ_OFFGBR_OPCODE = 0xc400, 101 MOVB_READ_OFFRM_OPCODE = 0x8400, 102 MOVL_WRITE_RN_OPCODE = 0x2002, 103 MOVL_WRITE_RNDEC_OPCODE = 0x2006, 104 MOVL_WRITE_R0RN_OPCODE = 0x0006, 105 MOVL_WRITE_OFFGBR_OPCODE = 0xc200, 106 MOVL_WRITE_OFFRN_OPCODE = 0x1000, 107 MOVL_READ_RM_OPCODE = 0x6002, 108 MOVL_READ_RMINC_OPCODE = 0x6006, 109 MOVL_READ_R0RM_OPCODE = 0x000e, 110 MOVL_READ_OFFGBR_OPCODE = 0xc600, 111 MOVL_READ_OFFPC_OPCODE = 0xd000, 112 MOVL_READ_OFFRM_OPCODE = 0x5000, 113 MOVW_WRITE_RN_OPCODE = 0x2001, 114 MOVW_READ_RM_OPCODE = 0x6001, 115 MOVW_READ_R0RM_OPCODE = 0x000d, 116 MOVW_READ_OFFRM_OPCODE = 0x8500, 117 MOVW_READ_OFFPC_OPCODE = 0x9000, 118 MOVA_READ_OFFPC_OPCODE = 0xc700, 119 MOVT_OPCODE = 0x0029, 120 MULL_OPCODE = 0x0007, 121 DMULL_L_OPCODE = 0x3005, 122 STSMACL_OPCODE = 0x001a, 123 STSMACH_OPCODE = 0x000a, 124 DMULSL_OPCODE = 0x300d, 125 NEG_OPCODE = 0x600b, 126 NEGC_OPCODE = 0x600a, 127 NOT_OPCODE = 0x6007, 128 OR_OPCODE = 0x200b, 129 ORIMM_OPCODE = 0xcb00, 130 ORBIMM_OPCODE = 0xcf00, 131 SETS_OPCODE = 0x0058, 132 SETT_OPCODE = 0x0018, 133 SHAD_OPCODE = 0x400c, 134 SHAL_OPCODE = 0x4020, 135 SHAR_OPCODE = 0x4021, 136 SHLD_OPCODE = 0x400d, 137 SHLL_OPCODE = 0x4000, 138 SHLL2_OPCODE = 0x4008, 139 SHLL8_OPCODE = 0x4018, 140 SHLL16_OPCODE = 0x4028, 141 SHLR_OPCODE = 0x4001, 142 SHLR2_OPCODE = 0x4009, 143 SHLR8_OPCODE = 0x4019, 144 SHLR16_OPCODE = 0x4029, 145 STSPR_OPCODE = 0x002a, 146 STSLPR_OPCODE = 0x4022, 147 FLOAT_OPCODE = 0xf02d, 148 SUB_OPCODE = 0x3008, 149 SUBC_OPCODE = 0x300a, 150 SUBV_OPCODE = 0x300b, 151 TST_OPCODE = 0x2008, 152 TSTIMM_OPCODE = 0xc800, 153 TSTB_OPCODE = 0xcc00, 154 EXTUW_OPCODE = 0x600d, 155 XOR_OPCODE = 0x200a, 156 XORIMM_OPCODE = 0xca00, 157 XORB_OPCODE = 0xce00, 158 FMOVS_READ_RM_INC_OPCODE = 0xf009, 159 FMOVS_READ_RM_OPCODE = 0xf008, 160 FMOVS_READ_R0RM_OPCODE = 0xf006, 161 FMOVS_WRITE_RN_OPCODE = 0xf00a, 162 FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b, 163 FMOVS_WRITE_R0RN_OPCODE = 0xf007, 164 FCNVDS_DRM_FPUL_OPCODE = 0xf0bd, 165 LDS_RM_FPUL_OPCODE = 0x405a, 166 FLDS_FRM_FPUL_OPCODE = 0xf01d, 167 STS_FPUL_RN_OPCODE = 0x005a, 168 FSTS_FPUL_FRN_OPCODE = 0xF00d, 169 LDSFPSCR_OPCODE = 0x406a, 170 STSFPSCR_OPCODE = 0x006a, 171 LDSRMFPUL_OPCODE = 0x405a, 172 FSTSFPULFRN_OPCODE = 0xf00d, 173 FSQRT_OPCODE = 0xf06d, 174 FSCHG_OPCODE = 0xf3fd, 175 CLRT_OPCODE = 8, 176 }; 177 178 namespace SH4Registers { 179 typedef enum { 180 r0, 181 r1, 182 r2, 183 r3, 184 r4, 185 r5, 186 r6, 187 r7, 188 r8, 189 r9, 190 r10, 191 r11, 192 r12, 193 r13, 194 r14, fp = r14, 195 r15, sp = r15, 196 pc, 197 pr, 198 } RegisterID; 199 200 typedef enum { 201 fr0, dr0 = fr0, 202 fr1, 203 fr2, dr2 = fr2, 204 fr3, 205 fr4, dr4 = fr4, 206 fr5, 207 fr6, dr6 = fr6, 208 fr7, 209 fr8, dr8 = fr8, 210 fr9, 211 fr10, dr10 = fr10, 212 fr11, 213 fr12, dr12 = fr12, 214 fr13, 215 fr14, dr14 = fr14, 216 fr15, 217 } FPRegisterID; 218 } 219 220 inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn) 221 { 222 return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4)); 223 } 224 225 inline uint16_t getOpcodeGroup2(uint16_t opc, int rm) 226 { 227 return (opc | ((rm & 0xf) << 8)); 228 } 229 230 inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn) 231 { 232 return (opc | ((rm & 0xf) << 8) | (rn & 0xff)); 233 } 234 235 inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset) 236 { 237 return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf)); 238 } 239 240 inline uint16_t getOpcodeGroup5(uint16_t opc, int rm) 241 { 242 return (opc | (rm & 0xff)); 243 } 244 245 inline uint16_t getOpcodeGroup6(uint16_t opc, int rm) 246 { 247 return (opc | (rm & 0xfff)); 248 } 249 250 inline uint16_t getOpcodeGroup7(uint16_t opc, int rm) 251 { 252 return (opc | ((rm & 0x7) << 9)); 253 } 254 255 inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn) 256 { 257 return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5)); 258 } 259 260 inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn) 261 { 262 return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5)); 263 } 264 265 inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn) 266 { 267 return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4)); 268 } 269 270 inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn) 271 { 272 return (opc | ((rm & 0xf) << 4) | (rn & 0xf)); 273 } 274 275 inline uint16_t getRn(uint16_t x) 276 { 277 return ((x & 0xf00) >> 8); 278 } 279 280 inline uint16_t getRm(uint16_t x) 281 { 282 return ((x & 0xf0) >> 4); 283 } 284 285 inline uint16_t getDisp(uint16_t x) 286 { 287 return (x & 0xf); 288 } 289 290 inline uint16_t getImm8(uint16_t x) 291 { 292 return (x & 0xff); 293 } 294 295 inline uint16_t getImm12(uint16_t x) 296 { 297 return (x & 0xfff); 298 } 299 300 inline uint16_t getDRn(uint16_t x) 301 { 302 return ((x & 0xe00) >> 9); 303 } 304 305 inline uint16_t getDRm(uint16_t x) 306 { 307 return ((x & 0xe0) >> 5); 308 } 309 310 class SH4Assembler { 311 public: 312 typedef SH4Registers::RegisterID RegisterID; 313 typedef SH4Registers::FPRegisterID FPRegisterID; 314 typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer; 315 static const RegisterID scratchReg1 = SH4Registers::r3; 316 static const RegisterID scratchReg2 = SH4Registers::r11; 317 static const uint32_t maxInstructionSize = 16; 318 319 enum { 320 padForAlign8 = 0x00, 321 padForAlign16 = 0x0009, 322 padForAlign32 = 0x00090009, 323 }; 324 325 SH4Assembler() 326 { 327 m_claimscratchReg = 0x0; 328 } 329 330 // SH4 condition codes 331 typedef enum { 332 EQ = 0x0, // Equal 333 NE = 0x1, // Not Equal 334 HS = 0x2, // Unsigend Greater Than equal 335 HI = 0x3, // Unsigend Greater Than 336 LS = 0x4, // Unsigend Lower or Same 337 LI = 0x5, // Unsigend Lower 338 GE = 0x6, // Greater or Equal 339 LT = 0x7, // Less Than 340 GT = 0x8, // Greater Than 341 LE = 0x9, // Less or Equal 342 OF = 0xa, // OverFlow 343 SI = 0xb, // Signed 344 EQU= 0xc, // Equal or unordered(NaN) 345 NEU= 0xd, 346 GTU= 0xe, 347 GEU= 0xf, 348 LTU= 0x10, 349 LEU= 0x11, 350 } Condition; 351 352 // Opaque label types 353 public: 354 class JmpSrc { 355 friend class SH4Assembler; 356 public: 357 JmpSrc() 358 : m_offset(-1) 359 { 360 } 361 362 private: 363 JmpSrc(int offset) 364 : m_offset(offset) 365 { 366 } 367 368 int m_offset; 369 }; 370 371 class JmpDst { 372 friend class SH4Assembler; 373 public: 374 JmpDst() 375 : m_offset(-1) 376 , m_used(false) 377 { 378 } 379 380 bool isUsed() const { return m_used; } 381 bool isSet() const { return (m_offset != -1); } 382 void used() { m_used = true; } 383 384 private: 385 JmpDst(int offset) 386 : m_offset(offset) 387 , m_used(false) 388 { 389 ASSERT(m_offset == offset); 390 } 391 392 int m_offset : 31; 393 int m_used : 1; 394 }; 395 396 bool isImmediate(int constant) 397 { 398 return ((constant <= 127) && (constant >= -128)); 399 } 400 401 RegisterID claimScratch() 402 { 403 ASSERT((m_claimscratchReg != 0x3)); 404 405 if (!(m_claimscratchReg & 0x1)) { 406 m_claimscratchReg = (m_claimscratchReg | 0x1); 407 return scratchReg1; 408 } 409 410 m_claimscratchReg = (m_claimscratchReg | 0x2); 411 return scratchReg2; 412 } 413 414 void releaseScratch(RegisterID scratchR) 415 { 416 if (scratchR == scratchReg1) 417 m_claimscratchReg = (m_claimscratchReg & 0x2); 418 else 419 m_claimscratchReg = (m_claimscratchReg & 0x1); 420 } 421 422 // Stack operations 423 424 void pushReg(RegisterID reg) 425 { 426 if (reg == SH4Registers::pr) { 427 oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp)); 428 return; 429 } 430 431 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg)); 432 } 433 434 void popReg(RegisterID reg) 435 { 436 if (reg == SH4Registers::pr) { 437 oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp)); 438 return; 439 } 440 441 oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp)); 442 } 443 444 void movt(RegisterID dst) 445 { 446 uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst); 447 oneShortOp(opc); 448 } 449 450 // Arithmetic operations 451 452 void addlRegReg(RegisterID src, RegisterID dst) 453 { 454 uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src); 455 oneShortOp(opc); 456 } 457 458 void addclRegReg(RegisterID src, RegisterID dst) 459 { 460 uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src); 461 oneShortOp(opc); 462 } 463 464 void addvlRegReg(RegisterID src, RegisterID dst) 465 { 466 uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src); 467 oneShortOp(opc); 468 } 469 470 void addlImm8r(int imm8, RegisterID dst) 471 { 472 ASSERT((imm8 <= 127) && (imm8 >= -128)); 473 474 uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8); 475 oneShortOp(opc); 476 } 477 478 void andlRegReg(RegisterID src, RegisterID dst) 479 { 480 uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src); 481 oneShortOp(opc); 482 } 483 484 void andlImm8r(int imm8, RegisterID dst) 485 { 486 ASSERT((imm8 <= 255) && (imm8 >= 0)); 487 ASSERT(dst == SH4Registers::r0); 488 489 uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8); 490 oneShortOp(opc); 491 } 492 493 void div1lRegReg(RegisterID src, RegisterID dst) 494 { 495 uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src); 496 oneShortOp(opc); 497 } 498 499 void div0lRegReg(RegisterID src, RegisterID dst) 500 { 501 uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src); 502 oneShortOp(opc); 503 } 504 505 void notlReg(RegisterID src, RegisterID dst) 506 { 507 uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src); 508 oneShortOp(opc); 509 } 510 511 void orlRegReg(RegisterID src, RegisterID dst) 512 { 513 uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src); 514 oneShortOp(opc); 515 } 516 517 void orlImm8r(int imm8, RegisterID dst) 518 { 519 ASSERT((imm8 <= 255) && (imm8 >= 0)); 520 ASSERT(dst == SH4Registers::r0); 521 522 uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8); 523 oneShortOp(opc); 524 } 525 526 void sublRegReg(RegisterID src, RegisterID dst) 527 { 528 uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src); 529 oneShortOp(opc); 530 } 531 532 void subvlRegReg(RegisterID src, RegisterID dst) 533 { 534 uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src); 535 oneShortOp(opc); 536 } 537 538 void xorlRegReg(RegisterID src, RegisterID dst) 539 { 540 uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src); 541 oneShortOp(opc); 542 } 543 544 void xorlImm8r(int imm8, RegisterID dst) 545 { 546 ASSERT((imm8 <= 255) && (imm8 >= 0)); 547 ASSERT(dst == SH4Registers::r0); 548 549 uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8); 550 oneShortOp(opc); 551 } 552 553 void shllImm8r(int imm, RegisterID dst) 554 { 555 switch (imm) { 556 case 1: 557 oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst)); 558 break; 559 case 2: 560 oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst)); 561 break; 562 case 8: 563 oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst)); 564 break; 565 case 16: 566 oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst)); 567 break; 568 default: 569 ASSERT_NOT_REACHED(); 570 } 571 } 572 573 void neg(RegisterID dst, RegisterID src) 574 { 575 uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src); 576 oneShortOp(opc); 577 } 578 579 void shllRegReg(RegisterID dst, RegisterID rShift) 580 { 581 uint16_t opc = getOpcodeGroup1(SHLD_OPCODE, dst, rShift); 582 oneShortOp(opc); 583 } 584 585 void shlrRegReg(RegisterID dst, RegisterID rShift) 586 { 587 neg(rShift, rShift); 588 shllRegReg(dst, rShift); 589 } 590 591 void sharRegReg(RegisterID dst, RegisterID rShift) 592 { 593 neg(rShift, rShift); 594 shaRegReg(dst, rShift); 595 } 596 597 void shaRegReg(RegisterID dst, RegisterID rShift) 598 { 599 uint16_t opc = getOpcodeGroup1(SHAD_OPCODE, dst, rShift); 600 oneShortOp(opc); 601 } 602 603 void shlrImm8r(int imm, RegisterID dst) 604 { 605 switch (imm) { 606 case 1: 607 oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst)); 608 break; 609 case 2: 610 oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst)); 611 break; 612 case 8: 613 oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst)); 614 break; 615 case 16: 616 oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst)); 617 break; 618 default: 619 ASSERT_NOT_REACHED(); 620 } 621 } 622 623 void imullRegReg(RegisterID src, RegisterID dst) 624 { 625 uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src); 626 oneShortOp(opc); 627 } 628 629 void dmullRegReg(RegisterID src, RegisterID dst) 630 { 631 uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src); 632 oneShortOp(opc); 633 } 634 635 void dmulslRegReg(RegisterID src, RegisterID dst) 636 { 637 uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src); 638 oneShortOp(opc); 639 } 640 641 void stsmacl(RegisterID reg) 642 { 643 uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg); 644 oneShortOp(opc); 645 } 646 647 void stsmach(RegisterID reg) 648 { 649 uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg); 650 oneShortOp(opc); 651 } 652 653 // Comparisons 654 655 void cmplRegReg(RegisterID left, RegisterID right, Condition cond) 656 { 657 switch (cond) { 658 case NE: 659 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left)); 660 break; 661 case GT: 662 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left)); 663 break; 664 case EQ: 665 oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left)); 666 break; 667 case GE: 668 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left)); 669 break; 670 case HS: 671 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left)); 672 break; 673 case HI: 674 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left)); 675 break; 676 case LI: 677 oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right)); 678 break; 679 case LS: 680 oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right)); 681 break; 682 case LE: 683 oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right)); 684 break; 685 case LT: 686 oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right)); 687 break; 688 default: 689 ASSERT_NOT_REACHED(); 690 } 691 } 692 693 void cmppl(RegisterID reg) 694 { 695 uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg); 696 oneShortOp(opc); 697 } 698 699 void cmppz(RegisterID reg) 700 { 701 uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg); 702 oneShortOp(opc); 703 } 704 705 void cmpEqImmR0(int imm, RegisterID dst, Condition cond) 706 { 707 uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm); 708 oneShortOp(opc); 709 } 710 711 void testlRegReg(RegisterID src, RegisterID dst) 712 { 713 uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src); 714 oneShortOp(opc); 715 } 716 717 void testlImm8r(int imm, RegisterID dst) 718 { 719 ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)); 720 721 uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm); 722 oneShortOp(opc); 723 } 724 725 void nop() 726 { 727 oneShortOp(NOP_OPCODE, false); 728 } 729 730 void sett() 731 { 732 oneShortOp(SETT_OPCODE); 733 } 734 735 void clrt() 736 { 737 oneShortOp(CLRT_OPCODE); 738 } 739 740 void fschg() 741 { 742 oneShortOp(FSCHG_OPCODE); 743 } 744 745 void bkpt() 746 { 747 oneShortOp(BRK_OPCODE, false); 748 } 749 750 void branch(uint16_t opc, int label) 751 { 752 switch (opc) { 753 case BT_OPCODE: 754 ASSERT((label <= 127) && (label >= -128)); 755 oneShortOp(getOpcodeGroup5(BT_OPCODE, label)); 756 break; 757 case BRA_OPCODE: 758 ASSERT((label <= 2047) && (label >= -2048)); 759 oneShortOp(getOpcodeGroup6(BRA_OPCODE, label)); 760 break; 761 case BF_OPCODE: 762 ASSERT((label <= 127) && (label >= -128)); 763 oneShortOp(getOpcodeGroup5(BF_OPCODE, label)); 764 break; 765 default: 766 ASSERT_NOT_REACHED(); 767 } 768 } 769 770 void branch(uint16_t opc, RegisterID reg) 771 { 772 switch (opc) { 773 case BRAF_OPCODE: 774 oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg)); 775 break; 776 case JMP_OPCODE: 777 oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg)); 778 break; 779 case JSR_OPCODE: 780 oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg)); 781 break; 782 case BSRF_OPCODE: 783 oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg)); 784 break; 785 default: 786 ASSERT_NOT_REACHED(); 787 } 788 } 789 790 void ldspr(RegisterID reg) 791 { 792 uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg); 793 oneShortOp(opc); 794 } 795 796 void stspr(RegisterID reg) 797 { 798 uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg); 799 oneShortOp(opc); 800 } 801 802 void extuw(RegisterID src, RegisterID dst) 803 { 804 uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src); 805 oneShortOp(opc); 806 } 807 808 // float operations 809 810 void ldsrmfpul(RegisterID src) 811 { 812 uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src); 813 oneShortOp(opc); 814 } 815 816 void fneg(FPRegisterID dst) 817 { 818 uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst); 819 oneShortOp(opc, true, false); 820 } 821 822 void fsqrt(FPRegisterID dst) 823 { 824 uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst); 825 oneShortOp(opc, true, false); 826 } 827 828 void stsfpulReg(RegisterID src) 829 { 830 uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src); 831 oneShortOp(opc); 832 } 833 834 void floatfpulfrn(RegisterID src) 835 { 836 uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src); 837 oneShortOp(opc, true, false); 838 } 839 840 void fmull(FPRegisterID src, FPRegisterID dst) 841 { 842 uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src); 843 oneShortOp(opc, true, false); 844 } 845 846 void fmovsReadrm(RegisterID src, FPRegisterID dst) 847 { 848 uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src); 849 oneShortOp(opc, true, false); 850 } 851 852 void fmovsWriterm(FPRegisterID src, RegisterID dst) 853 { 854 uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src); 855 oneShortOp(opc, true, false); 856 } 857 858 void fmovsWriter0r(FPRegisterID src, RegisterID dst) 859 { 860 uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src); 861 oneShortOp(opc, true, false); 862 } 863 864 void fmovsReadr0r(RegisterID src, FPRegisterID dst) 865 { 866 uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src); 867 oneShortOp(opc, true, false); 868 } 869 870 void fmovsReadrminc(RegisterID src, FPRegisterID dst) 871 { 872 uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src); 873 oneShortOp(opc, true, false); 874 } 875 876 void fmovsWriterndec(FPRegisterID src, RegisterID dst) 877 { 878 uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src); 879 oneShortOp(opc, true, false); 880 } 881 882 void ftrcRegfpul(FPRegisterID src) 883 { 884 uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src); 885 oneShortOp(opc, true, false); 886 } 887 888 void fldsfpul(RegisterID src) 889 { 890 uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src); 891 oneShortOp(opc); 892 } 893 894 void fstsfpul(RegisterID src) 895 { 896 uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src); 897 oneShortOp(opc); 898 } 899 900 void ldsfpscr(RegisterID reg) 901 { 902 uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg); 903 oneShortOp(opc); 904 } 905 906 void stsfpscr(RegisterID reg) 907 { 908 uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg); 909 oneShortOp(opc); 910 } 911 912 // double operations 913 914 void dcnvds(FPRegisterID src) 915 { 916 uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1); 917 oneShortOp(opc); 918 } 919 920 void dcmppeq(FPRegisterID src, FPRegisterID dst) 921 { 922 uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1); 923 oneShortOp(opc); 924 } 925 926 void dcmppgt(FPRegisterID src, FPRegisterID dst) 927 { 928 uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1); 929 oneShortOp(opc); 930 } 931 932 void dmulRegReg(FPRegisterID src, FPRegisterID dst) 933 { 934 uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1); 935 oneShortOp(opc); 936 } 937 938 void dsubRegReg(FPRegisterID src, FPRegisterID dst) 939 { 940 uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1); 941 oneShortOp(opc); 942 } 943 944 void daddRegReg(FPRegisterID src, FPRegisterID dst) 945 { 946 uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1); 947 oneShortOp(opc); 948 } 949 950 void dmovRegReg(FPRegisterID src, FPRegisterID dst) 951 { 952 uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1); 953 oneShortOp(opc); 954 } 955 956 void ddivRegReg(FPRegisterID src, FPRegisterID dst) 957 { 958 uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1); 959 oneShortOp(opc); 960 } 961 962 void dsqrt(FPRegisterID dst) 963 { 964 uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1); 965 oneShortOp(opc); 966 } 967 968 void dneg(FPRegisterID dst) 969 { 970 uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1); 971 oneShortOp(opc); 972 } 973 974 void fmovReadrm(RegisterID src, FPRegisterID dst) 975 { 976 uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src); 977 oneShortOp(opc); 978 } 979 980 void fmovWriterm(FPRegisterID src, RegisterID dst) 981 { 982 uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1); 983 oneShortOp(opc); 984 } 985 986 void fmovWriter0r(FPRegisterID src, RegisterID dst) 987 { 988 uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1); 989 oneShortOp(opc); 990 } 991 992 void fmovReadr0r(RegisterID src, FPRegisterID dst) 993 { 994 uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src); 995 oneShortOp(opc); 996 } 997 998 void fmovReadrminc(RegisterID src, FPRegisterID dst) 999 { 1000 uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src); 1001 oneShortOp(opc); 1002 } 1003 1004 void fmovWriterndec(FPRegisterID src, RegisterID dst) 1005 { 1006 uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1); 1007 oneShortOp(opc); 1008 } 1009 1010 void floatfpulDreg(FPRegisterID src) 1011 { 1012 uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1); 1013 oneShortOp(opc); 1014 } 1015 1016 void ftrcdrmfpul(FPRegisterID src) 1017 { 1018 uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1); 1019 oneShortOp(opc); 1020 } 1021 1022 // Various move ops 1023 1024 void movImm8(int imm8, RegisterID dst) 1025 { 1026 ASSERT((imm8 <= 127) && (imm8 >= -128)); 1027 1028 uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8); 1029 oneShortOp(opc); 1030 } 1031 1032 void movlRegReg(RegisterID src, RegisterID dst) 1033 { 1034 uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src); 1035 oneShortOp(opc); 1036 } 1037 1038 void movwRegMem(RegisterID src, RegisterID dst) 1039 { 1040 uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src); 1041 oneShortOp(opc); 1042 } 1043 1044 void movwMemReg(RegisterID src, RegisterID dst) 1045 { 1046 uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src); 1047 oneShortOp(opc); 1048 } 1049 1050 void movwPCReg(int offset, RegisterID base, RegisterID dst) 1051 { 1052 ASSERT(base == SH4Registers::pc); 1053 ASSERT((offset <= 255) && (offset >= 0)); 1054 1055 uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset); 1056 oneShortOp(opc); 1057 } 1058 1059 void movwMemReg(int offset, RegisterID base, RegisterID dst) 1060 { 1061 ASSERT(dst == SH4Registers::r0); 1062 1063 uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset); 1064 oneShortOp(opc); 1065 } 1066 1067 void movwR0mr(RegisterID src, RegisterID dst) 1068 { 1069 uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src); 1070 oneShortOp(opc); 1071 } 1072 1073 void movlRegMem(RegisterID src, int offset, RegisterID base) 1074 { 1075 ASSERT((offset <= 15) && (offset >= 0)); 1076 1077 if (!offset) { 1078 oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src)); 1079 return; 1080 } 1081 1082 oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset)); 1083 } 1084 1085 void movlRegMem(RegisterID src, RegisterID base) 1086 { 1087 uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src); 1088 oneShortOp(opc); 1089 } 1090 1091 void movlMemReg(int offset, RegisterID base, RegisterID dst) 1092 { 1093 if (base == SH4Registers::pc) { 1094 ASSERT((offset <= 255) && (offset >= 0)); 1095 oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset)); 1096 return; 1097 } 1098 1099 ASSERT((offset <= 15) && (offset >= 0)); 1100 if (!offset) { 1101 oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base)); 1102 return; 1103 } 1104 1105 oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset)); 1106 } 1107 1108 void movbMemReg(int offset, RegisterID base, RegisterID dst) 1109 { 1110 ASSERT(dst == SH4Registers::r0); 1111 1112 uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset); 1113 oneShortOp(opc); 1114 } 1115 1116 void movbR0mr(RegisterID src, RegisterID dst) 1117 { 1118 uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src); 1119 oneShortOp(opc); 1120 } 1121 1122 void movbMemReg(RegisterID src, RegisterID dst) 1123 { 1124 uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src); 1125 oneShortOp(opc); 1126 } 1127 1128 void movlMemReg(RegisterID base, RegisterID dst) 1129 { 1130 uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base); 1131 oneShortOp(opc); 1132 } 1133 1134 void movlMemRegIn(RegisterID base, RegisterID dst) 1135 { 1136 uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base); 1137 oneShortOp(opc); 1138 } 1139 1140 void movlR0mr(RegisterID src, RegisterID dst) 1141 { 1142 uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src); 1143 oneShortOp(opc); 1144 } 1145 1146 void movlRegMemr0(RegisterID src, RegisterID dst) 1147 { 1148 uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src); 1149 oneShortOp(opc); 1150 } 1151 1152 void movlImm8r(int imm8, RegisterID dst) 1153 { 1154 ASSERT((imm8 <= 127) && (imm8 >= -128)); 1155 1156 uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8); 1157 oneShortOp(opc); 1158 } 1159 1160 void loadConstant(uint32_t constant, RegisterID dst) 1161 { 1162 if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) { 1163 movImm8(constant, dst); 1164 return; 1165 } 1166 1167 uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0); 1168 1169 m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t)); 1170 printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.uncheckedSize()); 1171 m_buffer.putShortWithConstantInt(opc, constant, true); 1172 } 1173 1174 void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false) 1175 { 1176 uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0); 1177 1178 if (ensureSpace) 1179 m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t)); 1180 1181 printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.uncheckedSize()); 1182 m_buffer.putShortWithConstantInt(opc, constant); 1183 } 1184 1185 // Flow control 1186 1187 JmpSrc call() 1188 { 1189 RegisterID scr = claimScratch(); 1190 m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t)); 1191 loadConstantUnReusable(0x0, scr); 1192 branch(JSR_OPCODE, scr); 1193 nop(); 1194 releaseScratch(scr); 1195 return JmpSrc(m_buffer.uncheckedSize()); 1196 } 1197 1198 JmpSrc call(RegisterID dst) 1199 { 1200 m_buffer.ensureSpace(maxInstructionSize + 2); 1201 branch(JSR_OPCODE, dst); 1202 nop(); 1203 return JmpSrc(m_buffer.uncheckedSize()); 1204 } 1205 1206 JmpSrc jmp() 1207 { 1208 RegisterID scr = claimScratch(); 1209 m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t)); 1210 int m_size = m_buffer.uncheckedSize(); 1211 loadConstantUnReusable(0x0, scr); 1212 branch(BRAF_OPCODE, scr); 1213 nop(); 1214 releaseScratch(scr); 1215 return JmpSrc(m_size); 1216 } 1217 1218 JmpSrc jmp(RegisterID dst) 1219 { 1220 jmpReg(dst); 1221 return JmpSrc(m_buffer.uncheckedSize()); 1222 } 1223 1224 void jmpReg(RegisterID dst) 1225 { 1226 m_buffer.ensureSpace(maxInstructionSize + 2); 1227 branch(JMP_OPCODE, dst); 1228 nop(); 1229 } 1230 1231 JmpSrc jne() 1232 { 1233 int m_size = m_buffer.uncheckedSize(); 1234 branch(BF_OPCODE, 0); 1235 return JmpSrc(m_size); 1236 } 1237 1238 JmpSrc je() 1239 { 1240 int m_size = m_buffer.uncheckedSize(); 1241 branch(BT_OPCODE, 0); 1242 return JmpSrc(m_size); 1243 } 1244 1245 void ret() 1246 { 1247 m_buffer.ensureSpace(maxInstructionSize + 2); 1248 oneShortOp(RTS_OPCODE, false); 1249 } 1250 1251 JmpDst label() 1252 { 1253 return JmpDst(m_buffer.size()); 1254 } 1255 1256 int sizeOfConstantPool() 1257 { 1258 return m_buffer.sizeOfConstantPool(); 1259 } 1260 1261 JmpDst align(int alignment) 1262 { 1263 m_buffer.ensureSpace(maxInstructionSize + 2); 1264 while (!m_buffer.isAligned(alignment)) { 1265 nop(); 1266 m_buffer.ensureSpace(maxInstructionSize + 2); 1267 } 1268 return label(); 1269 } 1270 1271 static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress) 1272 { 1273 uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3)); 1274 *reinterpret_cast<uint32_t*>(address) = newAddress; 1275 } 1276 1277 static uint16_t* getInstructionPtr(void* code, int offset) 1278 { 1279 return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset); 1280 } 1281 1282 static void linkJump(void* code, JmpSrc from, void* to) 1283 { 1284 ASSERT(from.m_offset != -1); 1285 1286 uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset); 1287 uint16_t instruction = *instructionPtr; 1288 int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset; 1289 1290 if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) { 1291 /* BT label ==> BF 2 1292 nop LDR reg 1293 nop braf @reg 1294 nop nop 1295 */ 1296 offsetBits -= 8; 1297 instruction ^= 0x0202; 1298 *instructionPtr++ = instruction; 1299 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits); 1300 instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00)); 1301 *instructionPtr = instruction; 1302 printBlockInstr(instructionPtr - 2, from.m_offset, 3); 1303 return; 1304 } 1305 1306 /* MOV #imm, reg => LDR reg 1307 braf @reg braf @reg 1308 nop nop 1309 */ 1310 ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); 1311 1312 offsetBits -= 4; 1313 if (offsetBits >= -4096 && offsetBits <= 4094) { 1314 *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); 1315 *(++instructionPtr) = NOP_OPCODE; 1316 printBlockInstr(instructionPtr - 1, from.m_offset, 2); 1317 return; 1318 } 1319 1320 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); 1321 printInstr(*instructionPtr, from.m_offset + 2); 1322 } 1323 1324 static void linkCall(void* code, JmpSrc from, void* to) 1325 { 1326 uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset); 1327 instructionPtr -= 3; 1328 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to)); 1329 } 1330 1331 static void linkPointer(void* code, JmpDst where, void* value) 1332 { 1333 uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset); 1334 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value)); 1335 } 1336 1337 static unsigned getCallReturnOffset(JmpSrc call) 1338 { 1339 ASSERT(call.m_offset >= 0); 1340 return call.m_offset; 1341 } 1342 1343 static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool) 1344 { 1345 return (constPool + (*insn & 0xff)); 1346 } 1347 1348 static SH4Word patchConstantPoolLoad(SH4Word load, int value) 1349 { 1350 return ((load & ~0xff) | value); 1351 } 1352 1353 static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset) 1354 { 1355 ASSERT(((offset >> 1) <=2047) && ((offset >> 1) >= -2048)); 1356 1357 SH4Buffer::TwoShorts m_barrier; 1358 m_barrier.high = (BRA_OPCODE | (offset >> 1)); 1359 m_barrier.low = NOP_OPCODE; 1360 printInstr(((BRA_OPCODE | (offset >> 1))), 0); 1361 printInstr(NOP_OPCODE, 0); 1362 return m_barrier; 1363 } 1364 1365 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr) 1366 { 1367 SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr); 1368 SH4Word instruction = *instructionPtr; 1369 SH4Word index = instruction & 0xff; 1370 1371 if ((instruction & 0xf000) != MOVIMM_OPCODE) 1372 return; 1373 1374 ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024); 1375 1376 int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4); 1377 instruction &=0xf00; 1378 instruction |= 0xd000; 1379 offset &= 0x03ff; 1380 instruction |= (offset >> 2); 1381 *instructionPtr = instruction; 1382 printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr)); 1383 } 1384 1385 static void repatchPointer(void* where, void* value) 1386 { 1387 patchPointer(where, value); 1388 } 1389 1390 static void repatchInt32(void* where, int32_t value) 1391 { 1392 uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where); 1393 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value); 1394 } 1395 1396 static void relinkCall(void* from, void* to) 1397 { 1398 uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from); 1399 instructionPtr -= 3; 1400 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to)); 1401 } 1402 1403 static void relinkJump(void* from, void* to) 1404 { 1405 uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from); 1406 uint16_t instruction = *instructionPtr; 1407 int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from)); 1408 1409 if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) { 1410 offsetBits -= 8; 1411 instructionPtr++; 1412 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits); 1413 instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00)); 1414 *instructionPtr = instruction; 1415 printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3); 1416 return; 1417 } 1418 1419 ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); 1420 offsetBits -= 4; 1421 if (offsetBits >= -4096 && offsetBits <= 4094) { 1422 *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); 1423 *(++instructionPtr) = NOP_OPCODE; 1424 printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2); 1425 return; 1426 } 1427 1428 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); 1429 printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from)); 1430 } 1431 1432 // Linking & patching 1433 1434 void linkJump(JmpSrc from, JmpDst to) 1435 { 1436 ASSERT(to.m_offset != -1); 1437 ASSERT(from.m_offset != -1); 1438 1439 uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset); 1440 uint16_t instruction = *instructionPtr; 1441 int offsetBits; 1442 1443 if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) { 1444 /* BT label => BF 2 1445 nop LDR reg 1446 nop braf @reg 1447 nop nop 1448 */ 1449 offsetBits = (to.m_offset - from.m_offset) - 8; 1450 instruction ^= 0x0202; 1451 *instructionPtr++ = instruction; 1452 if ((*instructionPtr & 0xf000) == 0xe000) { 1453 uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress()); 1454 *addr = offsetBits; 1455 } else 1456 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits); 1457 instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00)); 1458 *instructionPtr = instruction; 1459 printBlockInstr(instructionPtr - 2, from.m_offset, 3); 1460 return; 1461 } 1462 1463 /* MOV # imm, reg => LDR reg 1464 braf @reg braf @reg 1465 nop nop 1466 */ 1467 ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); 1468 offsetBits = (to.m_offset - from.m_offset) - 4; 1469 if (offsetBits >= -4096 && offsetBits <= 4094) { 1470 *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); 1471 *(++instructionPtr) = NOP_OPCODE; 1472 printBlockInstr(instructionPtr - 1, from.m_offset, 2); 1473 return; 1474 } 1475 1476 instruction = *instructionPtr; 1477 if ((instruction & 0xf000) == 0xe000) { 1478 uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress()); 1479 *addr = offsetBits - 2; 1480 printInstr(*instructionPtr, from.m_offset + 2); 1481 return; 1482 } 1483 1484 changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); 1485 printInstr(*instructionPtr, from.m_offset + 2); 1486 } 1487 1488 static void* getRelocatedAddress(void* code, JmpSrc jump) 1489 { 1490 return reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) + jump.m_offset); 1491 } 1492 1493 static void* getRelocatedAddress(void* code, JmpDst destination) 1494 { 1495 ASSERT(destination.m_offset != -1); 1496 return reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) + destination.m_offset); 1497 } 1498 1499 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst) 1500 { 1501 return dst.m_offset - src.m_offset; 1502 } 1503 1504 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst) 1505 { 1506 return dst.m_offset - src.m_offset; 1507 } 1508 1509 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst) 1510 { 1511 return dst.m_offset - src.m_offset; 1512 } 1513 1514 static void patchPointer(void* code, JmpDst where, void* value) 1515 { 1516 patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value); 1517 } 1518 1519 static void patchPointer(void* code, void* value) 1520 { 1521 patchInt32(code, reinterpret_cast<uint32_t>(value)); 1522 } 1523 1524 static void patchInt32(void* code, uint32_t value) 1525 { 1526 changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value); 1527 } 1528 1529 void* executableCopy(ExecutablePool* allocator) 1530 { 1531 void* copy = m_buffer.executableCopy(allocator); 1532 ASSERT(copy); 1533 return copy; 1534 } 1535 1536 void prefix(uint16_t pre) 1537 { 1538 m_buffer.putByte(pre); 1539 } 1540 1541 void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true) 1542 { 1543 printInstr(opcode, m_buffer.uncheckedSize(), isDouble); 1544 if (checksize) 1545 m_buffer.ensureSpace(maxInstructionSize); 1546 m_buffer.putShortUnchecked(opcode); 1547 } 1548 1549 void ensureSpace(int space) 1550 { 1551 m_buffer.ensureSpace(space); 1552 } 1553 1554 void ensureSpace(int insnSpace, int constSpace) 1555 { 1556 m_buffer.ensureSpace(insnSpace, constSpace); 1557 } 1558 1559 // Administrative methods 1560 1561 void* data() const { return m_buffer.data(); } 1562 int size() 1563 { 1564 return m_buffer.size(); 1565 } 1566 1567 #ifdef SH4_ASSEMBLER_TRACING 1568 static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true) 1569 { 1570 if (!getenv("JavaScriptCoreDumpJIT")) 1571 return; 1572 1573 const char *format = 0; 1574 printfStdoutInstr("offset: 0x%8.8x\t", size); 1575 switch (opc) { 1576 case BRK_OPCODE: 1577 format = " BRK\n"; 1578 break; 1579 case NOP_OPCODE: 1580 format = " NOP\n"; 1581 break; 1582 case RTS_OPCODE: 1583 format =" *RTS\n"; 1584 break; 1585 case SETS_OPCODE: 1586 format = " SETS\n"; 1587 break; 1588 case SETT_OPCODE: 1589 format = " SETT\n"; 1590 break; 1591 case CLRT_OPCODE: 1592 format = " CLRT\n"; 1593 break; 1594 case FSCHG_OPCODE: 1595 format = " FSCHG\n"; 1596 break; 1597 } 1598 if (format) { 1599 printfStdoutInstr(format); 1600 return; 1601 } 1602 switch (opc & 0xf0ff) { 1603 case BRAF_OPCODE: 1604 format = " *BRAF R%d\n"; 1605 break; 1606 case DT_OPCODE: 1607 format = " DT R%d\n"; 1608 break; 1609 case CMPPL_OPCODE: 1610 format = " CMP/PL R%d\n"; 1611 break; 1612 case CMPPZ_OPCODE: 1613 format = " CMP/PZ R%d\n"; 1614 break; 1615 case JMP_OPCODE: 1616 format = " *JMP @R%d\n"; 1617 break; 1618 case JSR_OPCODE: 1619 format = " *JSR @R%d\n"; 1620 break; 1621 case LDSPR_OPCODE: 1622 format = " LDS R%d, PR\n"; 1623 break; 1624 case LDSLPR_OPCODE: 1625 format = " LDS.L @R%d+, PR\n"; 1626 break; 1627 case MOVT_OPCODE: 1628 format = " MOVT R%d\n"; 1629 break; 1630 case SHAL_OPCODE: 1631 format = " SHAL R%d\n"; 1632 break; 1633 case SHAR_OPCODE: 1634 format = " SHAR R%d\n"; 1635 break; 1636 case SHLL_OPCODE: 1637 format = " SHLL R%d\n"; 1638 break; 1639 case SHLL2_OPCODE: 1640 format = " SHLL2 R%d\n"; 1641 break; 1642 case SHLL8_OPCODE: 1643 format = " SHLL8 R%d\n"; 1644 break; 1645 case SHLL16_OPCODE: 1646 format = " SHLL16 R%d\n"; 1647 break; 1648 case SHLR_OPCODE: 1649 format = " SHLR R%d\n"; 1650 break; 1651 case SHLR2_OPCODE: 1652 format = " SHLR2 R%d\n"; 1653 break; 1654 case SHLR8_OPCODE: 1655 format = " SHLR8 R%d\n"; 1656 break; 1657 case SHLR16_OPCODE: 1658 format = " SHLR16 R%d\n"; 1659 break; 1660 case STSPR_OPCODE: 1661 format = " STS PR, R%d\n"; 1662 break; 1663 case STSLPR_OPCODE: 1664 format = " STS.L PR, @-R%d\n"; 1665 break; 1666 case LDS_RM_FPUL_OPCODE: 1667 format = " LDS R%d, FPUL\n"; 1668 break; 1669 case STS_FPUL_RN_OPCODE: 1670 format = " STS FPUL, R%d \n"; 1671 break; 1672 case FLDS_FRM_FPUL_OPCODE: 1673 format = " FLDS FR%d, FPUL\n"; 1674 break; 1675 case FSTS_FPUL_FRN_OPCODE: 1676 format = " FSTS FPUL, R%d \n"; 1677 break; 1678 case LDSFPSCR_OPCODE: 1679 format = " LDS R%d, FPSCR \n"; 1680 break; 1681 case STSFPSCR_OPCODE: 1682 format = " STS FPSCR, R%d \n"; 1683 break; 1684 case STSMACL_OPCODE: 1685 format = " STS MACL, R%d \n"; 1686 break; 1687 case STSMACH_OPCODE: 1688 format = " STS MACH, R%d \n"; 1689 break; 1690 case BSRF_OPCODE: 1691 format = " *BSRF R%d"; 1692 break; 1693 case FTRC_OPCODE: 1694 format = " FTRC FR%d, FPUL\n"; 1695 break; 1696 } 1697 if (format) { 1698 printfStdoutInstr(format, getRn(opc)); 1699 return; 1700 } 1701 switch (opc & 0xf0ff) { 1702 case FNEG_OPCODE: 1703 format = " FNEG DR%d\n"; 1704 break; 1705 case FLOAT_OPCODE: 1706 format = " FLOAT DR%d\n"; 1707 break; 1708 case FTRC_OPCODE: 1709 format = " FTRC FR%d, FPUL\n"; 1710 break; 1711 case FSQRT_OPCODE: 1712 format = " FSQRT FR%d\n"; 1713 break; 1714 case FCNVDS_DRM_FPUL_OPCODE: 1715 format = " FCNVDS FR%d, FPUL\n"; 1716 break; 1717 } 1718 if (format) { 1719 if (isdoubleInst) 1720 printfStdoutInstr(format, getDRn(opc) << 1); 1721 else 1722 printfStdoutInstr(format, getRn(opc)); 1723 return; 1724 } 1725 switch (opc & 0xf00f) { 1726 case ADD_OPCODE: 1727 format = " ADD R%d, R%d\n"; 1728 break; 1729 case ADDC_OPCODE: 1730 format = " ADDC R%d, R%d\n"; 1731 break; 1732 case ADDV_OPCODE: 1733 format = " ADDV R%d, R%d\n"; 1734 break; 1735 case AND_OPCODE: 1736 format = " AND R%d, R%d\n"; 1737 break; 1738 case DIV1_OPCODE: 1739 format = " DIV1 R%d, R%d\n"; 1740 break; 1741 case CMPEQ_OPCODE: 1742 format = " CMP/EQ R%d, R%d\n"; 1743 break; 1744 case CMPGE_OPCODE: 1745 format = " CMP/GE R%d, R%d\n"; 1746 break; 1747 case CMPGT_OPCODE: 1748 format = " CMP/GT R%d, R%d\n"; 1749 break; 1750 case CMPHI_OPCODE: 1751 format = " CMP/HI R%d, R%d\n"; 1752 break; 1753 case CMPHS_OPCODE: 1754 format = " CMP/HS R%d, R%d\n"; 1755 break; 1756 case MOV_OPCODE: 1757 format = " MOV R%d, R%d\n"; 1758 break; 1759 case MOVB_WRITE_RN_OPCODE: 1760 format = " MOV.B R%d, @R%d\n"; 1761 break; 1762 case MOVB_WRITE_RNDEC_OPCODE: 1763 format = " MOV.B R%d, @-R%d\n"; 1764 break; 1765 case MOVB_WRITE_R0RN_OPCODE: 1766 format = " MOV.B R%d, @(R0, R%d)\n"; 1767 break; 1768 case MOVB_READ_RM_OPCODE: 1769 format = " MOV.B @R%d, R%d\n"; 1770 break; 1771 case MOVB_READ_RMINC_OPCODE: 1772 format = " MOV.B @R%d+, R%d\n"; 1773 break; 1774 case MOVB_READ_R0RM_OPCODE: 1775 format = " MOV.B @(R0, R%d), R%d\n"; 1776 break; 1777 case MOVL_WRITE_RN_OPCODE: 1778 format = " MOV.L R%d, @R%d\n"; 1779 break; 1780 case MOVL_WRITE_RNDEC_OPCODE: 1781 format = " MOV.L R%d, @-R%d\n"; 1782 break; 1783 case MOVL_WRITE_R0RN_OPCODE: 1784 format = " MOV.L R%d, @(R0, R%d)\n"; 1785 break; 1786 case MOVL_READ_RM_OPCODE: 1787 format = " MOV.L @R%d, R%d\n"; 1788 break; 1789 case MOVL_READ_RMINC_OPCODE: 1790 format = " MOV.L @R%d+, R%d\n"; 1791 break; 1792 case MOVL_READ_R0RM_OPCODE: 1793 format = " MOV.L @(R0, R%d), R%d\n"; 1794 break; 1795 case MULL_OPCODE: 1796 format = " MUL.L R%d, R%d\n"; 1797 break; 1798 case DMULL_L_OPCODE: 1799 format = " DMULU.L R%d, R%d\n"; 1800 break; 1801 case DMULSL_OPCODE: 1802 format = " DMULS.L R%d, R%d\n"; 1803 break; 1804 case NEG_OPCODE: 1805 format = " NEG R%d, R%d\n"; 1806 break; 1807 case NEGC_OPCODE: 1808 format = " NEGC R%d, R%d\n"; 1809 break; 1810 case NOT_OPCODE: 1811 format = " NOT R%d, R%d\n"; 1812 break; 1813 case OR_OPCODE: 1814 format = " OR R%d, R%d\n"; 1815 break; 1816 case SHAD_OPCODE: 1817 format = " SHAD R%d, R%d\n"; 1818 break; 1819 case SHLD_OPCODE: 1820 format = " SHLD R%d, R%d\n"; 1821 break; 1822 case SUB_OPCODE: 1823 format = " SUB R%d, R%d\n"; 1824 break; 1825 case SUBC_OPCODE: 1826 format = " SUBC R%d, R%d\n"; 1827 break; 1828 case SUBV_OPCODE: 1829 format = " SUBV R%d, R%d\n"; 1830 break; 1831 case TST_OPCODE: 1832 format = " TST R%d, R%d\n"; 1833 break; 1834 case XOR_OPCODE: 1835 format = " XOR R%d, R%d\n";break; 1836 case MOVW_WRITE_RN_OPCODE: 1837 format = " MOV.W R%d, @R%d\n"; 1838 break; 1839 case MOVW_READ_RM_OPCODE: 1840 format = " MOV.W @R%d, R%d\n"; 1841 break; 1842 case MOVW_READ_R0RM_OPCODE: 1843 format = " MOV.W @(R0, R%d), R%d\n"; 1844 break; 1845 case EXTUW_OPCODE: 1846 format = " EXTU.W R%d, R%d\n"; 1847 break; 1848 } 1849 if (format) { 1850 printfStdoutInstr(format, getRm(opc), getRn(opc)); 1851 return; 1852 } 1853 switch (opc & 0xf00f) { 1854 case FSUB_OPCODE: 1855 format = " FSUB FR%d, FR%d\n"; 1856 break; 1857 case FADD_OPCODE: 1858 format = " FADD FR%d, FR%d\n"; 1859 break; 1860 case FDIV_OPCODE: 1861 format = " FDIV FR%d, FR%d\n"; 1862 break; 1863 case FMUL_OPCODE: 1864 format = " DMULL FR%d, FR%d\n"; 1865 break; 1866 case FMOV_OPCODE: 1867 format = " FMOV FR%d, FR%d\n"; 1868 break; 1869 case FCMPEQ_OPCODE: 1870 format = " FCMP/EQ FR%d, FR%d\n"; 1871 break; 1872 case FCMPGT_OPCODE: 1873 format = " FCMP/GT FR%d, FR%d\n"; 1874 break; 1875 } 1876 if (format) { 1877 if (isdoubleInst) 1878 printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1); 1879 else 1880 printfStdoutInstr(format, getRm(opc), getRn(opc)); 1881 return; 1882 } 1883 switch (opc & 0xf00f) { 1884 case FMOVS_WRITE_RN_DEC_OPCODE: 1885 format = " %s FR%d, @-R%d\n"; 1886 break; 1887 case FMOVS_WRITE_RN_OPCODE: 1888 format = " %s FR%d, @R%d\n"; 1889 break; 1890 case FMOVS_WRITE_R0RN_OPCODE: 1891 format = " %s FR%d, @(R0, R%d)\n"; 1892 break; 1893 } 1894 if (format) { 1895 if (isdoubleInst) 1896 printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc)); 1897 else 1898 printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc)); 1899 return; 1900 } 1901 switch (opc & 0xf00f) { 1902 case FMOVS_READ_RM_OPCODE: 1903 format = " %s @R%d, FR%d\n"; 1904 break; 1905 case FMOVS_READ_RM_INC_OPCODE: 1906 format = " %s @R%d+, FR%d\n"; 1907 break; 1908 case FMOVS_READ_R0RM_OPCODE: 1909 format = " %s @(R0, R%d), FR%d\n"; 1910 break; 1911 } 1912 if (format) { 1913 if (isdoubleInst) 1914 printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1); 1915 else 1916 printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc)); 1917 return; 1918 } 1919 switch (opc & 0xff00) { 1920 case BF_OPCODE: 1921 format = " BF %d\n"; 1922 break; 1923 case BFS_OPCODE: 1924 format = " *BF/S %d\n"; 1925 break; 1926 case ANDIMM_OPCODE: 1927 format = " AND #%d, R0\n"; 1928 break; 1929 case BT_OPCODE: 1930 format = " BT %d\n"; 1931 break; 1932 case BTS_OPCODE: 1933 format = " *BT/S %d\n"; 1934 break; 1935 case CMPEQIMM_OPCODE: 1936 format = " CMP/EQ #%d, R0\n"; 1937 break; 1938 case MOVB_WRITE_OFFGBR_OPCODE: 1939 format = " MOV.B R0, @(%d, GBR)\n"; 1940 break; 1941 case MOVB_READ_OFFGBR_OPCODE: 1942 format = " MOV.B @(%d, GBR), R0\n"; 1943 break; 1944 case MOVL_WRITE_OFFGBR_OPCODE: 1945 format = " MOV.L R0, @(%d, GBR)\n"; 1946 break; 1947 case MOVL_READ_OFFGBR_OPCODE: 1948 format = " MOV.L @(%d, GBR), R0\n"; 1949 break; 1950 case MOVA_READ_OFFPC_OPCODE: 1951 format = " MOVA @(%d, PC), R0\n"; 1952 break; 1953 case ORIMM_OPCODE: 1954 format = " OR #%d, R0\n"; 1955 break; 1956 case ORBIMM_OPCODE: 1957 format = " OR.B #%d, @(R0, GBR)\n"; 1958 break; 1959 case TSTIMM_OPCODE: 1960 format = " TST #%d, R0\n"; 1961 break; 1962 case TSTB_OPCODE: 1963 format = " TST.B %d, @(R0, GBR)\n"; 1964 break; 1965 case XORIMM_OPCODE: 1966 format = " XOR #%d, R0\n"; 1967 break; 1968 case XORB_OPCODE: 1969 format = " XOR.B %d, @(R0, GBR)\n"; 1970 break; 1971 } 1972 if (format) { 1973 printfStdoutInstr(format, getImm8(opc)); 1974 return; 1975 } 1976 switch (opc & 0xff00) { 1977 case MOVB_WRITE_OFFRN_OPCODE: 1978 format = " MOV.B R0, @(%d, R%d)\n"; 1979 break; 1980 case MOVB_READ_OFFRM_OPCODE: 1981 format = " MOV.B @(%d, R%d), R0\n"; 1982 break; 1983 } 1984 if (format) { 1985 printfStdoutInstr(format, getDisp(opc), getRm(opc)); 1986 return; 1987 } 1988 switch (opc & 0xf000) { 1989 case BRA_OPCODE: 1990 format = " *BRA %d\n"; 1991 break; 1992 case BSR_OPCODE: 1993 format = " *BSR %d\n"; 1994 break; 1995 } 1996 if (format) { 1997 printfStdoutInstr(format, getImm12(opc)); 1998 return; 1999 } 2000 switch (opc & 0xf000) { 2001 case MOVL_READ_OFFPC_OPCODE: 2002 format = " MOV.L @(%d, PC), R%d\n"; 2003 break; 2004 case ADDIMM_OPCODE: 2005 format = " ADD #%d, R%d\n"; 2006 break; 2007 case MOVIMM_OPCODE: 2008 format = " MOV #%d, R%d\n"; 2009 break; 2010 case MOVW_READ_OFFPC_OPCODE: 2011 format = " MOV.W @(%d, PC), R%d\n"; 2012 break; 2013 } 2014 if (format) { 2015 printfStdoutInstr(format, getImm8(opc), getRn(opc)); 2016 return; 2017 } 2018 switch (opc & 0xf000) { 2019 case MOVL_WRITE_OFFRN_OPCODE: 2020 format = " MOV.L R%d, @(%d, R%d)\n"; 2021 printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc)); 2022 break; 2023 case MOVL_READ_OFFRM_OPCODE: 2024 format = " MOV.L @(%d, R%d), R%d\n"; 2025 printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc)); 2026 break; 2027 } 2028 } 2029 2030 static void printfStdoutInstr(const char* format, ...) 2031 { 2032 if (getenv("JavaScriptCoreDumpJIT")) { 2033 va_list args; 2034 va_start(args, format); 2035 vprintfStdoutInstr(format, args); 2036 va_end(args); 2037 } 2038 } 2039 2040 static void vprintfStdoutInstr(const char* format, va_list args) 2041 { 2042 if (getenv("JavaScriptCoreDumpJIT")) 2043 vfprintf(stdout, format, args); 2044 } 2045 2046 static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) 2047 { 2048 printfStdoutInstr(">> repatch instructions after link\n"); 2049 for (int i = 0; i <= nbInstr; i++) 2050 printInstr(*(first + i), offset + i); 2051 printfStdoutInstr(">> end repatch\n"); 2052 } 2053 #else 2054 static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true) {}; 2055 static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) {}; 2056 #endif 2057 2058 private: 2059 SH4Buffer m_buffer; 2060 int m_claimscratchReg; 2061 }; 2062 2063 } // namespace JSC 2064 2065 #endif // ENABLE(ASSEMBLER) && CPU(SH4) 2066 2067 #endif // SH4Assembler_h 2068