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