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