1 /* 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2014, 2015, Red Hat Inc. 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 #ifndef CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP 27 #define CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP 28 29 #include "asm/register.hpp" 30 31 // definitions of various symbolic names for machine registers 32 33 // First intercalls between C and Java which use 8 general registers 34 // and 8 floating registers 35 36 // we also have to copy between x86 and ARM registers but that's a 37 // secondary complication -- not all code employing C call convention 38 // executes as x86 code though -- we generate some of it 39 40 class Argument VALUE_OBJ_CLASS_SPEC { 41 public: 42 enum { 43 n_int_register_parameters_c = 8, // r0, r1, ... r7 (c_rarg0, c_rarg1, ...) 44 n_float_register_parameters_c = 8, // v0, v1, ... v7 (c_farg0, c_farg1, ... ) 45 46 n_int_register_parameters_j = 8, // r1, ... r7, r0 (rj_rarg0, j_rarg1, ... 47 n_float_register_parameters_j = 8 // v0, v1, ... v7 (j_farg0, j_farg1, ... 48 }; 49 }; 50 51 REGISTER_DECLARATION(Register, c_rarg0, r0); 52 REGISTER_DECLARATION(Register, c_rarg1, r1); 53 REGISTER_DECLARATION(Register, c_rarg2, r2); 54 REGISTER_DECLARATION(Register, c_rarg3, r3); 55 REGISTER_DECLARATION(Register, c_rarg4, r4); 56 REGISTER_DECLARATION(Register, c_rarg5, r5); 57 REGISTER_DECLARATION(Register, c_rarg6, r6); 58 REGISTER_DECLARATION(Register, c_rarg7, r7); 59 60 REGISTER_DECLARATION(FloatRegister, c_farg0, v0); 61 REGISTER_DECLARATION(FloatRegister, c_farg1, v1); 62 REGISTER_DECLARATION(FloatRegister, c_farg2, v2); 63 REGISTER_DECLARATION(FloatRegister, c_farg3, v3); 64 REGISTER_DECLARATION(FloatRegister, c_farg4, v4); 65 REGISTER_DECLARATION(FloatRegister, c_farg5, v5); 66 REGISTER_DECLARATION(FloatRegister, c_farg6, v6); 67 REGISTER_DECLARATION(FloatRegister, c_farg7, v7); 68 69 // Symbolically name the register arguments used by the Java calling convention. 70 // We have control over the convention for java so we can do what we please. 71 // What pleases us is to offset the java calling convention so that when 72 // we call a suitable jni method the arguments are lined up and we don't 73 // have to do much shuffling. A suitable jni method is non-static and a 74 // small number of arguments 75 // 76 // |--------------------------------------------------------------------| 77 // | c_rarg0 c_rarg1 c_rarg2 c_rarg3 c_rarg4 c_rarg5 c_rarg6 c_rarg7 | 78 // |--------------------------------------------------------------------| 79 // | r0 r1 r2 r3 r4 r5 r6 r7 | 80 // |--------------------------------------------------------------------| 81 // | j_rarg7 j_rarg0 j_rarg1 j_rarg2 j_rarg3 j_rarg4 j_rarg5 j_rarg6 | 82 // |--------------------------------------------------------------------| 83 84 85 REGISTER_DECLARATION(Register, j_rarg0, c_rarg1); 86 REGISTER_DECLARATION(Register, j_rarg1, c_rarg2); 87 REGISTER_DECLARATION(Register, j_rarg2, c_rarg3); 88 REGISTER_DECLARATION(Register, j_rarg3, c_rarg4); 89 REGISTER_DECLARATION(Register, j_rarg4, c_rarg5); 90 REGISTER_DECLARATION(Register, j_rarg5, c_rarg6); 91 REGISTER_DECLARATION(Register, j_rarg6, c_rarg7); 92 REGISTER_DECLARATION(Register, j_rarg7, c_rarg0); 93 94 // Java floating args are passed as per C 95 96 REGISTER_DECLARATION(FloatRegister, j_farg0, v0); 97 REGISTER_DECLARATION(FloatRegister, j_farg1, v1); 98 REGISTER_DECLARATION(FloatRegister, j_farg2, v2); 99 REGISTER_DECLARATION(FloatRegister, j_farg3, v3); 100 REGISTER_DECLARATION(FloatRegister, j_farg4, v4); 101 REGISTER_DECLARATION(FloatRegister, j_farg5, v5); 102 REGISTER_DECLARATION(FloatRegister, j_farg6, v6); 103 REGISTER_DECLARATION(FloatRegister, j_farg7, v7); 104 105 // registers used to hold VM data either temporarily within a method 106 // or across method calls 107 108 // volatile (caller-save) registers 109 110 // r8 is used for indirect result location return 111 // we use it and r9 as scratch registers 112 REGISTER_DECLARATION(Register, rscratch1, r8); 113 REGISTER_DECLARATION(Register, rscratch2, r9); 114 115 // current method -- must be in a call-clobbered register 116 REGISTER_DECLARATION(Register, rmethod, r12); 117 118 // non-volatile (callee-save) registers are r16-29 119 // of which the following are dedicated global state 120 121 // link register 122 REGISTER_DECLARATION(Register, lr, r30); 123 // frame pointer 124 REGISTER_DECLARATION(Register, rfp, r29); 125 // current thread 126 REGISTER_DECLARATION(Register, rthread, r28); 127 // base of heap 128 REGISTER_DECLARATION(Register, rheapbase, r27); 129 // constant pool cache 130 REGISTER_DECLARATION(Register, rcpool, r26); 131 // monitors allocated on stack 132 REGISTER_DECLARATION(Register, rmonitors, r25); 133 // locals on stack 134 REGISTER_DECLARATION(Register, rlocals, r24); 135 // bytecode pointer 136 REGISTER_DECLARATION(Register, rbcp, r22); 137 // Dispatch table base 138 REGISTER_DECLARATION(Register, rdispatch, r21); 139 // Java stack pointer 140 REGISTER_DECLARATION(Register, esp, r20); 141 142 #define assert_cond(ARG1) assert(ARG1, #ARG1) 143 144 namespace asm_util { 145 uint32_t encode_logical_immediate(bool is32, uint64_t imm); 146 }; 147 148 using namespace asm_util; 149 150 151 class Assembler; 152 153 class Instruction_aarch64 { 154 unsigned insn; 155 #ifdef ASSERT 156 unsigned bits; 157 #endif 158 Assembler *assem; 159 160 public: 161 162 Instruction_aarch64(class Assembler *as) { 163 #ifdef ASSERT 164 bits = 0; 165 #endif 166 insn = 0; 167 assem = as; 168 } 169 170 inline ~Instruction_aarch64(); 171 172 unsigned &get_insn() { return insn; } 173 #ifdef ASSERT 174 unsigned &get_bits() { return bits; } 175 #endif 176 177 static inline int32_t extend(unsigned val, int hi = 31, int lo = 0) { 178 union { 179 unsigned u; 180 int n; 181 }; 182 183 u = val << (31 - hi); 184 n = n >> (31 - hi + lo); 185 return n; 186 } 187 188 static inline uint32_t extract(uint32_t val, int msb, int lsb) { 189 int nbits = msb - lsb + 1; 190 assert_cond(msb >= lsb); 191 uint32_t mask = (1U << nbits) - 1; 192 uint32_t result = val >> lsb; 193 result &= mask; 194 return result; 195 } 196 197 static inline int32_t sextract(uint32_t val, int msb, int lsb) { 198 uint32_t uval = extract(val, msb, lsb); 199 return extend(uval, msb - lsb); 200 } 201 202 static void patch(address a, int msb, int lsb, unsigned long val) { 203 int nbits = msb - lsb + 1; 204 guarantee(val < (1U << nbits), "Field too big for insn"); 205 assert_cond(msb >= lsb); 206 unsigned mask = (1U << nbits) - 1; 207 val <<= lsb; 208 mask <<= lsb; 209 unsigned target = *(unsigned *)a; 210 target &= ~mask; 211 target |= val; 212 *(unsigned *)a = target; 213 } 214 215 static void spatch(address a, int msb, int lsb, long val) { 216 int nbits = msb - lsb + 1; 217 long chk = val >> (nbits - 1); 218 guarantee (chk == -1 || chk == 0, "Field too big for insn"); 219 unsigned uval = val; 220 unsigned mask = (1U << nbits) - 1; 221 uval &= mask; 222 uval <<= lsb; 223 mask <<= lsb; 224 unsigned target = *(unsigned *)a; 225 target &= ~mask; 226 target |= uval; 227 *(unsigned *)a = target; 228 } 229 230 void f(unsigned val, int msb, int lsb) { 231 int nbits = msb - lsb + 1; 232 guarantee(val < (1U << nbits), "Field too big for insn"); 233 assert_cond(msb >= lsb); 234 unsigned mask = (1U << nbits) - 1; 235 val <<= lsb; 236 mask <<= lsb; 237 insn |= val; 238 assert_cond((bits & mask) == 0); 239 #ifdef ASSERT 240 bits |= mask; 241 #endif 242 } 243 244 void f(unsigned val, int bit) { 245 f(val, bit, bit); 246 } 247 248 void sf(long val, int msb, int lsb) { 249 int nbits = msb - lsb + 1; 250 long chk = val >> (nbits - 1); 251 guarantee (chk == -1 || chk == 0, "Field too big for insn"); 252 unsigned uval = val; 253 unsigned mask = (1U << nbits) - 1; 254 uval &= mask; 255 f(uval, lsb + nbits - 1, lsb); 256 } 257 258 void rf(Register r, int lsb) { 259 f(r->encoding_nocheck(), lsb + 4, lsb); 260 } 261 262 // reg|ZR 263 void zrf(Register r, int lsb) { 264 f(r->encoding_nocheck() - (r == zr), lsb + 4, lsb); 265 } 266 267 // reg|SP 268 void srf(Register r, int lsb) { 269 f(r == sp ? 31 : r->encoding_nocheck(), lsb + 4, lsb); 270 } 271 272 void rf(FloatRegister r, int lsb) { 273 f(r->encoding_nocheck(), lsb + 4, lsb); 274 } 275 276 unsigned get(int msb = 31, int lsb = 0) { 277 int nbits = msb - lsb + 1; 278 unsigned mask = ((1U << nbits) - 1) << lsb; 279 assert_cond(bits & mask == mask); 280 return (insn & mask) >> lsb; 281 } 282 283 void fixed(unsigned value, unsigned mask) { 284 assert_cond ((mask & bits) == 0); 285 #ifdef ASSERT 286 bits |= mask; 287 #endif 288 insn |= value; 289 } 290 }; 291 292 #define starti Instruction_aarch64 do_not_use(this); set_current(&do_not_use) 293 294 class PrePost { 295 int _offset; 296 Register _r; 297 public: 298 PrePost(Register reg, int o) : _r(reg), _offset(o) { } 299 int offset() { return _offset; } 300 Register reg() { return _r; } 301 }; 302 303 class Pre : public PrePost { 304 public: 305 Pre(Register reg, int o) : PrePost(reg, o) { } 306 }; 307 class Post : public PrePost { 308 public: 309 Post(Register reg, int o) : PrePost(reg, o) { } 310 }; 311 312 namespace ext 313 { 314 enum operation { uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx }; 315 }; 316 317 // abs methods which cannot overflow and so are well-defined across 318 // the entire domain of integer types. 319 static inline unsigned int uabs(unsigned int n) { 320 union { 321 unsigned int result; 322 int value; 323 }; 324 result = n; 325 if (value < 0) result = -result; 326 return result; 327 } 328 static inline unsigned long uabs(unsigned long n) { 329 union { 330 unsigned long result; 331 long value; 332 }; 333 result = n; 334 if (value < 0) result = -result; 335 return result; 336 } 337 static inline unsigned long uabs(long n) { return uabs((unsigned long)n); } 338 static inline unsigned long uabs(int n) { return uabs((unsigned int)n); } 339 340 // Addressing modes 341 class Address VALUE_OBJ_CLASS_SPEC { 342 public: 343 344 enum mode { no_mode, base_plus_offset, pre, post, pcrel, 345 base_plus_offset_reg, literal }; 346 347 // Shift and extend for base reg + reg offset addressing 348 class extend { 349 int _option, _shift; 350 ext::operation _op; 351 public: 352 extend() { } 353 extend(int s, int o, ext::operation op) : _shift(s), _option(o), _op(op) { } 354 int option() const{ return _option; } 355 int shift() const { return _shift; } 356 ext::operation op() const { return _op; } 357 }; 358 class uxtw : public extend { 359 public: 360 uxtw(int shift = -1): extend(shift, 0b010, ext::uxtw) { } 361 }; 362 class lsl : public extend { 363 public: 364 lsl(int shift = -1): extend(shift, 0b011, ext::uxtx) { } 365 }; 366 class sxtw : public extend { 367 public: 368 sxtw(int shift = -1): extend(shift, 0b110, ext::sxtw) { } 369 }; 370 class sxtx : public extend { 371 public: 372 sxtx(int shift = -1): extend(shift, 0b111, ext::sxtx) { } 373 }; 374 375 private: 376 Register _base; 377 Register _index; 378 long _offset; 379 enum mode _mode; 380 extend _ext; 381 382 RelocationHolder _rspec; 383 384 // Typically we use AddressLiterals we want to use their rval 385 // However in some situations we want the lval (effect address) of 386 // the item. We provide a special factory for making those lvals. 387 bool _is_lval; 388 389 // If the target is far we'll need to load the ea of this to a 390 // register to reach it. Otherwise if near we can do PC-relative 391 // addressing. 392 address _target; 393 394 public: 395 Address() 396 : _mode(no_mode) { } 397 Address(Register r) 398 : _mode(base_plus_offset), _base(r), _offset(0), _index(noreg), _target(0) { } 399 Address(Register r, int o) 400 : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { } 401 Address(Register r, long o) 402 : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { } 403 Address(Register r, unsigned long o) 404 : _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { } 405 #ifdef ASSERT 406 Address(Register r, ByteSize disp) 407 : _mode(base_plus_offset), _base(r), _offset(in_bytes(disp)), 408 _index(noreg), _target(0) { } 409 #endif 410 Address(Register r, Register r1, extend ext = lsl()) 411 : _mode(base_plus_offset_reg), _base(r), _index(r1), 412 _ext(ext), _offset(0), _target(0) { } 413 Address(Pre p) 414 : _mode(pre), _base(p.reg()), _offset(p.offset()) { } 415 Address(Post p) 416 : _mode(post), _base(p.reg()), _offset(p.offset()), _target(0) { } 417 Address(address target, RelocationHolder const& rspec) 418 : _mode(literal), 419 _rspec(rspec), 420 _is_lval(false), 421 _target(target) { } 422 Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type); 423 Address(Register base, RegisterOrConstant index, extend ext = lsl()) 424 : _base (base), 425 _ext(ext), _offset(0), _target(0) { 426 if (index.is_register()) { 427 _mode = base_plus_offset_reg; 428 _index = index.as_register(); 429 } else { 430 guarantee(ext.option() == ext::uxtx, "should be"); 431 assert(index.is_constant(), "should be"); 432 _mode = base_plus_offset; 433 _offset = index.as_constant() << ext.shift(); 434 } 435 } 436 437 Register base() const { 438 guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg 439 | _mode == post), 440 "wrong mode"); 441 return _base; 442 } 443 long offset() const { 444 return _offset; 445 } 446 Register index() const { 447 return _index; 448 } 449 mode getMode() const { 450 return _mode; 451 } 452 bool uses(Register reg) const { return _base == reg || _index == reg; } 453 address target() const { return _target; } 454 const RelocationHolder& rspec() const { return _rspec; } 455 456 void encode(Instruction_aarch64 *i) const { 457 i->f(0b111, 29, 27); 458 i->srf(_base, 5); 459 460 switch(_mode) { 461 case base_plus_offset: 462 { 463 unsigned size = i->get(31, 30); 464 if (i->get(26, 26) && i->get(23, 23)) { 465 // SIMD Q Type - Size = 128 bits 466 assert(size == 0, "bad size"); 467 size = 0b100; 468 } 469 unsigned mask = (1 << size) - 1; 470 if (_offset < 0 || _offset & mask) 471 { 472 i->f(0b00, 25, 24); 473 i->f(0, 21), i->f(0b00, 11, 10); 474 i->sf(_offset, 20, 12); 475 } else { 476 i->f(0b01, 25, 24); 477 i->f(_offset >> size, 21, 10); 478 } 479 } 480 break; 481 482 case base_plus_offset_reg: 483 { 484 i->f(0b00, 25, 24); 485 i->f(1, 21); 486 i->rf(_index, 16); 487 i->f(_ext.option(), 15, 13); 488 unsigned size = i->get(31, 30); 489 if (i->get(26, 26) && i->get(23, 23)) { 490 // SIMD Q Type - Size = 128 bits 491 assert(size == 0, "bad size"); 492 size = 0b100; 493 } 494 if (size == 0) // It's a byte 495 i->f(_ext.shift() >= 0, 12); 496 else { 497 if (_ext.shift() > 0) 498 assert(_ext.shift() == (int)size, "bad shift"); 499 i->f(_ext.shift() > 0, 12); 500 } 501 i->f(0b10, 11, 10); 502 } 503 break; 504 505 case pre: 506 i->f(0b00, 25, 24); 507 i->f(0, 21), i->f(0b11, 11, 10); 508 i->sf(_offset, 20, 12); 509 break; 510 511 case post: 512 i->f(0b00, 25, 24); 513 i->f(0, 21), i->f(0b01, 11, 10); 514 i->sf(_offset, 20, 12); 515 break; 516 517 default: 518 ShouldNotReachHere(); 519 } 520 } 521 522 void encode_pair(Instruction_aarch64 *i) const { 523 switch(_mode) { 524 case base_plus_offset: 525 i->f(0b010, 25, 23); 526 break; 527 case pre: 528 i->f(0b011, 25, 23); 529 break; 530 case post: 531 i->f(0b001, 25, 23); 532 break; 533 default: 534 ShouldNotReachHere(); 535 } 536 537 unsigned size; // Operand shift in 32-bit words 538 539 if (i->get(26, 26)) { // float 540 switch(i->get(31, 30)) { 541 case 0b10: 542 size = 2; break; 543 case 0b01: 544 size = 1; break; 545 case 0b00: 546 size = 0; break; 547 default: 548 ShouldNotReachHere(); 549 size = 0; // unreachable 550 } 551 } else { 552 size = i->get(31, 31); 553 } 554 555 size = 4 << size; 556 guarantee(_offset % size == 0, "bad offset"); 557 i->sf(_offset / size, 21, 15); 558 i->srf(_base, 5); 559 } 560 561 void encode_nontemporal_pair(Instruction_aarch64 *i) const { 562 // Only base + offset is allowed 563 i->f(0b000, 25, 23); 564 unsigned size = i->get(31, 31); 565 size = 4 << size; 566 guarantee(_offset % size == 0, "bad offset"); 567 i->sf(_offset / size, 21, 15); 568 i->srf(_base, 5); 569 guarantee(_mode == Address::base_plus_offset, 570 "Bad addressing mode for non-temporal op"); 571 } 572 573 void lea(MacroAssembler *, Register) const; 574 575 static bool offset_ok_for_immed(long offset, int shift = 0) { 576 unsigned mask = (1 << shift) - 1; 577 if (offset < 0 || offset & mask) { 578 return (uabs(offset) < (1 << (20 - 12))); // Unscaled offset 579 } else { 580 return ((offset >> shift) < (1 << (21 - 10 + 1))); // Scaled, unsigned offset 581 } 582 } 583 }; 584 585 // Convience classes 586 class RuntimeAddress: public Address { 587 588 public: 589 590 RuntimeAddress(address target) : Address(target, relocInfo::runtime_call_type) {} 591 592 }; 593 594 class OopAddress: public Address { 595 596 public: 597 598 OopAddress(address target) : Address(target, relocInfo::oop_type){} 599 600 }; 601 602 class ExternalAddress: public Address { 603 private: 604 static relocInfo::relocType reloc_for_target(address target) { 605 // Sometimes ExternalAddress is used for values which aren't 606 // exactly addresses, like the card table base. 607 // external_word_type can't be used for values in the first page 608 // so just skip the reloc in that case. 609 return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none; 610 } 611 612 public: 613 614 ExternalAddress(address target) : Address(target, reloc_for_target(target)) {} 615 616 }; 617 618 class InternalAddress: public Address { 619 620 public: 621 622 InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {} 623 }; 624 625 const int FPUStateSizeInWords = 32 * 2; 626 typedef enum { 627 PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM, 628 PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM, 629 PLIL1KEEP = 0b01000, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM 630 } prfop; 631 632 class Assembler : public AbstractAssembler { 633 634 #ifndef PRODUCT 635 static const unsigned long asm_bp; 636 637 void emit_long(jint x) { 638 if ((unsigned long)pc() == asm_bp) 639 asm volatile ("nop"); 640 AbstractAssembler::emit_int32(x); 641 } 642 #else 643 void emit_long(jint x) { 644 AbstractAssembler::emit_int32(x); 645 } 646 #endif 647 648 public: 649 650 enum { instruction_size = 4 }; 651 652 Address adjust(Register base, int offset, bool preIncrement) { 653 if (preIncrement) 654 return Address(Pre(base, offset)); 655 else 656 return Address(Post(base, offset)); 657 } 658 659 Address pre(Register base, int offset) { 660 return adjust(base, offset, true); 661 } 662 663 Address post (Register base, int offset) { 664 return adjust(base, offset, false); 665 } 666 667 Instruction_aarch64* current; 668 669 void set_current(Instruction_aarch64* i) { current = i; } 670 671 void f(unsigned val, int msb, int lsb) { 672 current->f(val, msb, lsb); 673 } 674 void f(unsigned val, int msb) { 675 current->f(val, msb, msb); 676 } 677 void sf(long val, int msb, int lsb) { 678 current->sf(val, msb, lsb); 679 } 680 void rf(Register reg, int lsb) { 681 current->rf(reg, lsb); 682 } 683 void srf(Register reg, int lsb) { 684 current->srf(reg, lsb); 685 } 686 void zrf(Register reg, int lsb) { 687 current->zrf(reg, lsb); 688 } 689 void rf(FloatRegister reg, int lsb) { 690 current->rf(reg, lsb); 691 } 692 void fixed(unsigned value, unsigned mask) { 693 current->fixed(value, mask); 694 } 695 696 void emit() { 697 emit_long(current->get_insn()); 698 assert_cond(current->get_bits() == 0xffffffff); 699 current = NULL; 700 } 701 702 typedef void (Assembler::* uncond_branch_insn)(address dest); 703 typedef void (Assembler::* compare_and_branch_insn)(Register Rt, address dest); 704 typedef void (Assembler::* test_and_branch_insn)(Register Rt, int bitpos, address dest); 705 typedef void (Assembler::* prefetch_insn)(address target, prfop); 706 707 void wrap_label(Label &L, uncond_branch_insn insn); 708 void wrap_label(Register r, Label &L, compare_and_branch_insn insn); 709 void wrap_label(Register r, int bitpos, Label &L, test_and_branch_insn insn); 710 void wrap_label(Label &L, prfop, prefetch_insn insn); 711 712 // PC-rel. addressing 713 714 void adr(Register Rd, address dest); 715 void _adrp(Register Rd, address dest); 716 717 void adr(Register Rd, const Address &dest); 718 void _adrp(Register Rd, const Address &dest); 719 720 void adr(Register Rd, Label &L) { 721 wrap_label(Rd, L, &Assembler::Assembler::adr); 722 } 723 void _adrp(Register Rd, Label &L) { 724 wrap_label(Rd, L, &Assembler::_adrp); 725 } 726 727 void adrp(Register Rd, const Address &dest, unsigned long &offset); 728 729 #undef INSN 730 731 void add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op, 732 int negated_op); 733 734 // Add/subtract (immediate) 735 #define INSN(NAME, decode, negated) \ 736 void NAME(Register Rd, Register Rn, unsigned imm, unsigned shift) { \ 737 starti; \ 738 f(decode, 31, 29), f(0b10001, 28, 24), f(shift, 23, 22), f(imm, 21, 10); \ 739 zrf(Rd, 0), srf(Rn, 5); \ 740 } \ 741 \ 742 void NAME(Register Rd, Register Rn, unsigned imm) { \ 743 starti; \ 744 add_sub_immediate(Rd, Rn, imm, decode, negated); \ 745 } 746 747 INSN(addsw, 0b001, 0b011); 748 INSN(subsw, 0b011, 0b001); 749 INSN(adds, 0b101, 0b111); 750 INSN(subs, 0b111, 0b101); 751 752 #undef INSN 753 754 #define INSN(NAME, decode, negated) \ 755 void NAME(Register Rd, Register Rn, unsigned imm) { \ 756 starti; \ 757 add_sub_immediate(Rd, Rn, imm, decode, negated); \ 758 } 759 760 INSN(addw, 0b000, 0b010); 761 INSN(subw, 0b010, 0b000); 762 INSN(add, 0b100, 0b110); 763 INSN(sub, 0b110, 0b100); 764 765 #undef INSN 766 767 // Logical (immediate) 768 #define INSN(NAME, decode, is32) \ 769 void NAME(Register Rd, Register Rn, uint64_t imm) { \ 770 starti; \ 771 uint32_t val = encode_logical_immediate(is32, imm); \ 772 f(decode, 31, 29), f(0b100100, 28, 23), f(val, 22, 10); \ 773 srf(Rd, 0), zrf(Rn, 5); \ 774 } 775 776 INSN(andw, 0b000, true); 777 INSN(orrw, 0b001, true); 778 INSN(eorw, 0b010, true); 779 INSN(andr, 0b100, false); 780 INSN(orr, 0b101, false); 781 INSN(eor, 0b110, false); 782 783 #undef INSN 784 785 #define INSN(NAME, decode, is32) \ 786 void NAME(Register Rd, Register Rn, uint64_t imm) { \ 787 starti; \ 788 uint32_t val = encode_logical_immediate(is32, imm); \ 789 f(decode, 31, 29), f(0b100100, 28, 23), f(val, 22, 10); \ 790 zrf(Rd, 0), zrf(Rn, 5); \ 791 } 792 793 INSN(ands, 0b111, false); 794 INSN(andsw, 0b011, true); 795 796 #undef INSN 797 798 // Move wide (immediate) 799 #define INSN(NAME, opcode) \ 800 void NAME(Register Rd, unsigned imm, unsigned shift = 0) { \ 801 assert_cond((shift/16)*16 == shift); \ 802 starti; \ 803 f(opcode, 31, 29), f(0b100101, 28, 23), f(shift/16, 22, 21), \ 804 f(imm, 20, 5); \ 805 rf(Rd, 0); \ 806 } 807 808 INSN(movnw, 0b000); 809 INSN(movzw, 0b010); 810 INSN(movkw, 0b011); 811 INSN(movn, 0b100); 812 INSN(movz, 0b110); 813 INSN(movk, 0b111); 814 815 #undef INSN 816 817 // Bitfield 818 #define INSN(NAME, opcode) \ 819 void NAME(Register Rd, Register Rn, unsigned immr, unsigned imms) { \ 820 starti; \ 821 f(opcode, 31, 22), f(immr, 21, 16), f(imms, 15, 10); \ 822 rf(Rn, 5), rf(Rd, 0); \ 823 } 824 825 INSN(sbfmw, 0b0001001100); 826 INSN(bfmw, 0b0011001100); 827 INSN(ubfmw, 0b0101001100); 828 INSN(sbfm, 0b1001001101); 829 INSN(bfm, 0b1011001101); 830 INSN(ubfm, 0b1101001101); 831 832 #undef INSN 833 834 // Extract 835 #define INSN(NAME, opcode) \ 836 void NAME(Register Rd, Register Rn, Register Rm, unsigned imms) { \ 837 starti; \ 838 f(opcode, 31, 21), f(imms, 15, 10); \ 839 rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ 840 } 841 842 INSN(extrw, 0b00010011100); 843 INSN(extr, 0b10010011110); 844 845 #undef INSN 846 847 // The maximum range of a branch is fixed for the AArch64 848 // architecture. In debug mode we shrink it in order to test 849 // trampolines, but not so small that branches in the interpreter 850 // are out of range. 851 static const unsigned long branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); 852 853 static bool reachable_from_branch_at(address branch, address target) { 854 return uabs(target - branch) < branch_range; 855 } 856 857 // Unconditional branch (immediate) 858 #define INSN(NAME, opcode) \ 859 void NAME(address dest) { \ 860 starti; \ 861 long offset = (dest - pc()) >> 2; \ 862 DEBUG_ONLY(assert(reachable_from_branch_at(pc(), dest), "debug only")); \ 863 f(opcode, 31), f(0b00101, 30, 26), sf(offset, 25, 0); \ 864 } \ 865 void NAME(Label &L) { \ 866 wrap_label(L, &Assembler::NAME); \ 867 } \ 868 void NAME(const Address &dest); 869 870 INSN(b, 0); 871 INSN(bl, 1); 872 873 #undef INSN 874 875 // Compare & branch (immediate) 876 #define INSN(NAME, opcode) \ 877 void NAME(Register Rt, address dest) { \ 878 long offset = (dest - pc()) >> 2; \ 879 starti; \ 880 f(opcode, 31, 24), sf(offset, 23, 5), rf(Rt, 0); \ 881 } \ 882 void NAME(Register Rt, Label &L) { \ 883 wrap_label(Rt, L, &Assembler::NAME); \ 884 } 885 886 INSN(cbzw, 0b00110100); 887 INSN(cbnzw, 0b00110101); 888 INSN(cbz, 0b10110100); 889 INSN(cbnz, 0b10110101); 890 891 #undef INSN 892 893 // Test & branch (immediate) 894 #define INSN(NAME, opcode) \ 895 void NAME(Register Rt, int bitpos, address dest) { \ 896 long offset = (dest - pc()) >> 2; \ 897 int b5 = bitpos >> 5; \ 898 bitpos &= 0x1f; \ 899 starti; \ 900 f(b5, 31), f(opcode, 30, 24), f(bitpos, 23, 19), sf(offset, 18, 5); \ 901 rf(Rt, 0); \ 902 } \ 903 void NAME(Register Rt, int bitpos, Label &L) { \ 904 wrap_label(Rt, bitpos, L, &Assembler::NAME); \ 905 } 906 907 INSN(tbz, 0b0110110); 908 INSN(tbnz, 0b0110111); 909 910 #undef INSN 911 912 // Conditional branch (immediate) 913 enum Condition 914 {EQ, NE, HS, CS=HS, LO, CC=LO, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV}; 915 916 void br(Condition cond, address dest) { 917 long offset = (dest - pc()) >> 2; 918 starti; 919 f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0); 920 } 921 922 #define INSN(NAME, cond) \ 923 void NAME(address dest) { \ 924 br(cond, dest); \ 925 } 926 927 INSN(beq, EQ); 928 INSN(bne, NE); 929 INSN(bhs, HS); 930 INSN(bcs, CS); 931 INSN(blo, LO); 932 INSN(bcc, CC); 933 INSN(bmi, MI); 934 INSN(bpl, PL); 935 INSN(bvs, VS); 936 INSN(bvc, VC); 937 INSN(bhi, HI); 938 INSN(bls, LS); 939 INSN(bge, GE); 940 INSN(blt, LT); 941 INSN(bgt, GT); 942 INSN(ble, LE); 943 INSN(bal, AL); 944 INSN(bnv, NV); 945 946 void br(Condition cc, Label &L); 947 948 #undef INSN 949 950 // Exception generation 951 void generate_exception(int opc, int op2, int LL, unsigned imm) { 952 starti; 953 f(0b11010100, 31, 24); 954 f(opc, 23, 21), f(imm, 20, 5), f(op2, 4, 2), f(LL, 1, 0); 955 } 956 957 #define INSN(NAME, opc, op2, LL) \ 958 void NAME(unsigned imm) { \ 959 generate_exception(opc, op2, LL, imm); \ 960 } 961 962 INSN(svc, 0b000, 0, 0b01); 963 INSN(hvc, 0b000, 0, 0b10); 964 INSN(smc, 0b000, 0, 0b11); 965 INSN(brk, 0b001, 0, 0b00); 966 INSN(hlt, 0b010, 0, 0b00); 967 INSN(dpcs1, 0b101, 0, 0b01); 968 INSN(dpcs2, 0b101, 0, 0b10); 969 INSN(dpcs3, 0b101, 0, 0b11); 970 971 #undef INSN 972 973 // System 974 void system(int op0, int op1, int CRn, int CRm, int op2, 975 Register rt = (Register)0b11111) 976 { 977 starti; 978 f(0b11010101000, 31, 21); 979 f(op0, 20, 19); 980 f(op1, 18, 16); 981 f(CRn, 15, 12); 982 f(CRm, 11, 8); 983 f(op2, 7, 5); 984 rf(rt, 0); 985 } 986 987 void hint(int imm) { 988 system(0b00, 0b011, 0b0010, imm, 0b000); 989 } 990 991 void nop() { 992 hint(0); 993 } 994 // we only provide mrs and msr for the special purpose system 995 // registers where op1 (instr[20:19]) == 11 and, (currently) only 996 // use it for FPSR n.b msr has L (instr[21]) == 0 mrs has L == 1 997 998 void msr(int op1, int CRn, int CRm, int op2, Register rt) { 999 starti; 1000 f(0b1101010100011, 31, 19); 1001 f(op1, 18, 16); 1002 f(CRn, 15, 12); 1003 f(CRm, 11, 8); 1004 f(op2, 7, 5); 1005 // writing zr is ok 1006 zrf(rt, 0); 1007 } 1008 1009 void mrs(int op1, int CRn, int CRm, int op2, Register rt) { 1010 starti; 1011 f(0b1101010100111, 31, 19); 1012 f(op1, 18, 16); 1013 f(CRn, 15, 12); 1014 f(CRm, 11, 8); 1015 f(op2, 7, 5); 1016 // reading to zr is a mistake 1017 rf(rt, 0); 1018 } 1019 1020 enum barrier {OSHLD = 0b0001, OSHST, OSH, NSHLD=0b0101, NSHST, NSH, 1021 ISHLD = 0b1001, ISHST, ISH, LD=0b1101, ST, SY}; 1022 1023 void dsb(barrier imm) { 1024 system(0b00, 0b011, 0b00011, imm, 0b100); 1025 } 1026 1027 void dmb(barrier imm) { 1028 system(0b00, 0b011, 0b00011, imm, 0b101); 1029 } 1030 1031 void isb() { 1032 system(0b00, 0b011, 0b00011, SY, 0b110); 1033 } 1034 1035 void dc(Register Rt) { 1036 system(0b01, 0b011, 0b0111, 0b1011, 0b001, Rt); 1037 } 1038 1039 void ic(Register Rt) { 1040 system(0b01, 0b011, 0b0111, 0b0101, 0b001, Rt); 1041 } 1042 1043 // A more convenient access to dmb for our purposes 1044 enum Membar_mask_bits { 1045 // We can use ISH for a barrier because the ARM ARM says "This 1046 // architecture assumes that all Processing Elements that use the 1047 // same operating system or hypervisor are in the same Inner 1048 // Shareable shareability domain." 1049 StoreStore = ISHST, 1050 LoadStore = ISHLD, 1051 LoadLoad = ISHLD, 1052 StoreLoad = ISH, 1053 AnyAny = ISH 1054 }; 1055 1056 void membar(Membar_mask_bits order_constraint) { 1057 dmb(Assembler::barrier(order_constraint)); 1058 } 1059 1060 // Unconditional branch (register) 1061 void branch_reg(Register R, int opc) { 1062 starti; 1063 f(0b1101011, 31, 25); 1064 f(opc, 24, 21); 1065 f(0b11111000000, 20, 10); 1066 rf(R, 5); 1067 f(0b00000, 4, 0); 1068 } 1069 1070 #define INSN(NAME, opc) \ 1071 void NAME(Register R) { \ 1072 branch_reg(R, opc); \ 1073 } 1074 1075 INSN(br, 0b0000); 1076 INSN(blr, 0b0001); 1077 INSN(ret, 0b0010); 1078 1079 void ret(void *p); // This forces a compile-time error for ret(0) 1080 1081 #undef INSN 1082 1083 #define INSN(NAME, opc) \ 1084 void NAME() { \ 1085 branch_reg((Register)0b11111, opc); \ 1086 } 1087 1088 INSN(eret, 0b0100); 1089 INSN(drps, 0b0101); 1090 1091 #undef INSN 1092 1093 // Load/store exclusive 1094 enum operand_size { byte, halfword, word, xword }; 1095 1096 void load_store_exclusive(Register Rs, Register Rt1, Register Rt2, 1097 Register Rn, enum operand_size sz, int op, int o0) { 1098 starti; 1099 f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21); 1100 rf(Rs, 16), f(o0, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0); 1101 } 1102 1103 #define INSN4(NAME, sz, op, o0) /* Four registers */ \ 1104 void NAME(Register Rs, Register Rt1, Register Rt2, Register Rn) { \ 1105 guarantee(Rs != Rn && Rs != Rt1 && Rs != Rt2, "unpredictable instruction"); \ 1106 load_store_exclusive(Rs, Rt1, Rt2, Rn, sz, op, o0); \ 1107 } 1108 1109 #define INSN3(NAME, sz, op, o0) /* Three registers */ \ 1110 void NAME(Register Rs, Register Rt, Register Rn) { \ 1111 guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ 1112 load_store_exclusive(Rs, Rt, (Register)0b11111, Rn, sz, op, o0); \ 1113 } 1114 1115 #define INSN2(NAME, sz, op, o0) /* Two registers */ \ 1116 void NAME(Register Rt, Register Rn) { \ 1117 load_store_exclusive((Register)0b11111, Rt, (Register)0b11111, \ 1118 Rn, sz, op, o0); \ 1119 } 1120 1121 #define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \ 1122 void NAME(Register Rt1, Register Rt2, Register Rn) { \ 1123 guarantee(Rt1 != Rt2, "unpredictable instruction"); \ 1124 load_store_exclusive((Register)0b11111, Rt1, Rt2, Rn, sz, op, o0); \ 1125 } 1126 1127 // bytes 1128 INSN3(stxrb, byte, 0b000, 0); 1129 INSN3(stlxrb, byte, 0b000, 1); 1130 INSN2(ldxrb, byte, 0b010, 0); 1131 INSN2(ldaxrb, byte, 0b010, 1); 1132 INSN2(stlrb, byte, 0b100, 1); 1133 INSN2(ldarb, byte, 0b110, 1); 1134 1135 // halfwords 1136 INSN3(stxrh, halfword, 0b000, 0); 1137 INSN3(stlxrh, halfword, 0b000, 1); 1138 INSN2(ldxrh, halfword, 0b010, 0); 1139 INSN2(ldaxrh, halfword, 0b010, 1); 1140 INSN2(stlrh, halfword, 0b100, 1); 1141 INSN2(ldarh, halfword, 0b110, 1); 1142 1143 // words 1144 INSN3(stxrw, word, 0b000, 0); 1145 INSN3(stlxrw, word, 0b000, 1); 1146 INSN4(stxpw, word, 0b001, 0); 1147 INSN4(stlxpw, word, 0b001, 1); 1148 INSN2(ldxrw, word, 0b010, 0); 1149 INSN2(ldaxrw, word, 0b010, 1); 1150 INSN_FOO(ldxpw, word, 0b011, 0); 1151 INSN_FOO(ldaxpw, word, 0b011, 1); 1152 INSN2(stlrw, word, 0b100, 1); 1153 INSN2(ldarw, word, 0b110, 1); 1154 1155 // xwords 1156 INSN3(stxr, xword, 0b000, 0); 1157 INSN3(stlxr, xword, 0b000, 1); 1158 INSN4(stxp, xword, 0b001, 0); 1159 INSN4(stlxp, xword, 0b001, 1); 1160 INSN2(ldxr, xword, 0b010, 0); 1161 INSN2(ldaxr, xword, 0b010, 1); 1162 INSN_FOO(ldxp, xword, 0b011, 0); 1163 INSN_FOO(ldaxp, xword, 0b011, 1); 1164 INSN2(stlr, xword, 0b100, 1); 1165 INSN2(ldar, xword, 0b110, 1); 1166 1167 #undef INSN2 1168 #undef INSN3 1169 #undef INSN4 1170 #undef INSN_FOO 1171 1172 // 8.1 Compare and swap extensions 1173 void compare_and_swap(Register Rs, Register Rt, Register Rn, 1174 enum operand_size sz, int op, int a, int r) { 1175 starti; 1176 f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21); 1177 rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0); 1178 } 1179 1180 // CAS 1181 #define INSN(NAME, sz, a, r) \ 1182 void NAME(Register Rs, Register Rt, Register Rn) { \ 1183 assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ 1184 compare_and_swap(Rs, Rt, Rn, sz, 1, a, r); \ 1185 } 1186 INSN(casb, byte, 0, 0) 1187 INSN(cash, halfword, 0, 0) 1188 INSN(casw, word, 0, 0) 1189 INSN(cas, xword, 0, 0) 1190 INSN(casab, byte, 1, 0) 1191 INSN(casah, halfword, 1, 0) 1192 INSN(casaw, word, 1, 0) 1193 INSN(casa, xword, 1, 0) 1194 INSN(caslb, byte, 0, 1) 1195 INSN(caslh, halfword, 0, 1) 1196 INSN(caslw, word, 0, 1) 1197 INSN(casl, xword, 0, 1) 1198 INSN(casalb, byte, 1, 1) 1199 INSN(casalh, halfword, 1, 1) 1200 INSN(casalw, word, 1, 1) 1201 INSN(casal, xword, 1, 1) 1202 #undef INSN 1203 1204 // CASP 1205 #define INSN(NAME, sz, a, r) \ 1206 void NAME(Register Rs, Register Rs1, \ 1207 Register Rt, Register Rt1, Register Rn) { \ 1208 assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \ 1209 Rs->successor() == Rs1 && Rt->successor() == Rt1 && \ 1210 Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \ 1211 assert(sz == word || sz == xword, "invalid size"); \ 1212 /* The size bit is in bit 30, not 31 as in ldx/stx above */ \ 1213 compare_and_swap(Rs, Rt, Rn, \ 1214 (operand_size)(sz == word ? 0b00:0b01), 0, a, r); \ 1215 } 1216 INSN(caspw, word, 0, 0) 1217 INSN(casp, xword, 0, 0) 1218 INSN(caspaw, word, 1, 0) 1219 INSN(caspa, xword, 1, 0) 1220 INSN(casplw, word, 0, 1) 1221 INSN(caspl, xword, 0, 1) 1222 INSN(caspalw, word, 1, 1) 1223 INSN(caspal, xword, 1, 1) 1224 #undef INSN 1225 1226 // Load register (literal) 1227 #define INSN(NAME, opc, V) \ 1228 void NAME(Register Rt, address dest) { \ 1229 long offset = (dest - pc()) >> 2; \ 1230 starti; \ 1231 f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ 1232 sf(offset, 23, 5); \ 1233 rf(Rt, 0); \ 1234 } \ 1235 void NAME(Register Rt, address dest, relocInfo::relocType rtype) { \ 1236 InstructionMark im(this); \ 1237 guarantee(rtype == relocInfo::internal_word_type, \ 1238 "only internal_word_type relocs make sense here"); \ 1239 code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); \ 1240 NAME(Rt, dest); \ 1241 } \ 1242 void NAME(Register Rt, Label &L) { \ 1243 wrap_label(Rt, L, &Assembler::NAME); \ 1244 } 1245 1246 INSN(ldrw, 0b00, 0); 1247 INSN(ldr, 0b01, 0); 1248 INSN(ldrsw, 0b10, 0); 1249 1250 #undef INSN 1251 1252 #define INSN(NAME, opc, V) \ 1253 void NAME(FloatRegister Rt, address dest) { \ 1254 long offset = (dest - pc()) >> 2; \ 1255 starti; \ 1256 f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ 1257 sf(offset, 23, 5); \ 1258 rf((Register)Rt, 0); \ 1259 } 1260 1261 INSN(ldrs, 0b00, 1); 1262 INSN(ldrd, 0b01, 1); 1263 INSN(ldrq, 0b10, 1); 1264 1265 #undef INSN 1266 1267 #define INSN(NAME, opc, V) \ 1268 void NAME(address dest, prfop op = PLDL1KEEP) { \ 1269 long offset = (dest - pc()) >> 2; \ 1270 starti; \ 1271 f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ 1272 sf(offset, 23, 5); \ 1273 f(op, 4, 0); \ 1274 } \ 1275 void NAME(Label &L, prfop op = PLDL1KEEP) { \ 1276 wrap_label(L, op, &Assembler::NAME); \ 1277 } 1278 1279 INSN(prfm, 0b11, 0); 1280 1281 #undef INSN 1282 1283 // Load/store 1284 void ld_st1(int opc, int p1, int V, int L, 1285 Register Rt1, Register Rt2, Address adr, bool no_allocate) { 1286 starti; 1287 f(opc, 31, 30), f(p1, 29, 27), f(V, 26), f(L, 22); 1288 zrf(Rt2, 10), zrf(Rt1, 0); 1289 if (no_allocate) { 1290 adr.encode_nontemporal_pair(current); 1291 } else { 1292 adr.encode_pair(current); 1293 } 1294 } 1295 1296 // Load/store register pair (offset) 1297 #define INSN(NAME, size, p1, V, L, no_allocate) \ 1298 void NAME(Register Rt1, Register Rt2, Address adr) { \ 1299 ld_st1(size, p1, V, L, Rt1, Rt2, adr, no_allocate); \ 1300 } 1301 1302 INSN(stpw, 0b00, 0b101, 0, 0, false); 1303 INSN(ldpw, 0b00, 0b101, 0, 1, false); 1304 INSN(ldpsw, 0b01, 0b101, 0, 1, false); 1305 INSN(stp, 0b10, 0b101, 0, 0, false); 1306 INSN(ldp, 0b10, 0b101, 0, 1, false); 1307 1308 // Load/store no-allocate pair (offset) 1309 INSN(stnpw, 0b00, 0b101, 0, 0, true); 1310 INSN(ldnpw, 0b00, 0b101, 0, 1, true); 1311 INSN(stnp, 0b10, 0b101, 0, 0, true); 1312 INSN(ldnp, 0b10, 0b101, 0, 1, true); 1313 1314 #undef INSN 1315 1316 #define INSN(NAME, size, p1, V, L, no_allocate) \ 1317 void NAME(FloatRegister Rt1, FloatRegister Rt2, Address adr) { \ 1318 ld_st1(size, p1, V, L, (Register)Rt1, (Register)Rt2, adr, no_allocate); \ 1319 } 1320 1321 INSN(stps, 0b00, 0b101, 1, 0, false); 1322 INSN(ldps, 0b00, 0b101, 1, 1, false); 1323 INSN(stpd, 0b01, 0b101, 1, 0, false); 1324 INSN(ldpd, 0b01, 0b101, 1, 1, false); 1325 INSN(stpq, 0b10, 0b101, 1, 0, false); 1326 INSN(ldpq, 0b10, 0b101, 1, 1, false); 1327 1328 #undef INSN 1329 1330 // Load/store register (all modes) 1331 void ld_st2(Register Rt, const Address &adr, int size, int op, int V = 0) { 1332 starti; 1333 1334 f(V, 26); // general reg? 1335 zrf(Rt, 0); 1336 1337 // Encoding for literal loads is done here (rather than pushed 1338 // down into Address::encode) because the encoding of this 1339 // instruction is too different from all of the other forms to 1340 // make it worth sharing. 1341 if (adr.getMode() == Address::literal) { 1342 assert(size == 0b10 || size == 0b11, "bad operand size in ldr"); 1343 assert(op == 0b01, "literal form can only be used with loads"); 1344 f(size & 0b01, 31, 30), f(0b011, 29, 27), f(0b00, 25, 24); 1345 long offset = (adr.target() - pc()) >> 2; 1346 sf(offset, 23, 5); 1347 code_section()->relocate(pc(), adr.rspec()); 1348 return; 1349 } 1350 1351 f(size, 31, 30); 1352 f(op, 23, 22); // str 1353 adr.encode(current); 1354 } 1355 1356 #define INSN(NAME, size, op) \ 1357 void NAME(Register Rt, const Address &adr) { \ 1358 ld_st2(Rt, adr, size, op); \ 1359 } \ 1360 1361 INSN(str, 0b11, 0b00); 1362 INSN(strw, 0b10, 0b00); 1363 INSN(strb, 0b00, 0b00); 1364 INSN(strh, 0b01, 0b00); 1365 1366 INSN(ldr, 0b11, 0b01); 1367 INSN(ldrw, 0b10, 0b01); 1368 INSN(ldrb, 0b00, 0b01); 1369 INSN(ldrh, 0b01, 0b01); 1370 1371 INSN(ldrsb, 0b00, 0b10); 1372 INSN(ldrsbw, 0b00, 0b11); 1373 INSN(ldrsh, 0b01, 0b10); 1374 INSN(ldrshw, 0b01, 0b11); 1375 INSN(ldrsw, 0b10, 0b10); 1376 1377 #undef INSN 1378 1379 #define INSN(NAME, size, op) \ 1380 void NAME(const Address &adr, prfop pfop = PLDL1KEEP) { \ 1381 ld_st2((Register)pfop, adr, size, op); \ 1382 } 1383 1384 INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with 1385 // writeback modes, but the assembler 1386 // doesn't enfore that. 1387 1388 #undef INSN 1389 1390 #define INSN(NAME, size, op) \ 1391 void NAME(FloatRegister Rt, const Address &adr) { \ 1392 ld_st2((Register)Rt, adr, size, op, 1); \ 1393 } 1394 1395 INSN(strd, 0b11, 0b00); 1396 INSN(strs, 0b10, 0b00); 1397 INSN(ldrd, 0b11, 0b01); 1398 INSN(ldrs, 0b10, 0b01); 1399 INSN(strq, 0b00, 0b10); 1400 INSN(ldrq, 0x00, 0b11); 1401 1402 #undef INSN 1403 1404 enum shift_kind { LSL, LSR, ASR, ROR }; 1405 1406 void op_shifted_reg(unsigned decode, 1407 enum shift_kind kind, unsigned shift, 1408 unsigned size, unsigned op) { 1409 f(size, 31); 1410 f(op, 30, 29); 1411 f(decode, 28, 24); 1412 f(shift, 15, 10); 1413 f(kind, 23, 22); 1414 } 1415 1416 // Logical (shifted register) 1417 #define INSN(NAME, size, op, N) \ 1418 void NAME(Register Rd, Register Rn, Register Rm, \ 1419 enum shift_kind kind = LSL, unsigned shift = 0) { \ 1420 starti; \ 1421 f(N, 21); \ 1422 zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \ 1423 op_shifted_reg(0b01010, kind, shift, size, op); \ 1424 } 1425 1426 INSN(andr, 1, 0b00, 0); 1427 INSN(orr, 1, 0b01, 0); 1428 INSN(eor, 1, 0b10, 0); 1429 INSN(ands, 1, 0b11, 0); 1430 INSN(andw, 0, 0b00, 0); 1431 INSN(orrw, 0, 0b01, 0); 1432 INSN(eorw, 0, 0b10, 0); 1433 INSN(andsw, 0, 0b11, 0); 1434 1435 INSN(bic, 1, 0b00, 1); 1436 INSN(orn, 1, 0b01, 1); 1437 INSN(eon, 1, 0b10, 1); 1438 INSN(bics, 1, 0b11, 1); 1439 INSN(bicw, 0, 0b00, 1); 1440 INSN(ornw, 0, 0b01, 1); 1441 INSN(eonw, 0, 0b10, 1); 1442 INSN(bicsw, 0, 0b11, 1); 1443 1444 #undef INSN 1445 1446 // Add/subtract (shifted register) 1447 #define INSN(NAME, size, op) \ 1448 void NAME(Register Rd, Register Rn, Register Rm, \ 1449 enum shift_kind kind, unsigned shift = 0) { \ 1450 starti; \ 1451 f(0, 21); \ 1452 assert_cond(kind != ROR); \ 1453 zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16); \ 1454 op_shifted_reg(0b01011, kind, shift, size, op); \ 1455 } 1456 1457 INSN(add, 1, 0b000); 1458 INSN(sub, 1, 0b10); 1459 INSN(addw, 0, 0b000); 1460 INSN(subw, 0, 0b10); 1461 1462 INSN(adds, 1, 0b001); 1463 INSN(subs, 1, 0b11); 1464 INSN(addsw, 0, 0b001); 1465 INSN(subsw, 0, 0b11); 1466 1467 #undef INSN 1468 1469 // Add/subtract (extended register) 1470 #define INSN(NAME, op) \ 1471 void NAME(Register Rd, Register Rn, Register Rm, \ 1472 ext::operation option, int amount = 0) { \ 1473 starti; \ 1474 zrf(Rm, 16), srf(Rn, 5), srf(Rd, 0); \ 1475 add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \ 1476 } 1477 1478 void add_sub_extended_reg(unsigned op, unsigned decode, 1479 Register Rd, Register Rn, Register Rm, 1480 unsigned opt, ext::operation option, unsigned imm) { 1481 guarantee(imm <= 4, "shift amount must be < 4"); 1482 f(op, 31, 29), f(decode, 28, 24), f(opt, 23, 22), f(1, 21); 1483 f(option, 15, 13), f(imm, 12, 10); 1484 } 1485 1486 INSN(addw, 0b000); 1487 INSN(subw, 0b010); 1488 INSN(add, 0b100); 1489 INSN(sub, 0b110); 1490 1491 #undef INSN 1492 1493 #define INSN(NAME, op) \ 1494 void NAME(Register Rd, Register Rn, Register Rm, \ 1495 ext::operation option, int amount = 0) { \ 1496 starti; \ 1497 zrf(Rm, 16), srf(Rn, 5), zrf(Rd, 0); \ 1498 add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \ 1499 } 1500 1501 INSN(addsw, 0b001); 1502 INSN(subsw, 0b011); 1503 INSN(adds, 0b101); 1504 INSN(subs, 0b111); 1505 1506 #undef INSN 1507 1508 // Aliases for short forms of add and sub 1509 #define INSN(NAME) \ 1510 void NAME(Register Rd, Register Rn, Register Rm) { \ 1511 if (Rd == sp || Rn == sp) \ 1512 NAME(Rd, Rn, Rm, ext::uxtx); \ 1513 else \ 1514 NAME(Rd, Rn, Rm, LSL); \ 1515 } 1516 1517 INSN(addw); 1518 INSN(subw); 1519 INSN(add); 1520 INSN(sub); 1521 1522 INSN(addsw); 1523 INSN(subsw); 1524 INSN(adds); 1525 INSN(subs); 1526 1527 #undef INSN 1528 1529 // Add/subtract (with carry) 1530 void add_sub_carry(unsigned op, Register Rd, Register Rn, Register Rm) { 1531 starti; 1532 f(op, 31, 29); 1533 f(0b11010000, 28, 21); 1534 f(0b000000, 15, 10); 1535 zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); 1536 } 1537 1538 #define INSN(NAME, op) \ 1539 void NAME(Register Rd, Register Rn, Register Rm) { \ 1540 add_sub_carry(op, Rd, Rn, Rm); \ 1541 } 1542 1543 INSN(adcw, 0b000); 1544 INSN(adcsw, 0b001); 1545 INSN(sbcw, 0b010); 1546 INSN(sbcsw, 0b011); 1547 INSN(adc, 0b100); 1548 INSN(adcs, 0b101); 1549 INSN(sbc,0b110); 1550 INSN(sbcs, 0b111); 1551 1552 #undef INSN 1553 1554 // Conditional compare (both kinds) 1555 void conditional_compare(unsigned op, int o2, int o3, 1556 Register Rn, unsigned imm5, unsigned nzcv, 1557 unsigned cond) { 1558 f(op, 31, 29); 1559 f(0b11010010, 28, 21); 1560 f(cond, 15, 12); 1561 f(o2, 10); 1562 f(o3, 4); 1563 f(nzcv, 3, 0); 1564 f(imm5, 20, 16), rf(Rn, 5); 1565 } 1566 1567 #define INSN(NAME, op) \ 1568 void NAME(Register Rn, Register Rm, int imm, Condition cond) { \ 1569 starti; \ 1570 f(0, 11); \ 1571 conditional_compare(op, 0, 0, Rn, (uintptr_t)Rm, imm, cond); \ 1572 } \ 1573 \ 1574 void NAME(Register Rn, int imm5, int imm, Condition cond) { \ 1575 starti; \ 1576 f(1, 11); \ 1577 conditional_compare(op, 0, 0, Rn, imm5, imm, cond); \ 1578 } 1579 1580 INSN(ccmnw, 0b001); 1581 INSN(ccmpw, 0b011); 1582 INSN(ccmn, 0b101); 1583 INSN(ccmp, 0b111); 1584 1585 #undef INSN 1586 1587 // Conditional select 1588 void conditional_select(unsigned op, unsigned op2, 1589 Register Rd, Register Rn, Register Rm, 1590 unsigned cond) { 1591 starti; 1592 f(op, 31, 29); 1593 f(0b11010100, 28, 21); 1594 f(cond, 15, 12); 1595 f(op2, 11, 10); 1596 zrf(Rm, 16), zrf(Rn, 5), rf(Rd, 0); 1597 } 1598 1599 #define INSN(NAME, op, op2) \ 1600 void NAME(Register Rd, Register Rn, Register Rm, Condition cond) { \ 1601 conditional_select(op, op2, Rd, Rn, Rm, cond); \ 1602 } 1603 1604 INSN(cselw, 0b000, 0b00); 1605 INSN(csincw, 0b000, 0b01); 1606 INSN(csinvw, 0b010, 0b00); 1607 INSN(csnegw, 0b010, 0b01); 1608 INSN(csel, 0b100, 0b00); 1609 INSN(csinc, 0b100, 0b01); 1610 INSN(csinv, 0b110, 0b00); 1611 INSN(csneg, 0b110, 0b01); 1612 1613 #undef INSN 1614 1615 // Data processing 1616 void data_processing(unsigned op29, unsigned opcode, 1617 Register Rd, Register Rn) { 1618 f(op29, 31, 29), f(0b11010110, 28, 21); 1619 f(opcode, 15, 10); 1620 rf(Rn, 5), rf(Rd, 0); 1621 } 1622 1623 // (1 source) 1624 #define INSN(NAME, op29, opcode2, opcode) \ 1625 void NAME(Register Rd, Register Rn) { \ 1626 starti; \ 1627 f(opcode2, 20, 16); \ 1628 data_processing(op29, opcode, Rd, Rn); \ 1629 } 1630 1631 INSN(rbitw, 0b010, 0b00000, 0b00000); 1632 INSN(rev16w, 0b010, 0b00000, 0b00001); 1633 INSN(revw, 0b010, 0b00000, 0b00010); 1634 INSN(clzw, 0b010, 0b00000, 0b00100); 1635 INSN(clsw, 0b010, 0b00000, 0b00101); 1636 1637 INSN(rbit, 0b110, 0b00000, 0b00000); 1638 INSN(rev16, 0b110, 0b00000, 0b00001); 1639 INSN(rev32, 0b110, 0b00000, 0b00010); 1640 INSN(rev, 0b110, 0b00000, 0b00011); 1641 INSN(clz, 0b110, 0b00000, 0b00100); 1642 INSN(cls, 0b110, 0b00000, 0b00101); 1643 1644 #undef INSN 1645 1646 // (2 sources) 1647 #define INSN(NAME, op29, opcode) \ 1648 void NAME(Register Rd, Register Rn, Register Rm) { \ 1649 starti; \ 1650 rf(Rm, 16); \ 1651 data_processing(op29, opcode, Rd, Rn); \ 1652 } 1653 1654 INSN(udivw, 0b000, 0b000010); 1655 INSN(sdivw, 0b000, 0b000011); 1656 INSN(lslvw, 0b000, 0b001000); 1657 INSN(lsrvw, 0b000, 0b001001); 1658 INSN(asrvw, 0b000, 0b001010); 1659 INSN(rorvw, 0b000, 0b001011); 1660 1661 INSN(udiv, 0b100, 0b000010); 1662 INSN(sdiv, 0b100, 0b000011); 1663 INSN(lslv, 0b100, 0b001000); 1664 INSN(lsrv, 0b100, 0b001001); 1665 INSN(asrv, 0b100, 0b001010); 1666 INSN(rorv, 0b100, 0b001011); 1667 1668 #undef INSN 1669 1670 // (3 sources) 1671 void data_processing(unsigned op54, unsigned op31, unsigned o0, 1672 Register Rd, Register Rn, Register Rm, 1673 Register Ra) { 1674 starti; 1675 f(op54, 31, 29), f(0b11011, 28, 24); 1676 f(op31, 23, 21), f(o0, 15); 1677 zrf(Rm, 16), zrf(Ra, 10), zrf(Rn, 5), zrf(Rd, 0); 1678 } 1679 1680 #define INSN(NAME, op54, op31, o0) \ 1681 void NAME(Register Rd, Register Rn, Register Rm, Register Ra) { \ 1682 data_processing(op54, op31, o0, Rd, Rn, Rm, Ra); \ 1683 } 1684 1685 INSN(maddw, 0b000, 0b000, 0); 1686 INSN(msubw, 0b000, 0b000, 1); 1687 INSN(madd, 0b100, 0b000, 0); 1688 INSN(msub, 0b100, 0b000, 1); 1689 INSN(smaddl, 0b100, 0b001, 0); 1690 INSN(smsubl, 0b100, 0b001, 1); 1691 INSN(umaddl, 0b100, 0b101, 0); 1692 INSN(umsubl, 0b100, 0b101, 1); 1693 1694 #undef INSN 1695 1696 #define INSN(NAME, op54, op31, o0) \ 1697 void NAME(Register Rd, Register Rn, Register Rm) { \ 1698 data_processing(op54, op31, o0, Rd, Rn, Rm, (Register)31); \ 1699 } 1700 1701 INSN(smulh, 0b100, 0b010, 0); 1702 INSN(umulh, 0b100, 0b110, 0); 1703 1704 #undef INSN 1705 1706 // Floating-point data-processing (1 source) 1707 void data_processing(unsigned op31, unsigned type, unsigned opcode, 1708 FloatRegister Vd, FloatRegister Vn) { 1709 starti; 1710 f(op31, 31, 29); 1711 f(0b11110, 28, 24); 1712 f(type, 23, 22), f(1, 21), f(opcode, 20, 15), f(0b10000, 14, 10); 1713 rf(Vn, 5), rf(Vd, 0); 1714 } 1715 1716 #define INSN(NAME, op31, type, opcode) \ 1717 void NAME(FloatRegister Vd, FloatRegister Vn) { \ 1718 data_processing(op31, type, opcode, Vd, Vn); \ 1719 } 1720 1721 private: 1722 INSN(i_fmovs, 0b000, 0b00, 0b000000); 1723 public: 1724 INSN(fabss, 0b000, 0b00, 0b000001); 1725 INSN(fnegs, 0b000, 0b00, 0b000010); 1726 INSN(fsqrts, 0b000, 0b00, 0b000011); 1727 INSN(fcvts, 0b000, 0b00, 0b000101); // Single-precision to double-precision 1728 1729 private: 1730 INSN(i_fmovd, 0b000, 0b01, 0b000000); 1731 public: 1732 INSN(fabsd, 0b000, 0b01, 0b000001); 1733 INSN(fnegd, 0b000, 0b01, 0b000010); 1734 INSN(fsqrtd, 0b000, 0b01, 0b000011); 1735 INSN(fcvtd, 0b000, 0b01, 0b000100); // Double-precision to single-precision 1736 1737 void fmovd(FloatRegister Vd, FloatRegister Vn) { 1738 assert(Vd != Vn, "should be"); 1739 i_fmovd(Vd, Vn); 1740 } 1741 1742 void fmovs(FloatRegister Vd, FloatRegister Vn) { 1743 assert(Vd != Vn, "should be"); 1744 i_fmovs(Vd, Vn); 1745 } 1746 1747 #undef INSN 1748 1749 // Floating-point data-processing (2 source) 1750 void data_processing(unsigned op31, unsigned type, unsigned opcode, 1751 FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { 1752 starti; 1753 f(op31, 31, 29); 1754 f(0b11110, 28, 24); 1755 f(type, 23, 22), f(1, 21), f(opcode, 15, 12), f(0b10, 11, 10); 1756 rf(Vm, 16), rf(Vn, 5), rf(Vd, 0); 1757 } 1758 1759 #define INSN(NAME, op31, type, opcode) \ 1760 void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \ 1761 data_processing(op31, type, opcode, Vd, Vn, Vm); \ 1762 } 1763 1764 INSN(fmuls, 0b000, 0b00, 0b0000); 1765 INSN(fdivs, 0b000, 0b00, 0b0001); 1766 INSN(fadds, 0b000, 0b00, 0b0010); 1767 INSN(fsubs, 0b000, 0b00, 0b0011); 1768 INSN(fnmuls, 0b000, 0b00, 0b1000); 1769 1770 INSN(fmuld, 0b000, 0b01, 0b0000); 1771 INSN(fdivd, 0b000, 0b01, 0b0001); 1772 INSN(faddd, 0b000, 0b01, 0b0010); 1773 INSN(fsubd, 0b000, 0b01, 0b0011); 1774 INSN(fnmuld, 0b000, 0b01, 0b1000); 1775 1776 #undef INSN 1777 1778 // Floating-point data-processing (3 source) 1779 void data_processing(unsigned op31, unsigned type, unsigned o1, unsigned o0, 1780 FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, 1781 FloatRegister Va) { 1782 starti; 1783 f(op31, 31, 29); 1784 f(0b11111, 28, 24); 1785 f(type, 23, 22), f(o1, 21), f(o0, 15); 1786 rf(Vm, 16), rf(Va, 10), rf(Vn, 5), rf(Vd, 0); 1787 } 1788 1789 #define INSN(NAME, op31, type, o1, o0) \ 1790 void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, \ 1791 FloatRegister Va) { \ 1792 data_processing(op31, type, o1, o0, Vd, Vn, Vm, Va); \ 1793 } 1794 1795 INSN(fmadds, 0b000, 0b00, 0, 0); 1796 INSN(fmsubs, 0b000, 0b00, 0, 1); 1797 INSN(fnmadds, 0b000, 0b00, 1, 0); 1798 INSN(fnmsubs, 0b000, 0b00, 1, 1); 1799 1800 INSN(fmaddd, 0b000, 0b01, 0, 0); 1801 INSN(fmsubd, 0b000, 0b01, 0, 1); 1802 INSN(fnmaddd, 0b000, 0b01, 1, 0); 1803 INSN(fnmsub, 0b000, 0b01, 1, 1); 1804 1805 #undef INSN 1806 1807 // Floating-point conditional select 1808 void fp_conditional_select(unsigned op31, unsigned type, 1809 unsigned op1, unsigned op2, 1810 Condition cond, FloatRegister Vd, 1811 FloatRegister Vn, FloatRegister Vm) { 1812 starti; 1813 f(op31, 31, 29); 1814 f(0b11110, 28, 24); 1815 f(type, 23, 22); 1816 f(op1, 21, 21); 1817 f(op2, 11, 10); 1818 f(cond, 15, 12); 1819 rf(Vm, 16), rf(Vn, 5), rf(Vd, 0); 1820 } 1821 1822 #define INSN(NAME, op31, type, op1, op2) \ 1823 void NAME(FloatRegister Vd, FloatRegister Vn, \ 1824 FloatRegister Vm, Condition cond) { \ 1825 fp_conditional_select(op31, type, op1, op2, cond, Vd, Vn, Vm); \ 1826 } 1827 1828 INSN(fcsels, 0b000, 0b00, 0b1, 0b11); 1829 INSN(fcseld, 0b000, 0b01, 0b1, 0b11); 1830 1831 #undef INSN 1832 1833 // Floating-point<->integer conversions 1834 void float_int_convert(unsigned op31, unsigned type, 1835 unsigned rmode, unsigned opcode, 1836 Register Rd, Register Rn) { 1837 starti; 1838 f(op31, 31, 29); 1839 f(0b11110, 28, 24); 1840 f(type, 23, 22), f(1, 21), f(rmode, 20, 19); 1841 f(opcode, 18, 16), f(0b000000, 15, 10); 1842 zrf(Rn, 5), zrf(Rd, 0); 1843 } 1844 1845 #define INSN(NAME, op31, type, rmode, opcode) \ 1846 void NAME(Register Rd, FloatRegister Vn) { \ 1847 float_int_convert(op31, type, rmode, opcode, Rd, (Register)Vn); \ 1848 } 1849 1850 INSN(fcvtzsw, 0b000, 0b00, 0b11, 0b000); 1851 INSN(fcvtzs, 0b100, 0b00, 0b11, 0b000); 1852 INSN(fcvtzdw, 0b000, 0b01, 0b11, 0b000); 1853 INSN(fcvtzd, 0b100, 0b01, 0b11, 0b000); 1854 1855 INSN(fmovs, 0b000, 0b00, 0b00, 0b110); 1856 INSN(fmovd, 0b100, 0b01, 0b00, 0b110); 1857 1858 // INSN(fmovhid, 0b100, 0b10, 0b01, 0b110); 1859 1860 #undef INSN 1861 1862 #define INSN(NAME, op31, type, rmode, opcode) \ 1863 void NAME(FloatRegister Vd, Register Rn) { \ 1864 float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn); \ 1865 } 1866 1867 INSN(fmovs, 0b000, 0b00, 0b00, 0b111); 1868 INSN(fmovd, 0b100, 0b01, 0b00, 0b111); 1869 1870 INSN(scvtfws, 0b000, 0b00, 0b00, 0b010); 1871 INSN(scvtfs, 0b100, 0b00, 0b00, 0b010); 1872 INSN(scvtfwd, 0b000, 0b01, 0b00, 0b010); 1873 INSN(scvtfd, 0b100, 0b01, 0b00, 0b010); 1874 1875 // INSN(fmovhid, 0b100, 0b10, 0b01, 0b111); 1876 1877 #undef INSN 1878 1879 // Floating-point compare 1880 void float_compare(unsigned op31, unsigned type, 1881 unsigned op, unsigned op2, 1882 FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) { 1883 starti; 1884 f(op31, 31, 29); 1885 f(0b11110, 28, 24); 1886 f(type, 23, 22), f(1, 21); 1887 f(op, 15, 14), f(0b1000, 13, 10), f(op2, 4, 0); 1888 rf(Vn, 5), rf(Vm, 16); 1889 } 1890 1891 1892 #define INSN(NAME, op31, type, op, op2) \ 1893 void NAME(FloatRegister Vn, FloatRegister Vm) { \ 1894 float_compare(op31, type, op, op2, Vn, Vm); \ 1895 } 1896 1897 #define INSN1(NAME, op31, type, op, op2) \ 1898 void NAME(FloatRegister Vn, double d) { \ 1899 assert_cond(d == 0.0); \ 1900 float_compare(op31, type, op, op2, Vn); \ 1901 } 1902 1903 INSN(fcmps, 0b000, 0b00, 0b00, 0b00000); 1904 INSN1(fcmps, 0b000, 0b00, 0b00, 0b01000); 1905 // INSN(fcmpes, 0b000, 0b00, 0b00, 0b10000); 1906 // INSN1(fcmpes, 0b000, 0b00, 0b00, 0b11000); 1907 1908 INSN(fcmpd, 0b000, 0b01, 0b00, 0b00000); 1909 INSN1(fcmpd, 0b000, 0b01, 0b00, 0b01000); 1910 // INSN(fcmped, 0b000, 0b01, 0b00, 0b10000); 1911 // INSN1(fcmped, 0b000, 0b01, 0b00, 0b11000); 1912 1913 #undef INSN 1914 #undef INSN1 1915 1916 // Floating-point Move (immediate) 1917 private: 1918 unsigned pack(double value); 1919 1920 void fmov_imm(FloatRegister Vn, double value, unsigned size) { 1921 starti; 1922 f(0b00011110, 31, 24), f(size, 23, 22), f(1, 21); 1923 f(pack(value), 20, 13), f(0b10000000, 12, 5); 1924 rf(Vn, 0); 1925 } 1926 1927 public: 1928 1929 void fmovs(FloatRegister Vn, double value) { 1930 if (value) 1931 fmov_imm(Vn, value, 0b00); 1932 else 1933 fmovs(Vn, zr); 1934 } 1935 void fmovd(FloatRegister Vn, double value) { 1936 if (value) 1937 fmov_imm(Vn, value, 0b01); 1938 else 1939 fmovd(Vn, zr); 1940 } 1941 1942 /* SIMD extensions 1943 * 1944 * We just use FloatRegister in the following. They are exactly the same 1945 * as SIMD registers. 1946 */ 1947 public: 1948 1949 enum SIMD_Arrangement { 1950 T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q 1951 }; 1952 1953 enum SIMD_RegVariant { 1954 B, H, S, D, Q 1955 }; 1956 1957 #define INSN(NAME, op) \ 1958 void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \ 1959 ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \ 1960 } \ 1961 1962 INSN(ldr, 1); 1963 INSN(str, 0); 1964 1965 #undef INSN 1966 1967 private: 1968 1969 void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) { 1970 starti; 1971 f(0,31), f((int)T & 1, 30); 1972 f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12); 1973 f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0); 1974 } 1975 void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, 1976 int imm, int op1, int op2) { 1977 starti; 1978 f(0,31), f((int)T & 1, 30); 1979 f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12); 1980 f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0); 1981 } 1982 void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, 1983 Register Xm, int op1, int op2) { 1984 starti; 1985 f(0,31), f((int)T & 1, 30); 1986 f(op1 | 0b100, 29, 21), rf(Xm, 16), f(op2, 15, 12); 1987 f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0); 1988 } 1989 1990 void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2) { 1991 switch (a.getMode()) { 1992 case Address::base_plus_offset: 1993 guarantee(a.offset() == 0, "no offset allowed here"); 1994 ld_st(Vt, T, a.base(), op1, op2); 1995 break; 1996 case Address::post: 1997 ld_st(Vt, T, a.base(), a.offset(), op1, op2); 1998 break; 1999 case Address::base_plus_offset_reg: 2000 ld_st(Vt, T, a.base(), a.index(), op1, op2); 2001 break; 2002 default: 2003 ShouldNotReachHere(); 2004 } 2005 } 2006 2007 public: 2008 2009 #define INSN1(NAME, op1, op2) \ 2010 void NAME(FloatRegister Vt, SIMD_Arrangement T, const Address &a) { \ 2011 ld_st(Vt, T, a, op1, op2); \ 2012 } 2013 2014 #define INSN2(NAME, op1, op2) \ 2015 void NAME(FloatRegister Vt, FloatRegister Vt2, SIMD_Arrangement T, const Address &a) { \ 2016 assert(Vt->successor() == Vt2, "Registers must be ordered"); \ 2017 ld_st(Vt, T, a, op1, op2); \ 2018 } 2019 2020 #define INSN3(NAME, op1, op2) \ 2021 void NAME(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3, \ 2022 SIMD_Arrangement T, const Address &a) { \ 2023 assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3, \ 2024 "Registers must be ordered"); \ 2025 ld_st(Vt, T, a, op1, op2); \ 2026 } 2027 2028 #define INSN4(NAME, op1, op2) \ 2029 void NAME(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3, \ 2030 FloatRegister Vt4, SIMD_Arrangement T, const Address &a) { \ 2031 assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 && \ 2032 Vt3->successor() == Vt4, "Registers must be ordered"); \ 2033 ld_st(Vt, T, a, op1, op2); \ 2034 } 2035 2036 INSN1(ld1, 0b001100010, 0b0111); 2037 INSN2(ld1, 0b001100010, 0b1010); 2038 INSN3(ld1, 0b001100010, 0b0110); 2039 INSN4(ld1, 0b001100010, 0b0010); 2040 2041 INSN2(ld2, 0b001100010, 0b1000); 2042 INSN3(ld3, 0b001100010, 0b0100); 2043 INSN4(ld4, 0b001100010, 0b0000); 2044 2045 INSN1(st1, 0b001100000, 0b0111); 2046 INSN2(st1, 0b001100000, 0b1010); 2047 INSN3(st1, 0b001100000, 0b0110); 2048 INSN4(st1, 0b001100000, 0b0010); 2049 2050 INSN2(st2, 0b001100000, 0b1000); 2051 INSN3(st3, 0b001100000, 0b0100); 2052 INSN4(st4, 0b001100000, 0b0000); 2053 2054 INSN1(ld1r, 0b001101010, 0b1100); 2055 INSN2(ld2r, 0b001101011, 0b1100); 2056 INSN3(ld3r, 0b001101010, 0b1110); 2057 INSN4(ld4r, 0b001101011, 0b1110); 2058 2059 #undef INSN1 2060 #undef INSN2 2061 #undef INSN3 2062 #undef INSN4 2063 2064 #define INSN(NAME, opc) \ 2065 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ 2066 starti; \ 2067 assert(T == T8B || T == T16B, "must be T8B or T16B"); \ 2068 f(0, 31), f((int)T & 1, 30), f(opc, 29, 21); \ 2069 rf(Vm, 16), f(0b000111, 15, 10), rf(Vn, 5), rf(Vd, 0); \ 2070 } 2071 2072 INSN(eor, 0b101110001); 2073 INSN(orr, 0b001110101); 2074 INSN(andr, 0b001110001); 2075 INSN(bic, 0b001110011); 2076 INSN(bif, 0b101110111); 2077 INSN(bit, 0b101110101); 2078 INSN(bsl, 0b101110011); 2079 INSN(orn, 0b001110111); 2080 2081 #undef INSN 2082 2083 #define INSN(NAME, opc, opc2) \ 2084 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ 2085 starti; \ 2086 f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ 2087 f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \ 2088 rf(Vn, 5), rf(Vd, 0); \ 2089 } 2090 2091 INSN(addv, 0, 0b100001); 2092 INSN(subv, 1, 0b100001); 2093 INSN(mulv, 0, 0b100111); 2094 INSN(mlav, 0, 0b100101); 2095 INSN(mlsv, 1, 0b100101); 2096 INSN(sshl, 0, 0b010001); 2097 INSN(ushl, 1, 0b010001); 2098 2099 #undef INSN 2100 2101 #define INSN(NAME, opc, opc2) \ 2102 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ 2103 starti; \ 2104 f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ 2105 f((int)T >> 1, 23, 22), f(opc2, 21, 10); \ 2106 rf(Vn, 5), rf(Vd, 0); \ 2107 } 2108 2109 INSN(absr, 0, 0b100000101110); 2110 INSN(negr, 1, 0b100000101110); 2111 INSN(notr, 1, 0b100000010110); 2112 INSN(addv, 0, 0b110001101110); 2113 INSN(cls, 0, 0b100000010010); 2114 INSN(clz, 1, 0b100000010010); 2115 INSN(cnt, 0, 0b100000010110); 2116 2117 #undef INSN 2118 2119 #define INSN(NAME, op0, cmode0) \ 2120 void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) { \ 2121 unsigned cmode = cmode0; \ 2122 unsigned op = op0; \ 2123 starti; \ 2124 assert(lsl == 0 || \ 2125 ((T == T4H || T == T8H) && lsl == 8) || \ 2126 ((T == T2S || T == T4S) && ((lsl >> 3) < 4)), "invalid shift"); \ 2127 cmode |= lsl >> 2; \ 2128 if (T == T4H || T == T8H) cmode |= 0b1000; \ 2129 if (!(T == T4H || T == T8H || T == T2S || T == T4S)) { \ 2130 assert(op == 0 && cmode0 == 0, "must be MOVI"); \ 2131 cmode = 0b1110; \ 2132 if (T == T1D || T == T2D) op = 1; \ 2133 } \ 2134 f(0, 31), f((int)T & 1, 30), f(op, 29), f(0b0111100000, 28, 19); \ 2135 f(imm8 >> 5, 18, 16), f(cmode, 15, 12), f(0x01, 11, 10), f(imm8 & 0b11111, 9, 5); \ 2136 rf(Vd, 0); \ 2137 } 2138 2139 INSN(movi, 0, 0); 2140 INSN(orri, 0, 1); 2141 INSN(mvni, 1, 0); 2142 INSN(bici, 1, 1); 2143 2144 #undef INSN 2145 2146 #define INSN(NAME, op1, op2, op3) \ 2147 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ 2148 starti; \ 2149 assert(T == T2S || T == T4S || T == T2D, "invalid arrangement"); \ 2150 f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23); \ 2151 f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0); \ 2152 } 2153 2154 INSN(fadd, 0, 0, 0b110101); 2155 INSN(fdiv, 1, 0, 0b111111); 2156 INSN(fmul, 1, 0, 0b110111); 2157 INSN(fsub, 0, 1, 0b110101); 2158 2159 #undef INSN 2160 2161 #define INSN(NAME, opc) \ 2162 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ 2163 starti; \ 2164 assert(T == T4S, "arrangement must be T4S"); \ 2165 f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0); \ 2166 } 2167 2168 INSN(sha1c, 0b000000); 2169 INSN(sha1m, 0b001000); 2170 INSN(sha1p, 0b000100); 2171 INSN(sha1su0, 0b001100); 2172 INSN(sha256h2, 0b010100); 2173 INSN(sha256h, 0b010000); 2174 INSN(sha256su1, 0b011000); 2175 2176 #undef INSN 2177 2178 #define INSN(NAME, opc) \ 2179 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ 2180 starti; \ 2181 assert(T == T4S, "arrangement must be T4S"); \ 2182 f(0b0101111000101000, 31, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0); \ 2183 } 2184 2185 INSN(sha1h, 0b000010); 2186 INSN(sha1su1, 0b000110); 2187 INSN(sha256su0, 0b001010); 2188 2189 #undef INSN 2190 2191 #define INSN(NAME, opc) \ 2192 void NAME(FloatRegister Vd, FloatRegister Vn) { \ 2193 starti; \ 2194 f(opc, 31, 10), rf(Vn, 5), rf(Vd, 0); \ 2195 } 2196 2197 INSN(aese, 0b0100111000101000010010); 2198 INSN(aesd, 0b0100111000101000010110); 2199 INSN(aesmc, 0b0100111000101000011010); 2200 INSN(aesimc, 0b0100111000101000011110); 2201 2202 #undef INSN 2203 2204 void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) { 2205 starti; 2206 assert(T != Q, "invalid register variant"); 2207 f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15); 2208 f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0); 2209 } 2210 2211 void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) { 2212 starti; 2213 f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21); 2214 f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10); 2215 rf(Vn, 5), rf(Rd, 0); 2216 } 2217 2218 #define INSN(NAME, opc, opc2) \ 2219 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \ 2220 starti; \ 2221 /* The encodings for the immh:immb fields (bits 22:16) are \ 2222 * 0001 xxx 8B/16B, shift = xxx \ 2223 * 001x xxx 4H/8H, shift = xxxx \ 2224 * 01xx xxx 2S/4S, shift = xxxxx \ 2225 * 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \ 2226 */ \ 2227 assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \ 2228 f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \ 2229 f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \ 2230 } 2231 2232 INSN(shl, 0, 0b010101); 2233 INSN(sshr, 0, 0b000001); 2234 INSN(ushr, 1, 0b000001); 2235 2236 #undef INSN 2237 2238 void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { 2239 starti; 2240 /* The encodings for the immh:immb fields (bits 22:16) are 2241 * 0001 xxx 8H, 8B/16b shift = xxx 2242 * 001x xxx 4S, 4H/8H shift = xxxx 2243 * 01xx xxx 2D, 2S/4S shift = xxxxx 2244 * 1xxx xxx RESERVED 2245 */ 2246 assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement"); 2247 assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value"); 2248 f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16); 2249 f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0); 2250 } 2251 void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) { 2252 ushll(Vd, Ta, Vn, Tb, shift); 2253 } 2254 2255 void uzp1(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement T, int op = 0){ 2256 starti; 2257 f(0, 31), f((T & 0x1), 30), f(0b001110, 29, 24), f((T >> 1), 23, 22), f(0, 21); 2258 rf(Vm, 16), f(0, 15), f(op, 14), f(0b0110, 13, 10), rf(Vn, 5), rf(Vd, 0); 2259 } 2260 void uzp2(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement T){ 2261 uzp1(Vd, Vn, Vm, T, 1); 2262 } 2263 2264 // Move from general purpose register 2265 // mov Vd.T[index], Rn 2266 void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) { 2267 starti; 2268 f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); 2269 f(0b000111, 15, 10), rf(Xn, 5), rf(Vd, 0); 2270 } 2271 2272 // Move to general purpose register 2273 // mov Rd, Vn.T[index] 2274 void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) { 2275 starti; 2276 f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21); 2277 f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); 2278 f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0); 2279 } 2280 2281 void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { 2282 starti; 2283 assert((Ta == T1Q && (Tb == T1D || Tb == T2D)) || 2284 (Ta == T8H && (Tb == T8B || Tb == T16B)), "Invalid Size specifier"); 2285 int size = (Ta == T1Q) ? 0b11 : 0b00; 2286 f(0, 31), f(Tb & 1, 30), f(0b001110, 29, 24), f(size, 23, 22); 2287 f(1, 21), rf(Vm, 16), f(0b111000, 15, 10), rf(Vn, 5), rf(Vd, 0); 2288 } 2289 void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { 2290 assert(Tb == T2D || Tb == T16B, "pmull2 assumes T2D or T16B as the second size specifier"); 2291 pmull(Vd, Ta, Vn, Vm, Tb); 2292 } 2293 2294 void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) { 2295 starti; 2296 int size_b = (int)Tb >> 1; 2297 int size_a = (int)Ta >> 1; 2298 assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier"); 2299 f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22); 2300 f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0); 2301 } 2302 2303 void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs) 2304 { 2305 starti; 2306 assert(T != T1D, "reserved encoding"); 2307 f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21); 2308 f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), rf(Xs, 5), rf(Vd, 0); 2309 } 2310 2311 void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0) 2312 { 2313 starti; 2314 assert(T != T1D, "reserved encoding"); 2315 f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21); 2316 f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16); 2317 f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0); 2318 } 2319 2320 // CRC32 instructions 2321 #define INSN(NAME, c, sf, sz) \ 2322 void NAME(Register Rd, Register Rn, Register Rm) { \ 2323 starti; \ 2324 f(sf, 31), f(0b0011010110, 30, 21), f(0b010, 15, 13), f(c, 12); \ 2325 f(sz, 11, 10), rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ 2326 } 2327 2328 INSN(crc32b, 0, 0, 0b00); 2329 INSN(crc32h, 0, 0, 0b01); 2330 INSN(crc32w, 0, 0, 0b10); 2331 INSN(crc32x, 0, 1, 0b11); 2332 INSN(crc32cb, 1, 0, 0b00); 2333 INSN(crc32ch, 1, 0, 0b01); 2334 INSN(crc32cw, 1, 0, 0b10); 2335 INSN(crc32cx, 1, 1, 0b11); 2336 2337 #undef INSN 2338 2339 // Table vector lookup 2340 #define INSN(NAME, op) \ 2341 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, unsigned registers, FloatRegister Vm) { \ 2342 starti; \ 2343 assert(T == T8B || T == T16B, "invalid arrangement"); \ 2344 assert(0 < registers && registers <= 4, "invalid number of registers"); \ 2345 f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21), rf(Vm, 16), f(0, 15); \ 2346 f(registers - 1, 14, 13), f(op, 12),f(0b00, 11, 10), rf(Vn, 5), rf(Vd, 0); \ 2347 } 2348 2349 INSN(tbl, 0); 2350 INSN(tbx, 1); 2351 2352 #undef INSN 2353 2354 // AdvSIMD two-reg misc 2355 #define INSN(NAME, U, opcode) \ 2356 void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \ 2357 starti; \ 2358 assert((ASSERTION), MSG); \ 2359 f(0, 31), f((int)T & 1, 30), f(U, 29), f(0b01110, 28, 24); \ 2360 f((int)(T >> 1), 23, 22), f(0b10000, 21, 17), f(opcode, 16, 12); \ 2361 f(0b10, 11, 10), rf(Vn, 5), rf(Vd, 0); \ 2362 } 2363 2364 #define MSG "invalid arrangement" 2365 2366 #define ASSERTION (T == T2S || T == T4S || T == T2D) 2367 INSN(fsqrt, 1, 0b11111); 2368 INSN(fabs, 0, 0b01111); 2369 INSN(fneg, 1, 0b01111); 2370 #undef ASSERTION 2371 2372 #define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H || T == T2S || T == T4S) 2373 INSN(rev64, 0, 0b00000); 2374 #undef ASSERTION 2375 2376 #define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H) 2377 INSN(rev32, 1, 0b00000); 2378 private: 2379 INSN(_rbit, 1, 0b00101); 2380 public: 2381 2382 #undef ASSERTION 2383 2384 #define ASSERTION (T == T8B || T == T16B) 2385 INSN(rev16, 0, 0b00001); 2386 // RBIT only allows T8B and T16B but encodes them oddly. Argh... 2387 void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { 2388 assert((ASSERTION), MSG); 2389 _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn); 2390 } 2391 #undef ASSERTION 2392 2393 #undef MSG 2394 2395 #undef INSN 2396 2397 void ext(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index) 2398 { 2399 starti; 2400 assert(T == T8B || T == T16B, "invalid arrangement"); 2401 assert((T == T8B && index <= 0b0111) || (T == T16B && index <= 0b1111), "Invalid index value"); 2402 f(0, 31), f((int)T & 1, 30), f(0b101110000, 29, 21); 2403 rf(Vm, 16), f(0, 15), f(index, 14, 11); 2404 f(0, 10), rf(Vn, 5), rf(Vd, 0); 2405 } 2406 2407 /* Simulator extensions to the ISA 2408 2409 haltsim 2410 2411 takes no arguments, causes the sim to enter a debug break and then 2412 return from the simulator run() call with STATUS_HALT? The linking 2413 code will call fatal() when it sees STATUS_HALT. 2414 2415 blrt Xn, Wm 2416 blrt Xn, #gpargs, #fpargs, #type 2417 Xn holds the 64 bit x86 branch_address 2418 call format is encoded either as immediate data in the call 2419 or in register Wm. In the latter case 2420 Wm[13..6] = #gpargs, 2421 Wm[5..2] = #fpargs, 2422 Wm[1,0] = #type 2423 2424 calls the x86 code address 'branch_address' supplied in Xn passing 2425 arguments taken from the general and floating point registers according 2426 to the supplied counts 'gpargs' and 'fpargs'. may return a result in r0 2427 or v0 according to the the return type #type' where 2428 2429 address branch_address; 2430 uimm4 gpargs; 2431 uimm4 fpargs; 2432 enum ReturnType type; 2433 2434 enum ReturnType 2435 { 2436 void_ret = 0, 2437 int_ret = 1, 2438 long_ret = 1, 2439 obj_ret = 1, // i.e. same as long 2440 float_ret = 2, 2441 double_ret = 3 2442 } 2443 2444 notify 2445 2446 notifies the simulator of a transfer of control. instr[14:0] 2447 identifies the type of change of control. 2448 2449 0 ==> initial entry to a method. 2450 2451 1 ==> return into a method from a submethod call. 2452 2453 2 ==> exit out of Java method code. 2454 2455 3 ==> start execution for a new bytecode. 2456 2457 in cases 1 and 2 the simulator is expected to use a JVM callback to 2458 identify the name of the specific method being executed. in case 4 2459 the simulator is expected to use a JVM callback to identify the 2460 bytecode index. 2461 2462 Instruction encodings 2463 --------------------- 2464 2465 These are encoded in the space with instr[28:25] = 00 which is 2466 unallocated. Encodings are 2467 2468 10987654321098765432109876543210 2469 PSEUDO_HALT = 0x11100000000000000000000000000000 2470 PSEUDO_BLRT = 0x11000000000000000_______________ 2471 PSEUDO_BLRTR = 0x1100000000000000100000__________ 2472 PSEUDO_NOTIFY = 0x10100000000000000_______________ 2473 2474 instr[31,29] = op1 : 111 ==> HALT, 110 ==> BLRT/BLRTR, 101 ==> NOTIFY 2475 2476 for BLRT 2477 instr[14,11] = #gpargs, instr[10,7] = #fpargs 2478 instr[6,5] = #type, instr[4,0] = Rn 2479 for BLRTR 2480 instr[9,5] = Rm, instr[4,0] = Rn 2481 for NOTIFY 2482 instr[14:0] = type : 0 ==> entry, 1 ==> reentry, 2 ==> exit, 3 ==> bcstart 2483 */ 2484 2485 enum NotifyType { method_entry, method_reentry, method_exit, bytecode_start }; 2486 2487 virtual void notify(int type) { 2488 if (UseBuiltinSim) { 2489 starti; 2490 // 109 2491 f(0b101, 31, 29); 2492 // 87654321098765 2493 f(0b00000000000000, 28, 15); 2494 f(type, 14, 0); 2495 } 2496 } 2497 2498 void blrt(Register Rn, int gpargs, int fpargs, int type) { 2499 if (UseBuiltinSim) { 2500 starti; 2501 f(0b110, 31 ,29); 2502 f(0b00, 28, 25); 2503 // 4321098765 2504 f(0b0000000000, 24, 15); 2505 f(gpargs, 14, 11); 2506 f(fpargs, 10, 7); 2507 f(type, 6, 5); 2508 rf(Rn, 0); 2509 } else { 2510 blr(Rn); 2511 } 2512 } 2513 2514 void blrt(Register Rn, Register Rm) { 2515 if (UseBuiltinSim) { 2516 starti; 2517 f(0b110, 31 ,29); 2518 f(0b00, 28, 25); 2519 // 4321098765 2520 f(0b0000000001, 24, 15); 2521 // 43210 2522 f(0b00000, 14, 10); 2523 rf(Rm, 5); 2524 rf(Rn, 0); 2525 } else { 2526 blr(Rn); 2527 } 2528 } 2529 2530 void haltsim() { 2531 starti; 2532 f(0b111, 31 ,29); 2533 f(0b00, 28, 27); 2534 // 654321098765432109876543210 2535 f(0b000000000000000000000000000, 26, 0); 2536 } 2537 2538 Assembler(CodeBuffer* code) : AbstractAssembler(code) { 2539 } 2540 2541 virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, 2542 Register tmp, 2543 int offset) { 2544 ShouldNotCallThis(); 2545 return RegisterOrConstant(); 2546 } 2547 2548 // Stack overflow checking 2549 virtual void bang_stack_with_offset(int offset); 2550 2551 static bool operand_valid_for_logical_immediate(bool is32, uint64_t imm); 2552 static bool operand_valid_for_add_sub_immediate(long imm); 2553 static bool operand_valid_for_float_immediate(double imm); 2554 2555 void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); 2556 void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); 2557 }; 2558 2559 inline Assembler::Membar_mask_bits operator|(Assembler::Membar_mask_bits a, 2560 Assembler::Membar_mask_bits b) { 2561 return Assembler::Membar_mask_bits(unsigned(a)|unsigned(b)); 2562 } 2563 2564 Instruction_aarch64::~Instruction_aarch64() { 2565 assem->emit(); 2566 } 2567 2568 #undef starti 2569 2570 // Invert a condition 2571 inline const Assembler::Condition operator~(const Assembler::Condition cond) { 2572 return Assembler::Condition(int(cond) ^ 1); 2573 } 2574 2575 class BiasedLockingCounters; 2576 2577 extern "C" void das(uint64_t start, int len); 2578 2579 #endif // CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP