1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2012, 2015 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "precompiled.hpp" 27 #include "asm/assembler.inline.hpp" 28 #include "gc/shared/cardTableBarrierSet.hpp" 29 #include "gc/shared/collectedHeap.inline.hpp" 30 #include "interpreter/interpreter.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "prims/methodHandles.hpp" 33 #include "runtime/biasedLocking.hpp" 34 #include "runtime/interfaceSupport.inline.hpp" 35 #include "runtime/objectMonitor.hpp" 36 #include "runtime/os.hpp" 37 #include "runtime/sharedRuntime.hpp" 38 #include "runtime/stubRoutines.hpp" 39 #include "utilities/macros.hpp" 40 #if INCLUDE_ALL_GCS 41 #include "gc/g1/g1BarrierSet.hpp" 42 #include "gc/g1/heapRegion.hpp" 43 #endif // INCLUDE_ALL_GCS 44 45 #ifdef PRODUCT 46 #define BLOCK_COMMENT(str) // nothing 47 #else 48 #define BLOCK_COMMENT(str) block_comment(str) 49 #endif 50 51 int AbstractAssembler::code_fill_byte() { 52 return 0x00; // illegal instruction 0x00000000 53 } 54 55 56 // Patch instruction `inst' at offset `inst_pos' to refer to 57 // `dest_pos' and return the resulting instruction. We should have 58 // pcs, not offsets, but since all is relative, it will work out fine. 59 int Assembler::patched_branch(int dest_pos, int inst, int inst_pos) { 60 int m = 0; // mask for displacement field 61 int v = 0; // new value for displacement field 62 63 switch (inv_op_ppc(inst)) { 64 case b_op: m = li(-1); v = li(disp(dest_pos, inst_pos)); break; 65 case bc_op: m = bd(-1); v = bd(disp(dest_pos, inst_pos)); break; 66 default: ShouldNotReachHere(); 67 } 68 return inst & ~m | v; 69 } 70 71 // Return the offset, relative to _code_begin, of the destination of 72 // the branch inst at offset pos. 73 int Assembler::branch_destination(int inst, int pos) { 74 int r = 0; 75 switch (inv_op_ppc(inst)) { 76 case b_op: r = bxx_destination_offset(inst, pos); break; 77 case bc_op: r = inv_bd_field(inst, pos); break; 78 default: ShouldNotReachHere(); 79 } 80 return r; 81 } 82 83 // Low-level andi-one-instruction-macro. 84 void Assembler::andi(Register a, Register s, const long ui16) { 85 if (is_power_of_2_long(((jlong) ui16)+1)) { 86 // pow2minus1 87 clrldi(a, s, 64-log2_long((((jlong) ui16)+1))); 88 } else if (is_power_of_2_long((jlong) ui16)) { 89 // pow2 90 rlwinm(a, s, 0, 31-log2_long((jlong) ui16), 31-log2_long((jlong) ui16)); 91 } else if (is_power_of_2_long((jlong)-ui16)) { 92 // negpow2 93 clrrdi(a, s, log2_long((jlong)-ui16)); 94 } else { 95 assert(is_uimm(ui16, 16), "must be 16-bit unsigned immediate"); 96 andi_(a, s, ui16); 97 } 98 } 99 100 // RegisterOrConstant version. 101 void Assembler::ld(Register d, RegisterOrConstant roc, Register s1) { 102 if (roc.is_constant()) { 103 if (s1 == noreg) { 104 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 105 Assembler::ld(d, simm16_rest, d); 106 } else if (is_simm(roc.as_constant(), 16)) { 107 Assembler::ld(d, roc.as_constant(), s1); 108 } else { 109 load_const_optimized(d, roc.as_constant()); 110 Assembler::ldx(d, d, s1); 111 } 112 } else { 113 if (s1 == noreg) 114 Assembler::ld(d, 0, roc.as_register()); 115 else 116 Assembler::ldx(d, roc.as_register(), s1); 117 } 118 } 119 120 void Assembler::lwa(Register d, RegisterOrConstant roc, Register s1) { 121 if (roc.is_constant()) { 122 if (s1 == noreg) { 123 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 124 Assembler::lwa(d, simm16_rest, d); 125 } else if (is_simm(roc.as_constant(), 16)) { 126 Assembler::lwa(d, roc.as_constant(), s1); 127 } else { 128 load_const_optimized(d, roc.as_constant()); 129 Assembler::lwax(d, d, s1); 130 } 131 } else { 132 if (s1 == noreg) 133 Assembler::lwa(d, 0, roc.as_register()); 134 else 135 Assembler::lwax(d, roc.as_register(), s1); 136 } 137 } 138 139 void Assembler::lwz(Register d, RegisterOrConstant roc, Register s1) { 140 if (roc.is_constant()) { 141 if (s1 == noreg) { 142 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 143 Assembler::lwz(d, simm16_rest, d); 144 } else if (is_simm(roc.as_constant(), 16)) { 145 Assembler::lwz(d, roc.as_constant(), s1); 146 } else { 147 load_const_optimized(d, roc.as_constant()); 148 Assembler::lwzx(d, d, s1); 149 } 150 } else { 151 if (s1 == noreg) 152 Assembler::lwz(d, 0, roc.as_register()); 153 else 154 Assembler::lwzx(d, roc.as_register(), s1); 155 } 156 } 157 158 void Assembler::lha(Register d, RegisterOrConstant roc, Register s1) { 159 if (roc.is_constant()) { 160 if (s1 == noreg) { 161 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 162 Assembler::lha(d, simm16_rest, d); 163 } else if (is_simm(roc.as_constant(), 16)) { 164 Assembler::lha(d, roc.as_constant(), s1); 165 } else { 166 load_const_optimized(d, roc.as_constant()); 167 Assembler::lhax(d, d, s1); 168 } 169 } else { 170 if (s1 == noreg) 171 Assembler::lha(d, 0, roc.as_register()); 172 else 173 Assembler::lhax(d, roc.as_register(), s1); 174 } 175 } 176 177 void Assembler::lhz(Register d, RegisterOrConstant roc, Register s1) { 178 if (roc.is_constant()) { 179 if (s1 == noreg) { 180 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 181 Assembler::lhz(d, simm16_rest, d); 182 } else if (is_simm(roc.as_constant(), 16)) { 183 Assembler::lhz(d, roc.as_constant(), s1); 184 } else { 185 load_const_optimized(d, roc.as_constant()); 186 Assembler::lhzx(d, d, s1); 187 } 188 } else { 189 if (s1 == noreg) 190 Assembler::lhz(d, 0, roc.as_register()); 191 else 192 Assembler::lhzx(d, roc.as_register(), s1); 193 } 194 } 195 196 void Assembler::lbz(Register d, RegisterOrConstant roc, Register s1) { 197 if (roc.is_constant()) { 198 if (s1 == noreg) { 199 int simm16_rest = load_const_optimized(d, roc.as_constant(), noreg, true); 200 Assembler::lbz(d, simm16_rest, d); 201 } else if (is_simm(roc.as_constant(), 16)) { 202 Assembler::lbz(d, roc.as_constant(), s1); 203 } else { 204 load_const_optimized(d, roc.as_constant()); 205 Assembler::lbzx(d, d, s1); 206 } 207 } else { 208 if (s1 == noreg) 209 Assembler::lbz(d, 0, roc.as_register()); 210 else 211 Assembler::lbzx(d, roc.as_register(), s1); 212 } 213 } 214 215 void Assembler::std(Register d, RegisterOrConstant roc, Register s1, Register tmp) { 216 if (roc.is_constant()) { 217 if (s1 == noreg) { 218 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 219 int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); 220 Assembler::std(d, simm16_rest, tmp); 221 } else if (is_simm(roc.as_constant(), 16)) { 222 Assembler::std(d, roc.as_constant(), s1); 223 } else { 224 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 225 load_const_optimized(tmp, roc.as_constant()); 226 Assembler::stdx(d, tmp, s1); 227 } 228 } else { 229 if (s1 == noreg) 230 Assembler::std(d, 0, roc.as_register()); 231 else 232 Assembler::stdx(d, roc.as_register(), s1); 233 } 234 } 235 236 void Assembler::stw(Register d, RegisterOrConstant roc, Register s1, Register tmp) { 237 if (roc.is_constant()) { 238 if (s1 == noreg) { 239 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 240 int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); 241 Assembler::stw(d, simm16_rest, tmp); 242 } else if (is_simm(roc.as_constant(), 16)) { 243 Assembler::stw(d, roc.as_constant(), s1); 244 } else { 245 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 246 load_const_optimized(tmp, roc.as_constant()); 247 Assembler::stwx(d, tmp, s1); 248 } 249 } else { 250 if (s1 == noreg) 251 Assembler::stw(d, 0, roc.as_register()); 252 else 253 Assembler::stwx(d, roc.as_register(), s1); 254 } 255 } 256 257 void Assembler::sth(Register d, RegisterOrConstant roc, Register s1, Register tmp) { 258 if (roc.is_constant()) { 259 if (s1 == noreg) { 260 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 261 int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); 262 Assembler::sth(d, simm16_rest, tmp); 263 } else if (is_simm(roc.as_constant(), 16)) { 264 Assembler::sth(d, roc.as_constant(), s1); 265 } else { 266 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 267 load_const_optimized(tmp, roc.as_constant()); 268 Assembler::sthx(d, tmp, s1); 269 } 270 } else { 271 if (s1 == noreg) 272 Assembler::sth(d, 0, roc.as_register()); 273 else 274 Assembler::sthx(d, roc.as_register(), s1); 275 } 276 } 277 278 void Assembler::stb(Register d, RegisterOrConstant roc, Register s1, Register tmp) { 279 if (roc.is_constant()) { 280 if (s1 == noreg) { 281 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 282 int simm16_rest = load_const_optimized(tmp, roc.as_constant(), noreg, true); 283 Assembler::stb(d, simm16_rest, tmp); 284 } else if (is_simm(roc.as_constant(), 16)) { 285 Assembler::stb(d, roc.as_constant(), s1); 286 } else { 287 guarantee(tmp != noreg, "Need tmp reg to encode large constants"); 288 load_const_optimized(tmp, roc.as_constant()); 289 Assembler::stbx(d, tmp, s1); 290 } 291 } else { 292 if (s1 == noreg) 293 Assembler::stb(d, 0, roc.as_register()); 294 else 295 Assembler::stbx(d, roc.as_register(), s1); 296 } 297 } 298 299 void Assembler::add(Register d, RegisterOrConstant roc, Register s1) { 300 if (roc.is_constant()) { 301 intptr_t c = roc.as_constant(); 302 assert(is_simm(c, 16), "too big"); 303 addi(d, s1, (int)c); 304 } 305 else add(d, roc.as_register(), s1); 306 } 307 308 void Assembler::subf(Register d, RegisterOrConstant roc, Register s1) { 309 if (roc.is_constant()) { 310 intptr_t c = roc.as_constant(); 311 assert(is_simm(-c, 16), "too big"); 312 addi(d, s1, (int)-c); 313 } 314 else subf(d, roc.as_register(), s1); 315 } 316 317 void Assembler::cmpd(ConditionRegister d, RegisterOrConstant roc, Register s1) { 318 if (roc.is_constant()) { 319 intptr_t c = roc.as_constant(); 320 assert(is_simm(c, 16), "too big"); 321 cmpdi(d, s1, (int)c); 322 } 323 else cmpd(d, roc.as_register(), s1); 324 } 325 326 // Load a 64 bit constant. Patchable. 327 void Assembler::load_const(Register d, long x, Register tmp) { 328 // 64-bit value: x = xa xb xc xd 329 int xa = (x >> 48) & 0xffff; 330 int xb = (x >> 32) & 0xffff; 331 int xc = (x >> 16) & 0xffff; 332 int xd = (x >> 0) & 0xffff; 333 if (tmp == noreg) { 334 Assembler::lis( d, (int)(short)xa); 335 Assembler::ori( d, d, (unsigned int)xb); 336 Assembler::sldi(d, d, 32); 337 Assembler::oris(d, d, (unsigned int)xc); 338 Assembler::ori( d, d, (unsigned int)xd); 339 } else { 340 // exploit instruction level parallelism if we have a tmp register 341 assert_different_registers(d, tmp); 342 Assembler::lis(tmp, (int)(short)xa); 343 Assembler::lis(d, (int)(short)xc); 344 Assembler::ori(tmp, tmp, (unsigned int)xb); 345 Assembler::ori(d, d, (unsigned int)xd); 346 Assembler::insrdi(d, tmp, 32, 0); 347 } 348 } 349 350 // Load a 64 bit constant, optimized, not identifyable. 351 // Tmp can be used to increase ILP. Set return_simm16_rest=true to get a 352 // 16 bit immediate offset. 353 int Assembler::load_const_optimized(Register d, long x, Register tmp, bool return_simm16_rest) { 354 // Avoid accidentally trying to use R0 for indexed addressing. 355 assert_different_registers(d, tmp); 356 357 short xa, xb, xc, xd; // Four 16-bit chunks of const. 358 long rem = x; // Remaining part of const. 359 360 xd = rem & 0xFFFF; // Lowest 16-bit chunk. 361 rem = (rem >> 16) + ((unsigned short)xd >> 15); // Compensation for sign extend. 362 363 if (rem == 0) { // opt 1: simm16 364 li(d, xd); 365 return 0; 366 } 367 368 int retval = 0; 369 if (return_simm16_rest) { 370 retval = xd; 371 x = rem << 16; 372 xd = 0; 373 } 374 375 if (d == R0) { // Can't use addi. 376 if (is_simm(x, 32)) { // opt 2: simm32 377 lis(d, x >> 16); 378 if (xd) ori(d, d, (unsigned short)xd); 379 } else { 380 // 64-bit value: x = xa xb xc xd 381 xa = (x >> 48) & 0xffff; 382 xb = (x >> 32) & 0xffff; 383 xc = (x >> 16) & 0xffff; 384 bool xa_loaded = (xb & 0x8000) ? (xa != -1) : (xa != 0); 385 if (tmp == noreg || (xc == 0 && xd == 0)) { 386 if (xa_loaded) { 387 lis(d, xa); 388 if (xb) { ori(d, d, (unsigned short)xb); } 389 } else { 390 li(d, xb); 391 } 392 sldi(d, d, 32); 393 if (xc) { oris(d, d, (unsigned short)xc); } 394 if (xd) { ori( d, d, (unsigned short)xd); } 395 } else { 396 // Exploit instruction level parallelism if we have a tmp register. 397 bool xc_loaded = (xd & 0x8000) ? (xc != -1) : (xc != 0); 398 if (xa_loaded) { 399 lis(tmp, xa); 400 } 401 if (xc_loaded) { 402 lis(d, xc); 403 } 404 if (xa_loaded) { 405 if (xb) { ori(tmp, tmp, (unsigned short)xb); } 406 } else { 407 li(tmp, xb); 408 } 409 if (xc_loaded) { 410 if (xd) { ori(d, d, (unsigned short)xd); } 411 } else { 412 li(d, xd); 413 } 414 insrdi(d, tmp, 32, 0); 415 } 416 } 417 return retval; 418 } 419 420 xc = rem & 0xFFFF; // Next 16-bit chunk. 421 rem = (rem >> 16) + ((unsigned short)xc >> 15); // Compensation for sign extend. 422 423 if (rem == 0) { // opt 2: simm32 424 lis(d, xc); 425 } else { // High 32 bits needed. 426 427 if (tmp != noreg && (int)x != 0) { // opt 3: We have a temp reg. 428 // No carry propagation between xc and higher chunks here (use logical instructions). 429 xa = (x >> 48) & 0xffff; 430 xb = (x >> 32) & 0xffff; // No sign compensation, we use lis+ori or li to allow usage of R0. 431 bool xa_loaded = (xb & 0x8000) ? (xa != -1) : (xa != 0); 432 bool return_xd = false; 433 434 if (xa_loaded) { lis(tmp, xa); } 435 if (xc) { lis(d, xc); } 436 if (xa_loaded) { 437 if (xb) { ori(tmp, tmp, (unsigned short)xb); } // No addi, we support tmp == R0. 438 } else { 439 li(tmp, xb); 440 } 441 if (xc) { 442 if (xd) { addi(d, d, xd); } 443 } else { 444 li(d, xd); 445 } 446 insrdi(d, tmp, 32, 0); 447 return retval; 448 } 449 450 xb = rem & 0xFFFF; // Next 16-bit chunk. 451 rem = (rem >> 16) + ((unsigned short)xb >> 15); // Compensation for sign extend. 452 453 xa = rem & 0xFFFF; // Highest 16-bit chunk. 454 455 // opt 4: avoid adding 0 456 if (xa) { // Highest 16-bit needed? 457 lis(d, xa); 458 if (xb) { addi(d, d, xb); } 459 } else { 460 li(d, xb); 461 } 462 sldi(d, d, 32); 463 if (xc) { addis(d, d, xc); } 464 } 465 466 if (xd) { addi(d, d, xd); } 467 return retval; 468 } 469 470 // We emit only one addition to s to optimize latency. 471 int Assembler::add_const_optimized(Register d, Register s, long x, Register tmp, bool return_simm16_rest) { 472 assert(s != R0 && s != tmp, "unsupported"); 473 long rem = x; 474 475 // Case 1: Can use mr or addi. 476 short xd = rem & 0xFFFF; // Lowest 16-bit chunk. 477 rem = (rem >> 16) + ((unsigned short)xd >> 15); 478 if (rem == 0) { 479 if (xd == 0) { 480 if (d != s) { mr(d, s); } 481 return 0; 482 } 483 if (return_simm16_rest && (d == s)) { 484 return xd; 485 } 486 addi(d, s, xd); 487 return 0; 488 } 489 490 // Case 2: Can use addis. 491 if (xd == 0) { 492 short xc = rem & 0xFFFF; // 2nd 16-bit chunk. 493 rem = (rem >> 16) + ((unsigned short)xd >> 15); 494 if (rem == 0) { 495 addis(d, s, xc); 496 return 0; 497 } 498 } 499 500 // Other cases: load & add. 501 Register tmp1 = tmp, 502 tmp2 = noreg; 503 if ((d != tmp) && (d != s)) { 504 // Can use d. 505 tmp1 = d; 506 tmp2 = tmp; 507 } 508 int simm16_rest = load_const_optimized(tmp1, x, tmp2, return_simm16_rest); 509 add(d, tmp1, s); 510 return simm16_rest; 511 } 512 513 #ifndef PRODUCT 514 // Test of ppc assembler. 515 void Assembler::test_asm() { 516 // PPC 1, section 3.3.8, Fixed-Point Arithmetic Instructions 517 addi( R0, R1, 10); 518 addis( R5, R2, 11); 519 addic_( R3, R31, 42); 520 subfic( R21, R12, 2112); 521 add( R3, R2, R1); 522 add_( R11, R22, R30); 523 subf( R7, R6, R5); 524 subf_( R8, R9, R4); 525 addc( R11, R12, R13); 526 addc_( R14, R14, R14); 527 subfc( R15, R16, R17); 528 subfc_( R18, R20, R19); 529 adde( R20, R22, R24); 530 adde_( R29, R27, R26); 531 subfe( R28, R1, R0); 532 subfe_( R21, R11, R29); 533 neg( R21, R22); 534 neg_( R13, R23); 535 mulli( R0, R11, -31); 536 mulld( R1, R18, R21); 537 mulld_( R2, R17, R22); 538 mullw( R3, R16, R23); 539 mullw_( R4, R15, R24); 540 divd( R5, R14, R25); 541 divd_( R6, R13, R26); 542 divw( R7, R12, R27); 543 divw_( R8, R11, R28); 544 545 li( R3, -4711); 546 547 // PPC 1, section 3.3.9, Fixed-Point Compare Instructions 548 cmpi( CCR7, 0, R27, 4711); 549 cmp( CCR0, 1, R14, R11); 550 cmpli( CCR5, 1, R17, 45); 551 cmpl( CCR3, 0, R9, R10); 552 553 cmpwi( CCR7, R27, 4711); 554 cmpw( CCR0, R14, R11); 555 cmplwi( CCR5, R17, 45); 556 cmplw( CCR3, R9, R10); 557 558 cmpdi( CCR7, R27, 4711); 559 cmpd( CCR0, R14, R11); 560 cmpldi( CCR5, R17, 45); 561 cmpld( CCR3, R9, R10); 562 563 // PPC 1, section 3.3.11, Fixed-Point Logical Instructions 564 andi_( R4, R5, 0xff); 565 andis_( R12, R13, 0x7b51); 566 ori( R1, R4, 13); 567 oris( R3, R5, 177); 568 xori( R7, R6, 51); 569 xoris( R29, R0, 1); 570 andr( R17, R21, R16); 571 and_( R3, R5, R15); 572 orr( R2, R1, R9); 573 or_( R17, R15, R11); 574 xorr( R19, R18, R10); 575 xor_( R31, R21, R11); 576 nand( R5, R7, R3); 577 nand_( R3, R1, R0); 578 nor( R2, R3, R5); 579 nor_( R3, R6, R8); 580 andc( R25, R12, R11); 581 andc_( R24, R22, R21); 582 orc( R20, R10, R12); 583 orc_( R22, R2, R13); 584 585 nop(); 586 587 // PPC 1, section 3.3.12, Fixed-Point Rotate and Shift Instructions 588 sld( R5, R6, R8); 589 sld_( R3, R5, R9); 590 slw( R2, R1, R10); 591 slw_( R6, R26, R16); 592 srd( R16, R24, R8); 593 srd_( R21, R14, R7); 594 srw( R22, R25, R29); 595 srw_( R5, R18, R17); 596 srad( R7, R11, R0); 597 srad_( R9, R13, R1); 598 sraw( R7, R15, R2); 599 sraw_( R4, R17, R3); 600 sldi( R3, R18, 63); 601 sldi_( R2, R20, 30); 602 slwi( R1, R21, 30); 603 slwi_( R7, R23, 8); 604 srdi( R0, R19, 2); 605 srdi_( R12, R24, 5); 606 srwi( R13, R27, 6); 607 srwi_( R14, R29, 7); 608 sradi( R15, R30, 9); 609 sradi_( R16, R31, 19); 610 srawi( R17, R31, 15); 611 srawi_( R18, R31, 12); 612 613 clrrdi( R3, R30, 5); 614 clrldi( R9, R10, 11); 615 616 rldicr( R19, R20, 13, 15); 617 rldicr_(R20, R20, 16, 14); 618 rldicl( R21, R21, 30, 33); 619 rldicl_(R22, R1, 20, 25); 620 rlwinm( R23, R2, 25, 10, 11); 621 rlwinm_(R24, R3, 12, 13, 14); 622 623 // PPC 1, section 3.3.2 Fixed-Point Load Instructions 624 lwzx( R3, R5, R7); 625 lwz( R11, 0, R1); 626 lwzu( R31, -4, R11); 627 628 lwax( R3, R5, R7); 629 lwa( R31, -4, R11); 630 lhzx( R3, R5, R7); 631 lhz( R31, -4, R11); 632 lhzu( R31, -4, R11); 633 634 635 lhax( R3, R5, R7); 636 lha( R31, -4, R11); 637 lhau( R11, 0, R1); 638 639 lbzx( R3, R5, R7); 640 lbz( R31, -4, R11); 641 lbzu( R11, 0, R1); 642 643 ld( R31, -4, R11); 644 ldx( R3, R5, R7); 645 ldu( R31, -4, R11); 646 647 // PPC 1, section 3.3.3 Fixed-Point Store Instructions 648 stwx( R3, R5, R7); 649 stw( R31, -4, R11); 650 stwu( R11, 0, R1); 651 652 sthx( R3, R5, R7 ); 653 sth( R31, -4, R11); 654 sthu( R31, -4, R11); 655 656 stbx( R3, R5, R7); 657 stb( R31, -4, R11); 658 stbu( R31, -4, R11); 659 660 std( R31, -4, R11); 661 stdx( R3, R5, R7); 662 stdu( R31, -4, R11); 663 664 // PPC 1, section 3.3.13 Move To/From System Register Instructions 665 mtlr( R3); 666 mflr( R3); 667 mtctr( R3); 668 mfctr( R3); 669 mtcrf( 0xff, R15); 670 mtcr( R15); 671 mtcrf( 0x03, R15); 672 mtcr( R15); 673 mfcr( R15); 674 675 // PPC 1, section 2.4.1 Branch Instructions 676 Label lbl1, lbl2, lbl3; 677 bind(lbl1); 678 679 b(pc()); 680 b(pc() - 8); 681 b(lbl1); 682 b(lbl2); 683 b(lbl3); 684 685 bl(pc() - 8); 686 bl(lbl1); 687 bl(lbl2); 688 689 bcl(4, 10, pc() - 8); 690 bcl(4, 10, lbl1); 691 bcl(4, 10, lbl2); 692 693 bclr( 4, 6, 0); 694 bclrl(4, 6, 0); 695 696 bind(lbl2); 697 698 bcctr( 4, 6, 0); 699 bcctrl(4, 6, 0); 700 701 blt(CCR0, lbl2); 702 bgt(CCR1, lbl2); 703 beq(CCR2, lbl2); 704 bso(CCR3, lbl2); 705 bge(CCR4, lbl2); 706 ble(CCR5, lbl2); 707 bne(CCR6, lbl2); 708 bns(CCR7, lbl2); 709 710 bltl(CCR0, lbl2); 711 bgtl(CCR1, lbl2); 712 beql(CCR2, lbl2); 713 bsol(CCR3, lbl2); 714 bgel(CCR4, lbl2); 715 blel(CCR5, lbl2); 716 bnel(CCR6, lbl2); 717 bnsl(CCR7, lbl2); 718 blr(); 719 720 sync(); 721 icbi( R1, R2); 722 dcbst(R2, R3); 723 724 // FLOATING POINT instructions ppc. 725 // PPC 1, section 4.6.2 Floating-Point Load Instructions 726 lfs( F1, -11, R3); 727 lfsu(F2, 123, R4); 728 lfsx(F3, R5, R6); 729 lfd( F4, 456, R7); 730 lfdu(F5, 789, R8); 731 lfdx(F6, R10, R11); 732 733 // PPC 1, section 4.6.3 Floating-Point Store Instructions 734 stfs( F7, 876, R12); 735 stfsu( F8, 543, R13); 736 stfsx( F9, R14, R15); 737 stfd( F10, 210, R16); 738 stfdu( F11, 111, R17); 739 stfdx( F12, R18, R19); 740 741 // PPC 1, section 4.6.4 Floating-Point Move Instructions 742 fmr( F13, F14); 743 fmr_( F14, F15); 744 fneg( F16, F17); 745 fneg_( F18, F19); 746 fabs( F20, F21); 747 fabs_( F22, F23); 748 fnabs( F24, F25); 749 fnabs_(F26, F27); 750 751 // PPC 1, section 4.6.5.1 Floating-Point Elementary Arithmetic 752 // Instructions 753 fadd( F28, F29, F30); 754 fadd_( F31, F0, F1); 755 fadds( F2, F3, F4); 756 fadds_(F5, F6, F7); 757 fsub( F8, F9, F10); 758 fsub_( F11, F12, F13); 759 fsubs( F14, F15, F16); 760 fsubs_(F17, F18, F19); 761 fmul( F20, F21, F22); 762 fmul_( F23, F24, F25); 763 fmuls( F26, F27, F28); 764 fmuls_(F29, F30, F31); 765 fdiv( F0, F1, F2); 766 fdiv_( F3, F4, F5); 767 fdivs( F6, F7, F8); 768 fdivs_(F9, F10, F11); 769 770 // PPC 1, section 4.6.6 Floating-Point Rounding and Conversion 771 // Instructions 772 frsp( F12, F13); 773 fctid( F14, F15); 774 fctidz(F16, F17); 775 fctiw( F18, F19); 776 fctiwz(F20, F21); 777 fcfid( F22, F23); 778 779 // PPC 1, section 4.6.7 Floating-Point Compare Instructions 780 fcmpu( CCR7, F24, F25); 781 782 tty->print_cr("\ntest_asm disassembly (0x%lx 0x%lx):", p2i(code()->insts_begin()), p2i(code()->insts_end())); 783 code()->decode(); 784 } 785 786 #endif // !PRODUCT