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