< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page
rev 60626 : 8248663: AArch64: Avoid existing macros/keywords of MSVC
Reviewed-by:
Contributed-by: mbeckwit, luhenry, burban
rev 60629 : 8248656: Add Windows AArch64 platform support code
Reviewed-by:
Contributed-by: mbeckwit, luhenry, burban
rev 60631 : 8248660: AArch64: Make _clear_cache and _nop portable
Reviewed-by:
Contributed-by: mbeckwit, luhenry, burban


  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_ASSEMBLER_AARCH64_HPP
  27 #define CPU_AARCH64_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 {
  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 


 596 
 597   InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {}
 598 };
 599 
 600 const int FPUStateSizeInWords = FloatRegisterImpl::number_of_registers *
 601                                 FloatRegisterImpl::save_slots_per_register;
 602 
 603 typedef enum {
 604   PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM,
 605   PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM,
 606   PLIL1KEEP = 0b01000, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM
 607 } prfop;
 608 
 609 class Assembler : public AbstractAssembler {
 610 
 611 #ifndef PRODUCT
 612   static const uintptr_t asm_bp;
 613 
 614   void emit_long(jint x) {
 615     if ((uintptr_t)pc() == asm_bp)
 616       asm volatile ("nop");
 617     AbstractAssembler::emit_int32(x);
 618   }
 619 #else
 620   void emit_long(jint x) {
 621     AbstractAssembler::emit_int32(x);
 622   }
 623 #endif
 624 
 625 public:
 626 
 627   enum { instruction_size = 4 };
 628 
 629   //---<  calculate length of instruction  >---
 630   // We just use the values set above.
 631   // instruction must start at passed address
 632   static unsigned int instr_len(unsigned char *instr) { return instruction_size; }
 633 
 634   //---<  longest instructions  >---
 635   static unsigned int instr_maxlen() { return instruction_size; }
 636 
 637   Address adjust(Register base, int offset, bool preIncrement) {
 638     if (preIncrement)
 639       return Address(Pre(base, offset));
 640     else
 641       return Address(Post(base, offset));
 642   }
 643 
 644   Address pre(Register base, int offset) {
 645     return adjust(base, offset, true);
 646   }
 647 
 648   Address post(Register base, int offset) {
 649     return adjust(base, offset, false);
 650   }
 651 
 652   Address post(Register base, Register idx) {
 653     return Address(Post(base, idx));
 654   }
 655 


 656   Instruction_aarch64* current;
 657 
 658   void set_current(Instruction_aarch64* i) { current = i; }
 659 
 660   void f(unsigned val, int msb, int lsb) {
 661     current->f(val, msb, lsb);
 662   }
 663   void f(unsigned val, int msb) {
 664     current->f(val, msb, msb);
 665   }
 666   void sf(int64_t val, int msb, int lsb) {
 667     current->sf(val, msb, lsb);
 668   }
 669   void rf(Register reg, int lsb) {
 670     current->rf(reg, lsb);
 671   }
 672   void srf(Register reg, int lsb) {
 673     current->srf(reg, lsb);
 674   }
 675   void zrf(Register reg, int lsb) {


1504   }                                                                     \
1505                                                                         \
1506   /* These instructions have no immediate form. Provide an overload so  \
1507      that if anyone does try to use an immediate operand -- this has    \
1508      happened! -- we'll get a compile-time error. */                    \
1509   void NAME(Register Rd, Register Rn, unsigned imm,                     \
1510             enum shift_kind kind = LSL, unsigned shift = 0) {           \
1511     assert(false, " can't be used with immediate operand");             \
1512   }
1513 
1514   INSN(bic, 1, 0b00, 1);
1515   INSN(orn, 1, 0b01, 1);
1516   INSN(eon, 1, 0b10, 1);
1517   INSN(bics, 1, 0b11, 1);
1518   INSN(bicw, 0, 0b00, 1);
1519   INSN(ornw, 0, 0b01, 1);
1520   INSN(eonw, 0, 0b10, 1);
1521   INSN(bicsw, 0, 0b11, 1);
1522 
1523 #undef INSN





1524 
1525   // Aliases for short forms of orn
1526 void mvn(Register Rd, Register Rm,
1527             enum shift_kind kind = LSL, unsigned shift = 0) {
1528   orn(Rd, zr, Rm, kind, shift);
1529 }
1530 
1531 void mvnw(Register Rd, Register Rm,
1532             enum shift_kind kind = LSL, unsigned shift = 0) {
1533   ornw(Rd, zr, Rm, kind, shift);
1534 }
1535 
1536   // Add/subtract (shifted register)
1537 #define INSN(NAME, size, op)                            \
1538   void NAME(Register Rd, Register Rn, Register Rm,      \
1539             enum shift_kind kind, unsigned shift = 0) { \
1540     starti;                                             \
1541     f(0, 21);                                           \
1542     assert_cond(kind != ROR);                           \
1543     guarantee(size == 1 || shift < 32, "incorrect shift");\




  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_ASSEMBLER_AARCH64_HPP
  27 #define CPU_AARCH64_ASSEMBLER_AARCH64_HPP
  28 
  29 #include "asm/register.hpp"
  30 
  31 #ifdef __GNUC__
  32 
  33 // __nop needs volatile so that compiler doesn't optimize it away
  34 #define NOP() asm volatile ("nop");
  35 
  36 #elif defined(_MSC_VER)
  37 
  38 // Use MSVC instrinsic: https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=vs-2019#I
  39 #define NOP() __nop();
  40 
  41 #endif
  42 
  43 
  44 
  45 // definitions of various symbolic names for machine registers
  46 
  47 // First intercalls between C and Java which use 8 general registers
  48 // and 8 floating registers
  49 
  50 // we also have to copy between x86 and ARM registers but that's a
  51 // secondary complication -- not all code employing C call convention
  52 // executes as x86 code though -- we generate some of it
  53 
  54 class Argument {
  55  public:
  56   enum {
  57     n_int_register_parameters_c   = 8,  // r0, r1, ... r7 (c_rarg0, c_rarg1, ...)
  58     n_float_register_parameters_c = 8,  // v0, v1, ... v7 (c_farg0, c_farg1, ... )
  59 
  60     n_int_register_parameters_j   = 8, // r1, ... r7, r0 (rj_rarg0, j_rarg1, ...
  61     n_float_register_parameters_j = 8  // v0, v1, ... v7 (j_farg0, j_farg1, ...
  62   };
  63 };
  64 


 610 
 611   InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {}
 612 };
 613 
 614 const int FPUStateSizeInWords = FloatRegisterImpl::number_of_registers *
 615                                 FloatRegisterImpl::save_slots_per_register;
 616 
 617 typedef enum {
 618   PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM,
 619   PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM,
 620   PLIL1KEEP = 0b01000, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM
 621 } prfop;
 622 
 623 class Assembler : public AbstractAssembler {
 624 
 625 #ifndef PRODUCT
 626   static const uintptr_t asm_bp;
 627 
 628   void emit_long(jint x) {
 629     if ((uintptr_t)pc() == asm_bp)
 630       NOP();
 631     AbstractAssembler::emit_int32(x);
 632   }
 633 #else
 634   void emit_long(jint x) {
 635     AbstractAssembler::emit_int32(x);
 636   }
 637 #endif
 638 
 639 public:
 640 
 641   enum { instruction_size = 4 };
 642 
 643   //---<  calculate length of instruction  >---
 644   // We just use the values set above.
 645   // instruction must start at passed address
 646   static unsigned int instr_len(unsigned char *instr) { return instruction_size; }
 647 
 648   //---<  longest instructions  >---
 649   static unsigned int instr_maxlen() { return instruction_size; }
 650 
 651   Address adjust(Register base, int offset, bool preIncrement) {
 652     if (preIncrement)
 653       return Address(Pre(base, offset));
 654     else
 655       return Address(Post(base, offset));
 656   }
 657 
 658   Address pre(Register base, int offset) {
 659     return adjust(base, offset, true);
 660   }
 661 
 662   Address post(Register base, int offset) {
 663     return adjust(base, offset, false);
 664   }
 665 
 666   Address post(Register base, Register idx) {
 667     return Address(Post(base, idx));
 668   }
 669 
 670   static address locate_next_instruction(address inst);
 671 
 672   Instruction_aarch64* current;
 673 
 674   void set_current(Instruction_aarch64* i) { current = i; }
 675 
 676   void f(unsigned val, int msb, int lsb) {
 677     current->f(val, msb, lsb);
 678   }
 679   void f(unsigned val, int msb) {
 680     current->f(val, msb, msb);
 681   }
 682   void sf(int64_t val, int msb, int lsb) {
 683     current->sf(val, msb, lsb);
 684   }
 685   void rf(Register reg, int lsb) {
 686     current->rf(reg, lsb);
 687   }
 688   void srf(Register reg, int lsb) {
 689     current->srf(reg, lsb);
 690   }
 691   void zrf(Register reg, int lsb) {


1520   }                                                                     \
1521                                                                         \
1522   /* These instructions have no immediate form. Provide an overload so  \
1523      that if anyone does try to use an immediate operand -- this has    \
1524      happened! -- we'll get a compile-time error. */                    \
1525   void NAME(Register Rd, Register Rn, unsigned imm,                     \
1526             enum shift_kind kind = LSL, unsigned shift = 0) {           \
1527     assert(false, " can't be used with immediate operand");             \
1528   }
1529 
1530   INSN(bic, 1, 0b00, 1);
1531   INSN(orn, 1, 0b01, 1);
1532   INSN(eon, 1, 0b10, 1);
1533   INSN(bics, 1, 0b11, 1);
1534   INSN(bicw, 0, 0b00, 1);
1535   INSN(ornw, 0, 0b01, 1);
1536   INSN(eonw, 0, 0b10, 1);
1537   INSN(bicsw, 0, 0b11, 1);
1538 
1539 #undef INSN
1540 
1541 #ifdef _WIN64
1542 // In MSVC, `mvn` is defined as a macro and it affects compilation
1543 #undef mvn
1544 #endif
1545 
1546   // Aliases for short forms of orn
1547 void mvn(Register Rd, Register Rm,
1548             enum shift_kind kind = LSL, unsigned shift = 0) {
1549   orn(Rd, zr, Rm, kind, shift);
1550 }
1551 
1552 void mvnw(Register Rd, Register Rm,
1553             enum shift_kind kind = LSL, unsigned shift = 0) {
1554   ornw(Rd, zr, Rm, kind, shift);
1555 }
1556 
1557   // Add/subtract (shifted register)
1558 #define INSN(NAME, size, op)                            \
1559   void NAME(Register Rd, Register Rn, Register Rm,      \
1560             enum shift_kind kind, unsigned shift = 0) { \
1561     starti;                                             \
1562     f(0, 21);                                           \
1563     assert_cond(kind != ROR);                           \
1564     guarantee(size == 1 || shift < 32, "incorrect shift");\


< prev index next >