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