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