Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/cpu/ppc/assembler_ppc.cpp
40930 views
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
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.
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.
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.
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 - log2i_exact((((jlong) ui16)+1)));
85
} else if (is_power_of_2((jlong) ui16)) {
86
// pow2
87
rlwinm(a, s, 0, 31 - log2i_exact((jlong) ui16), 31 - log2i_exact((jlong) ui16));
88
} else if (is_power_of_2((jlong)-ui16)) {
89
// negpow2
90
clrrdi(a, s, log2i_exact((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.
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
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
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
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
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
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
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
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
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
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
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
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
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.
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.
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.
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.
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
785