src/cpu/ppc/vm/assembler_ppc.cpp

Thu, 20 Mar 2014 11:03:06 +0100

author
goetz
date
Thu, 20 Mar 2014 11:03:06 +0100
changeset 6515
71a71b0bc844
parent 6458
ec28f9c041ff
child 6876
710a3c8b516e
child 7358
327e7269f90d
permissions
-rw-r--r--

8037915: PPC64/AIX: Several smaller fixes
Reviewed-by: kvn

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

mercurial