src/cpu/ppc/vm/assembler_ppc.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6515
71a71b0bc844
parent 0
f90c822e73f8
child 7535
7ae4e26cb1e0
permissions
-rw-r--r--

merge

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

mercurial