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