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