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