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