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 
code_fill_byte()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.
patched_branch(int dest_pos,int inst,int inst_pos)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.
branch_destination(int inst,int 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.
andi(Register a,Register s,const long ui16)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.
ld(Register d,RegisterOrConstant roc,Register s1)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 
lwa(Register d,RegisterOrConstant roc,Register s1)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 
lwz(Register d,RegisterOrConstant roc,Register s1)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 
lha(Register d,RegisterOrConstant roc,Register s1)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 
lhz(Register d,RegisterOrConstant roc,Register s1)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 
lbz(Register d,RegisterOrConstant roc,Register s1)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 
std(Register d,RegisterOrConstant roc,Register s1,Register tmp)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 
stw(Register d,RegisterOrConstant roc,Register s1,Register tmp)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 
sth(Register d,RegisterOrConstant roc,Register s1,Register tmp)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 
stb(Register d,RegisterOrConstant roc,Register s1,Register tmp)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 
add(Register d,RegisterOrConstant roc,Register s1)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 
subf(Register d,RegisterOrConstant roc,Register s1)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 
cmpd(ConditionRegister d,RegisterOrConstant roc,Register s1)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.
load_const(Register d,long x,Register tmp)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.
load_const_optimized(Register d,long x,Register tmp,bool return_simm16_rest)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.
add_const_optimized(Register d,Register s,long x,Register tmp,bool return_simm16_rest)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)xc >> 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.
test_asm()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
783