1 /*
   2  * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef CPU_ARM_VM_ASSEMBLER_ARM_64_HPP
  26 #define CPU_ARM_VM_ASSEMBLER_ARM_64_HPP
  27 
  28 enum AsmShift12 {
  29   lsl0, lsl12
  30 };
  31 
  32 enum AsmPrefetchOp {
  33     pldl1keep = 0b00000,
  34     pldl1strm,
  35     pldl2keep,
  36     pldl2strm,
  37     pldl3keep,
  38     pldl3strm,
  39 
  40     plil1keep = 0b01000,
  41     plil1strm,
  42     plil2keep,
  43     plil2strm,
  44     plil3keep,
  45     plil3strm,
  46 
  47     pstl1keep = 0b10000,
  48     pstl1strm,
  49     pstl2keep,
  50     pstl2strm,
  51     pstl3keep,
  52     pstl3strm,
  53 };
  54 
  55 // Shifted register operand for data processing instructions.
  56 class AsmOperand VALUE_OBJ_CLASS_SPEC {
  57  private:
  58   Register _reg;
  59   AsmShift _shift;
  60   int _shift_imm;
  61 
  62  public:
  63   AsmOperand(Register reg) {
  64     assert(reg != SP, "SP is not allowed in shifted register operand");
  65     _reg = reg;
  66     _shift = lsl;
  67     _shift_imm = 0;
  68   }
  69 
  70   AsmOperand(Register reg, AsmShift shift, int shift_imm) {
  71     assert(reg != SP, "SP is not allowed in shifted register operand");
  72     assert(shift_imm >= 0, "shift amount should be non-negative");
  73     _reg = reg;
  74     _shift = shift;
  75     _shift_imm = shift_imm;
  76   }
  77 
  78   Register reg() const {
  79     return _reg;
  80   }
  81 
  82   AsmShift shift() const {
  83     return _shift;
  84   }
  85 
  86   int shift_imm() const {
  87     return _shift_imm;
  88   }
  89 };
  90 
  91 
  92 class Assembler : public AbstractAssembler  {
  93 
  94  public:
  95 
  96   static const int LogInstructionSize = 2;
  97   static const int InstructionSize    = 1 << LogInstructionSize;
  98 
  99   Assembler(CodeBuffer* code) : AbstractAssembler(code) {}
 100 
 101   static inline AsmCondition inverse(AsmCondition cond) {
 102     assert ((cond != al) && (cond != nv), "AL and NV conditions cannot be inversed");
 103     return (AsmCondition)((int)cond ^ 1);
 104   }
 105 
 106   // Returns value of nzcv flags conforming to the given condition.
 107   static inline int flags_for_condition(AsmCondition cond) {
 108     switch(cond) {            // NZCV
 109       case mi: case lt: return 0b1000;
 110       case eq: case le: return 0b0100;
 111       case hs: case hi: return 0b0010;
 112       case vs:          return 0b0001;
 113       default:          return 0b0000;
 114     }
 115   }
 116 
 117   // Immediate, encoded into logical instructions.
 118   class LogicalImmediate {
 119    private:
 120     bool _encoded;
 121     bool _is32bit;
 122     int _immN;
 123     int _immr;
 124     int _imms;
 125 
 126     static inline bool has_equal_subpatterns(uintx imm, int size);
 127     static inline int least_pattern_size(uintx imm);
 128     static inline int population_count(uintx x);
 129     static inline uintx set_least_zeroes(uintx x);
 130 
 131 #ifdef ASSERT
 132     uintx decode();
 133 #endif
 134 
 135     void construct(uintx imm, bool is32);
 136 
 137    public:
 138     LogicalImmediate(uintx imm, bool is32 = false) { construct(imm, is32); }
 139 
 140     // Returns true if given immediate can be used in AArch64 logical instruction.
 141     bool is_encoded() const { return _encoded; }
 142 
 143     bool is32bit() const { return _is32bit; }
 144     int immN() const { assert(_encoded, "should be"); return _immN; }
 145     int immr() const { assert(_encoded, "should be"); return _immr; }
 146     int imms() const { assert(_encoded, "should be"); return _imms; }
 147   };
 148 
 149   // Immediate, encoded into arithmetic add/sub instructions.
 150   class ArithmeticImmediate {
 151    private:
 152     bool _encoded;
 153     int _imm;
 154     AsmShift12 _shift;
 155 
 156    public:
 157     ArithmeticImmediate(intx x) {
 158       if (is_unsigned_imm_in_range(x, 12, 0)) {
 159         _encoded = true;
 160         _imm = x;
 161         _shift = lsl0;
 162       } else if (is_unsigned_imm_in_range(x, 12, 12)) {
 163         _encoded = true;
 164         _imm = x >> 12;
 165         _shift = lsl12;
 166       } else {
 167         _encoded = false;
 168       }
 169     }
 170 
 171     ArithmeticImmediate(intx x, AsmShift12 sh) {
 172       if (is_unsigned_imm_in_range(x, 12, 0)) {
 173         _encoded = true;
 174         _imm = x;
 175         _shift = sh;
 176       } else {
 177         _encoded = false;
 178       }
 179     }
 180 
 181     // Returns true if this immediate can be used in AArch64 arithmetic (add/sub/cmp/cmn) instructions.
 182     bool is_encoded() const  { return _encoded; }
 183 
 184     int imm() const          { assert(_encoded, "should be"); return _imm; }
 185     AsmShift12 shift() const { assert(_encoded, "should be"); return _shift; }
 186   };
 187 
 188   static inline bool is_imm_in_range(intx value, int bits, int align_bits) {
 189     intx sign_bits = (value >> (bits + align_bits - 1));
 190     return ((value & right_n_bits(align_bits)) == 0) && ((sign_bits == 0) || (sign_bits == -1));
 191   }
 192 
 193   static inline int encode_imm(intx value, int bits, int align_bits, int low_bit_in_encoding) {
 194     assert (is_imm_in_range(value, bits, align_bits), "immediate value is out of range");
 195     return ((value >> align_bits) & right_n_bits(bits)) << low_bit_in_encoding;
 196   }
 197 
 198   static inline bool is_unsigned_imm_in_range(intx value, int bits, int align_bits) {
 199     return (value >= 0) && ((value & right_n_bits(align_bits)) == 0) && ((value >> (align_bits + bits)) == 0);
 200   }
 201 
 202   static inline int encode_unsigned_imm(intx value, int bits, int align_bits, int low_bit_in_encoding) {
 203     assert (is_unsigned_imm_in_range(value, bits, align_bits), "immediate value is out of range");
 204     return (value >> align_bits) << low_bit_in_encoding;
 205   }
 206 
 207   static inline bool is_offset_in_range(intx offset, int bits) {
 208     assert (bits == 14 || bits == 19 || bits == 26, "wrong bits number");
 209     return is_imm_in_range(offset, bits, 2);
 210   }
 211 
 212   static inline int encode_offset(intx offset, int bits, int low_bit_in_encoding) {
 213     return encode_imm(offset, bits, 2, low_bit_in_encoding);
 214   }
 215 
 216   // Returns true if given value can be used as immediate in arithmetic (add/sub/cmp/cmn) instructions.
 217   static inline bool is_arith_imm_in_range(intx value) {
 218     return ArithmeticImmediate(value).is_encoded();
 219   }
 220 
 221 
 222   // Load/store instructions
 223 
 224 #define F(mnemonic, opc) \
 225   void mnemonic(Register rd, address literal_addr) {                                                       \
 226     intx offset = literal_addr - pc();                                                                     \
 227     assert (opc != 0b01 || offset == 0 || ((uintx)literal_addr & 7) == 0, "ldr target should be aligned"); \
 228     assert (is_offset_in_range(offset, 19), "offset is out of range");                                     \
 229     emit_int32(opc << 30 | 0b011 << 27 | encode_offset(offset, 19, 5) | rd->encoding_with_zr());           \
 230   }
 231 
 232   F(ldr_w, 0b00)
 233   F(ldr,   0b01)
 234   F(ldrsw, 0b10)
 235 #undef F
 236 
 237 #define F(mnemonic, opc) \
 238   void mnemonic(FloatRegister rt, address literal_addr) {                                                  \
 239     intx offset = literal_addr - pc();                                                                     \
 240     assert (offset == 0 || ((uintx)literal_addr & right_n_bits(2 + opc)) == 0, "ldr target should be aligned"); \
 241     assert (is_offset_in_range(offset, 19), "offset is out of range");                                     \
 242     emit_int32(opc << 30 | 0b011100 << 24 | encode_offset(offset, 19, 5) | rt->encoding());                \
 243   }
 244 
 245   F(ldr_s, 0b00)
 246   F(ldr_d, 0b01)
 247   F(ldr_q, 0b10)
 248 #undef F
 249 
 250 #define F(mnemonic, size, o2, L, o1, o0) \
 251   void mnemonic(Register rt, Register rn) {                                                                \
 252     emit_int32(size << 30 | 0b001000 << 24 | o2 << 23 | L << 22 | o1 << 21 | 0b11111 << 16 |               \
 253         o0 << 15 | 0b11111 << 10 | rn->encoding_with_sp() << 5 | rt->encoding_with_zr());                  \
 254   }
 255 
 256   F(ldxrb,   0b00, 0, 1, 0, 0)
 257   F(ldaxrb,  0b00, 0, 1, 0, 1)
 258   F(ldarb,   0b00, 1, 1, 0, 1)
 259   F(ldxrh,   0b01, 0, 1, 0, 0)
 260   F(ldaxrh,  0b01, 0, 1, 0, 1)
 261   F(ldarh,   0b01, 1, 1, 0, 1)
 262   F(ldxr_w,  0b10, 0, 1, 0, 0)
 263   F(ldaxr_w, 0b10, 0, 1, 0, 1)
 264   F(ldar_w,  0b10, 1, 1, 0, 1)
 265   F(ldxr,    0b11, 0, 1, 0, 0)
 266   F(ldaxr,   0b11, 0, 1, 0, 1)
 267   F(ldar,    0b11, 1, 1, 0, 1)
 268 
 269   F(stlrb,   0b00, 1, 0, 0, 1)
 270   F(stlrh,   0b01, 1, 0, 0, 1)
 271   F(stlr_w,  0b10, 1, 0, 0, 1)
 272   F(stlr,    0b11, 1, 0, 0, 1)
 273 #undef F
 274 
 275 #define F(mnemonic, size, o2, L, o1, o0) \
 276   void mnemonic(Register rs, Register rt, Register rn) {                                                     \
 277     assert (rs != rt, "should be different");                                                                \
 278     assert (rs != rn, "should be different");                                                                \
 279     emit_int32(size << 30 | 0b001000 << 24 | o2 << 23 | L << 22 | o1 << 21 | rs->encoding_with_zr() << 16 |  \
 280         o0 << 15 | 0b11111 << 10 | rn->encoding_with_sp() << 5 | rt->encoding_with_zr());                    \
 281   }
 282 
 283   F(stxrb,   0b00, 0, 0, 0, 0)
 284   F(stlxrb,  0b00, 0, 0, 0, 1)
 285   F(stxrh,   0b01, 0, 0, 0, 0)
 286   F(stlxrh,  0b01, 0, 0, 0, 1)
 287   F(stxr_w,  0b10, 0, 0, 0, 0)
 288   F(stlxr_w, 0b10, 0, 0, 0, 1)
 289   F(stxr,    0b11, 0, 0, 0, 0)
 290   F(stlxr,   0b11, 0, 0, 0, 1)
 291 #undef F
 292 
 293 #define F(mnemonic, size, o2, L, o1, o0) \
 294   void mnemonic(Register rt, Register rt2, Register rn) {                                                  \
 295     assert (rt != rt2, "should be different");                                                             \
 296     emit_int32(size << 30 | 0b001000 << 24 | o2 << 23 | L << 22 | o1 << 21 | 0b11111 << 16 |               \
 297         o0 << 15 | rt2->encoding_with_zr() << 10 | rn->encoding_with_sp() << 5 | rt->encoding_with_zr());  \
 298   }
 299 
 300   F(ldxp_w,  0b10, 0, 1, 1, 0)
 301   F(ldaxp_w, 0b10, 0, 1, 1, 1)
 302   F(ldxp,    0b11, 0, 1, 1, 0)
 303   F(ldaxp,   0b11, 0, 1, 1, 1)
 304 #undef F
 305 
 306 #define F(mnemonic, size, o2, L, o1, o0) \
 307   void mnemonic(Register rs, Register rt, Register rt2, Register rn) {                                       \
 308     assert (rs != rt, "should be different");                                                                \
 309     assert (rs != rt2, "should be different");                                                               \
 310     assert (rs != rn, "should be different");                                                                \
 311     emit_int32(size << 30 | 0b001000 << 24 | o2 << 23 | L << 22 | o1 << 21 | rs->encoding_with_zr() << 16 |  \
 312         o0 << 15 | rt2->encoding_with_zr() << 10 | rn->encoding_with_sp() << 5 | rt->encoding_with_zr());    \
 313   }
 314 
 315   F(stxp_w,  0b10, 0, 0, 1, 0)
 316   F(stlxp_w, 0b10, 0, 0, 1, 1)
 317   F(stxp,    0b11, 0, 0, 1, 0)
 318   F(stlxp,   0b11, 0, 0, 1, 1)
 319 #undef F
 320 
 321 #define F(mnemonic, opc, V, L) \
 322   void mnemonic(Register rt, Register rt2, Register rn, int offset = 0) {                                  \
 323     assert (!L || rt != rt2, "should be different");                                                       \
 324     int align_bits = 2 + (opc >> 1);                                                                       \
 325     assert (is_imm_in_range(offset, 7, align_bits), "offset is out of range");                             \
 326     emit_int32(opc << 30 | 0b101 << 27 | V << 26 | L << 22 | encode_imm(offset, 7, align_bits, 15) |       \
 327         rt2->encoding_with_zr() << 10 | rn->encoding_with_sp() << 5 | rt->encoding_with_zr());             \
 328   }
 329 
 330   F(stnp_w,  0b00, 0, 0)
 331   F(ldnp_w,  0b00, 0, 1)
 332   F(stnp,    0b10, 0, 0)
 333   F(ldnp,    0b10, 0, 1)
 334 #undef F
 335 
 336 #define F(mnemonic, opc, V, L) \
 337   void mnemonic(FloatRegister rt, FloatRegister rt2, Register rn, int offset = 0) {                        \
 338     assert (!L || (rt != rt2), "should be different");                                                     \
 339     int align_bits = 2 + opc;                                                                              \
 340     assert (is_imm_in_range(offset, 7, align_bits), "offset is out of range");                             \
 341     emit_int32(opc << 30 | 0b101 << 27 | V << 26 | L << 22 | encode_imm(offset, 7, align_bits, 15) |       \
 342         rt2->encoding() << 10 | rn->encoding_with_sp() << 5 | rt->encoding());                             \
 343   }
 344 
 345   F(stnp_s,  0b00, 1, 0)
 346   F(stnp_d,  0b01, 1, 0)
 347   F(stnp_q,  0b10, 1, 0)
 348   F(ldnp_s,  0b00, 1, 1)
 349   F(ldnp_d,  0b01, 1, 1)
 350   F(ldnp_q,  0b10, 1, 1)
 351 #undef F
 352 
 353 #define F(mnemonic, size, V, opc) \
 354   void mnemonic(Register rt, Address addr) { \
 355     assert((addr.mode() == basic_offset) || (rt != addr.base()), "should be different");                    \
 356     if (addr.index() == noreg) {                                                                            \
 357       if ((addr.mode() == basic_offset) && is_unsigned_imm_in_range(addr.disp(), 12, size)) {               \
 358         emit_int32(size << 30 | 0b111 << 27 | V << 26 | 0b01 << 24 | opc << 22 |                            \
 359            encode_unsigned_imm(addr.disp(), 12, size, 10) |                                                 \
 360            addr.base()->encoding_with_sp() << 5 | rt->encoding_with_zr());                                  \
 361       } else {                                                                                              \
 362         assert(is_imm_in_range(addr.disp(), 9, 0), "offset is out of range");                               \
 363         emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | encode_imm(addr.disp(), 9, 0, 12) |     \
 364            addr.mode() << 10 | addr.base()->encoding_with_sp() << 5 | rt->encoding_with_zr());              \
 365       }                                                                                                     \
 366     } else {                                                                                                \
 367       assert (addr.disp() == 0, "non-zero displacement for [reg + reg] address mode");                      \
 368       assert ((addr.shift_imm() == 0) || (addr.shift_imm() == size), "invalid shift amount");               \
 369       emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | 1 << 21 |                                 \
 370          addr.index()->encoding_with_zr() << 16 | addr.extend() << 13 | (addr.shift_imm() != 0) << 12 |     \
 371          0b10 << 10 | addr.base()->encoding_with_sp() << 5 | rt->encoding_with_zr());                       \
 372     }                                                                                                       \
 373   }
 374 
 375   F(strb,    0b00, 0, 0b00)
 376   F(ldrb,    0b00, 0, 0b01)
 377   F(ldrsb,   0b00, 0, 0b10)
 378   F(ldrsb_w, 0b00, 0, 0b11)
 379 
 380   F(strh,    0b01, 0, 0b00)
 381   F(ldrh,    0b01, 0, 0b01)
 382   F(ldrsh,   0b01, 0, 0b10)
 383   F(ldrsh_w, 0b01, 0, 0b11)
 384 
 385   F(str_w,   0b10, 0, 0b00)
 386   F(ldr_w,   0b10, 0, 0b01)
 387   F(ldrsw,   0b10, 0, 0b10)
 388 
 389   F(str,     0b11, 0, 0b00)
 390   F(ldr,     0b11, 0, 0b01)
 391 #undef F
 392 
 393 #define F(mnemonic, size, V, opc) \
 394   void mnemonic(AsmPrefetchOp prfop, Address addr) { \
 395     assert (addr.mode() == basic_offset, #mnemonic " supports only basic_offset address mode");             \
 396     if (addr.index() == noreg) {                                                                            \
 397       if (is_unsigned_imm_in_range(addr.disp(), 12, size)) {                                                \
 398         emit_int32(size << 30 | 0b111 << 27 | V << 26 | 0b01 << 24 | opc << 22 |                            \
 399            encode_unsigned_imm(addr.disp(), 12, size, 10) |                                                 \
 400            addr.base()->encoding_with_sp() << 5 | prfop);                                                   \
 401       } else {                                                                                              \
 402         assert(is_imm_in_range(addr.disp(), 9, 0), "offset is out of range");                               \
 403         emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | encode_imm(addr.disp(), 9, 0, 12) |     \
 404            addr.base()->encoding_with_sp() << 5 | prfop);                                                   \
 405       }                                                                                                     \
 406     } else {                                                                                                \
 407       assert (addr.disp() == 0, "non-zero displacement for [reg + reg] address mode");                      \
 408       assert ((addr.shift_imm() == 0) || (addr.shift_imm() == size), "invalid shift amount");               \
 409       emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | 1 << 21 |                                 \
 410          addr.index()->encoding_with_zr() << 16 | addr.extend() << 13 | (addr.shift_imm() != 0) << 12 |     \
 411          0b10 << 10 | addr.base()->encoding_with_sp() << 5 | prfop);                                        \
 412     }                                                                                                       \
 413   }
 414 
 415   F(prfm, 0b11, 0, 0b10)
 416 #undef F
 417 
 418 #define F(mnemonic, size, V, opc) \
 419   void mnemonic(FloatRegister rt, Address addr) { \
 420     int align_bits = (((opc & 0b10) >> 1) << 2) | size;                                                     \
 421     if (addr.index() == noreg) {                                                                            \
 422       if ((addr.mode() == basic_offset) && is_unsigned_imm_in_range(addr.disp(), 12, align_bits)) {         \
 423         emit_int32(size << 30 | 0b111 << 27 | V << 26 | 0b01 << 24 | opc << 22 |                            \
 424            encode_unsigned_imm(addr.disp(), 12, align_bits, 10) |                                           \
 425            addr.base()->encoding_with_sp() << 5 | rt->encoding());                                          \
 426       } else {                                                                                              \
 427         assert(is_imm_in_range(addr.disp(), 9, 0), "offset is out of range");                               \
 428         emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | encode_imm(addr.disp(), 9, 0, 12) |     \
 429            addr.mode() << 10 | addr.base()->encoding_with_sp() << 5 | rt->encoding());                      \
 430       }                                                                                                     \
 431     } else {                                                                                                \
 432       assert (addr.disp() == 0, "non-zero displacement for [reg + reg] address mode");                      \
 433       assert ((addr.shift_imm() == 0) || (addr.shift_imm() == align_bits), "invalid shift amount");         \
 434       emit_int32(size << 30 | 0b111 << 27 | V << 26 | opc << 22 | 1 << 21 |                                 \
 435          addr.index()->encoding_with_zr() << 16 | addr.extend() << 13 | (addr.shift_imm() != 0) << 12 |     \
 436          0b10 << 10 | addr.base()->encoding_with_sp() << 5 | rt->encoding());                               \
 437     }                                                                                                       \
 438   }
 439 
 440   F(str_b, 0b00, 1, 0b00)
 441   F(ldr_b, 0b00, 1, 0b01)
 442   F(str_h, 0b01, 1, 0b00)
 443   F(ldr_h, 0b01, 1, 0b01)
 444   F(str_s, 0b10, 1, 0b00)
 445   F(ldr_s, 0b10, 1, 0b01)
 446   F(str_d, 0b11, 1, 0b00)
 447   F(ldr_d, 0b11, 1, 0b01)
 448   F(str_q, 0b00, 1, 0b10)
 449   F(ldr_q, 0b00, 1, 0b11)
 450 #undef F
 451 
 452 #define F(mnemonic, opc, V, L) \
 453   void mnemonic(Register rt, Register rt2, Address addr) {                                                         \
 454     assert((addr.mode() == basic_offset) || ((rt != addr.base()) && (rt2 != addr.base())), "should be different"); \
 455     assert(!L || (rt != rt2), "should be different");                                                              \
 456     assert(addr.index() == noreg, "[reg + reg] address mode is not available for load/store pair");                \
 457     int align_bits = 2 + (opc >> 1);                                                                               \
 458     int mode_encoding = (addr.mode() == basic_offset) ? 0b10 : addr.mode();                                        \
 459     assert(is_imm_in_range(addr.disp(), 7, align_bits), "offset is out of range");                                 \
 460     emit_int32(opc << 30 | 0b101 << 27 | V << 26 | mode_encoding << 23 | L << 22 |                                 \
 461        encode_imm(addr.disp(), 7, align_bits, 15) | rt2->encoding_with_zr() << 10 |                                \
 462        addr.base()->encoding_with_sp() << 5 | rt->encoding_with_zr());                                             \
 463   }
 464 
 465   F(stp_w, 0b00, 0, 0)
 466   F(ldp_w, 0b00, 0, 1)
 467   F(ldpsw, 0b01, 0, 1)
 468   F(stp,   0b10, 0, 0)
 469   F(ldp,   0b10, 0, 1)
 470 #undef F
 471 
 472 #define F(mnemonic, opc, V, L) \
 473   void mnemonic(FloatRegister rt, FloatRegister rt2, Address addr) {                                                         \
 474     assert(!L || (rt != rt2), "should be different");                                                              \
 475     assert(addr.index() == noreg, "[reg + reg] address mode is not available for load/store pair");                \
 476     int align_bits = 2 + opc;                                                                                      \
 477     int mode_encoding = (addr.mode() == basic_offset) ? 0b10 : addr.mode();                                        \
 478     assert(is_imm_in_range(addr.disp(), 7, align_bits), "offset is out of range");                                 \
 479     emit_int32(opc << 30 | 0b101 << 27 | V << 26 | mode_encoding << 23 | L << 22 |                                 \
 480        encode_imm(addr.disp(), 7, align_bits, 15) | rt2->encoding() << 10 |                                        \
 481        addr.base()->encoding_with_sp() << 5 | rt->encoding());                                                     \
 482   }
 483 
 484   F(stp_s, 0b00, 1, 0)
 485   F(ldp_s, 0b00, 1, 1)
 486   F(stp_d, 0b01, 1, 0)
 487   F(ldp_d, 0b01, 1, 1)
 488   F(stp_q, 0b10, 1, 0)
 489   F(ldp_q, 0b10, 1, 1)
 490 #undef F
 491 
 492   // Data processing instructions
 493 
 494 #define F(mnemonic, sf, opc) \
 495   void mnemonic(Register rd, Register rn, const LogicalImmediate& imm) {                      \
 496     assert (imm.is_encoded(), "illegal immediate for logical instruction");                   \
 497     assert (imm.is32bit() == (sf == 0), "immediate size does not match instruction size");    \
 498     emit_int32(sf << 31 | opc << 29 | 0b100100 << 23 | imm.immN() << 22 | imm.immr() << 16 |  \
 499         imm.imms() << 10 | rn->encoding_with_zr() << 5 |                                      \
 500         ((opc == 0b11) ? rd->encoding_with_zr() : rd->encoding_with_sp()));                   \
 501   }                                                                                           \
 502   void mnemonic(Register rd, Register rn, uintx imm) {                                        \
 503     LogicalImmediate limm(imm, (sf == 0));                                                    \
 504     mnemonic(rd, rn, limm);                                                                   \
 505   }                                                                                           \
 506   void mnemonic(Register rd, Register rn, unsigned int imm) {                                 \
 507     mnemonic(rd, rn, (uintx)imm);                                                             \
 508   }
 509 
 510   F(andr_w, 0, 0b00)
 511   F(orr_w,  0, 0b01)
 512   F(eor_w,  0, 0b10)
 513   F(ands_w, 0, 0b11)
 514 
 515   F(andr, 1, 0b00)
 516   F(orr,  1, 0b01)
 517   F(eor,  1, 0b10)
 518   F(ands, 1, 0b11)
 519 #undef F
 520 
 521   void tst(Register rn, unsigned int imm) {
 522     ands(ZR, rn, imm);
 523   }
 524 
 525   void tst_w(Register rn, unsigned int imm) {
 526     ands_w(ZR, rn, imm);
 527   }
 528 
 529 #define F(mnemonic, sf, opc, N) \
 530   void mnemonic(Register rd, Register rn, AsmOperand operand) { \
 531     assert (operand.shift_imm() >> (5 + sf) == 0, "shift amount is too large");          \
 532     emit_int32(sf << 31 | opc << 29 | 0b01010 << 24 | operand.shift() << 22 | N << 21 |  \
 533         operand.reg()->encoding_with_zr() << 16 | operand.shift_imm() << 10 |            \
 534         rn->encoding_with_zr() << 5 | rd->encoding_with_zr());                           \
 535   }
 536 
 537   F(andr_w, 0, 0b00, 0)
 538   F(bic_w,  0, 0b00, 1)
 539   F(orr_w,  0, 0b01, 0)
 540   F(orn_w,  0, 0b01, 1)
 541   F(eor_w,  0, 0b10, 0)
 542   F(eon_w,  0, 0b10, 1)
 543   F(ands_w, 0, 0b11, 0)
 544   F(bics_w, 0, 0b11, 1)
 545 
 546   F(andr, 1, 0b00, 0)
 547   F(bic,  1, 0b00, 1)
 548   F(orr,  1, 0b01, 0)
 549   F(orn,  1, 0b01, 1)
 550   F(eor,  1, 0b10, 0)
 551   F(eon,  1, 0b10, 1)
 552   F(ands, 1, 0b11, 0)
 553   F(bics, 1, 0b11, 1)
 554 #undef F
 555 
 556   void tst(Register rn, AsmOperand operand) {
 557     ands(ZR, rn, operand);
 558   }
 559 
 560   void tst_w(Register rn, AsmOperand operand) {
 561     ands_w(ZR, rn, operand);
 562   }
 563 
 564   void mvn(Register rd, AsmOperand operand) {
 565     orn(rd, ZR, operand);
 566   }
 567 
 568   void mvn_w(Register rd, AsmOperand operand) {
 569     orn_w(rd, ZR, operand);
 570   }
 571 
 572 #define F(mnemonic, sf, op, S) \
 573   void mnemonic(Register rd, Register rn, const ArithmeticImmediate& imm) {                       \
 574     assert(imm.is_encoded(), "immediate is out of range");                                        \
 575     emit_int32(sf << 31 | op << 30 | S << 29 | 0b10001 << 24 | imm.shift() << 22 |                \
 576         imm.imm() << 10 | rn->encoding_with_sp() << 5 |                                           \
 577         (S == 1 ? rd->encoding_with_zr() : rd->encoding_with_sp()));                              \
 578   }                                                                                               \
 579   void mnemonic(Register rd, Register rn, int imm) {                                              \
 580     mnemonic(rd, rn, ArithmeticImmediate(imm));                                                   \
 581   }                                                                                               \
 582   void mnemonic(Register rd, Register rn, int imm, AsmShift12 shift) {                            \
 583     mnemonic(rd, rn, ArithmeticImmediate(imm, shift));                                            \
 584   }                                                                                               \
 585   void mnemonic(Register rd, Register rn, Register rm, AsmExtendOp extend, int shift_imm = 0) {   \
 586     assert ((0 <= shift_imm) && (shift_imm <= 4), "shift amount is out of range");                \
 587     emit_int32(sf << 31 | op << 30 | S << 29 | 0b01011001 << 21 | rm->encoding_with_zr() << 16 |  \
 588         extend << 13 | shift_imm << 10 | rn->encoding_with_sp() << 5 |                            \
 589         (S == 1 ? rd->encoding_with_zr() : rd->encoding_with_sp()));                              \
 590   }                                                                                               \
 591   void mnemonic(Register rd, Register rn, AsmOperand operand) {                                   \
 592     assert (operand.shift() != ror, "illegal shift type");                                        \
 593     assert (operand.shift_imm() >> (5 + sf) == 0, "shift amount is too large");                   \
 594     emit_int32(sf << 31 | op << 30 | S << 29 | 0b01011 << 24 | operand.shift() << 22 |            \
 595         operand.reg()->encoding_with_zr() << 16 | operand.shift_imm() << 10 |                     \
 596         rn->encoding_with_zr() << 5 | rd->encoding_with_zr());                                    \
 597   }
 598 
 599   F(add_w,  0, 0, 0)
 600   F(adds_w, 0, 0, 1)
 601   F(sub_w,  0, 1, 0)
 602   F(subs_w, 0, 1, 1)
 603 
 604   F(add,    1, 0, 0)
 605   F(adds,   1, 0, 1)
 606   F(sub,    1, 1, 0)
 607   F(subs,   1, 1, 1)
 608 #undef F
 609 
 610   void mov(Register rd, Register rm) {
 611     if ((rd == SP) || (rm == SP)) {
 612       add(rd, rm, 0);
 613     } else {
 614       orr(rd, ZR, rm);
 615     }
 616   }
 617 
 618   void mov_w(Register rd, Register rm) {
 619     if ((rd == SP) || (rm == SP)) {
 620       add_w(rd, rm, 0);
 621     } else {
 622       orr_w(rd, ZR, rm);
 623     }
 624   }
 625 
 626   void cmp(Register rn, int imm) {
 627     subs(ZR, rn, imm);
 628   }
 629 
 630   void cmp_w(Register rn, int imm) {
 631     subs_w(ZR, rn, imm);
 632   }
 633 
 634   void cmp(Register rn, Register rm) {
 635     assert (rm != SP, "SP should not be used as the 2nd operand of cmp");
 636     if (rn == SP) {
 637       subs(ZR, rn, rm, ex_uxtx);
 638     } else {
 639       subs(ZR, rn, rm);
 640     }
 641   }
 642 
 643   void cmp_w(Register rn, Register rm) {
 644     assert ((rn != SP) && (rm != SP), "SP should not be used in 32-bit cmp");
 645     subs_w(ZR, rn, rm);
 646   }
 647 
 648   void cmp(Register rn, AsmOperand operand) {
 649     assert (rn != SP, "SP is not allowed in cmp with shifted register (AsmOperand)");
 650     subs(ZR, rn, operand);
 651   }
 652 
 653   void cmn(Register rn, int imm) {
 654     adds(ZR, rn, imm);
 655   }
 656 
 657   void cmn_w(Register rn, int imm) {
 658     adds_w(ZR, rn, imm);
 659   }
 660 
 661   void cmn(Register rn, Register rm) {
 662     assert (rm != SP, "SP should not be used as the 2nd operand of cmp");
 663     if (rn == SP) {
 664       adds(ZR, rn, rm, ex_uxtx);
 665     } else {
 666       adds(ZR, rn, rm);
 667     }
 668   }
 669 
 670   void cmn_w(Register rn, Register rm) {
 671     assert ((rn != SP) && (rm != SP), "SP should not be used in 32-bit cmp");
 672     adds_w(ZR, rn, rm);
 673   }
 674 
 675   void neg(Register rd, Register rm) {
 676     sub(rd, ZR, rm);
 677   }
 678 
 679   void neg_w(Register rd, Register rm) {
 680     sub_w(rd, ZR, rm);
 681   }
 682 
 683 #define F(mnemonic, sf, op, S) \
 684   void mnemonic(Register rd, Register rn, Register rm) { \
 685     emit_int32(sf << 31 | op << 30 | S << 29 | 0b11010000 << 21 | rm->encoding_with_zr() << 16 |   \
 686         rn->encoding_with_zr() << 5 | rd->encoding_with_zr());                                     \
 687   }
 688 
 689   F(adc_w,  0, 0, 0)
 690   F(adcs_w, 0, 0, 1)
 691   F(sbc_w,  0, 1, 0)
 692   F(sbcs_w, 0, 1, 1)
 693 
 694   F(adc,    1, 0, 0)
 695   F(adcs,   1, 0, 1)
 696   F(sbc,    1, 1, 0)
 697   F(sbcs,   1, 1, 1)
 698 #undef F
 699 
 700 #define F(mnemonic, sf, N) \
 701   void mnemonic(Register rd, Register rn, Register rm, int lsb) { \
 702     assert ((lsb >> (5 + sf)) == 0, "illegal least significant bit position");        \
 703     emit_int32(sf << 31 | 0b100111 << 23 | N << 22 | rm->encoding_with_zr() << 16 |   \
 704         lsb << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());            \
 705   }
 706 
 707   F(extr_w,  0, 0)
 708   F(extr,    1, 1)
 709 #undef F
 710 
 711 #define F(mnemonic, sf, opc) \
 712   void mnemonic(Register rd, int imm, int shift) { \
 713     assert ((imm >> 16) == 0, "immediate is out of range");                       \
 714     assert (((shift & 0xf) == 0) && ((shift >> (5 + sf)) == 0), "invalid shift"); \
 715     emit_int32(sf << 31 | opc << 29 | 0b100101 << 23 | (shift >> 4) << 21 |       \
 716         imm << 5 | rd->encoding_with_zr());                                       \
 717   }
 718 
 719   F(movn_w,  0, 0b00)
 720   F(movz_w,  0, 0b10)
 721   F(movk_w,  0, 0b11)
 722   F(movn,    1, 0b00)
 723   F(movz,    1, 0b10)
 724   F(movk,    1, 0b11)
 725 #undef F
 726 
 727   void mov(Register rd, int imm) {
 728     assert ((imm >> 16) == 0, "immediate is out of range");
 729     movz(rd, imm, 0);
 730   }
 731 
 732   void mov_w(Register rd, int imm) {
 733     assert ((imm >> 16) == 0, "immediate is out of range");
 734     movz_w(rd, imm, 0);
 735   }
 736 
 737 #define F(mnemonic, sf, op, S) \
 738   void mnemonic(Register rn, int imm, int nzcv, AsmCondition cond) { \
 739     assert ((imm >> 5) == 0, "immediate is out of range");                      \
 740     assert ((nzcv >> 4) == 0, "illegal nzcv");                                  \
 741     emit_int32(sf << 31 | op << 30 | S << 29 | 0b11010010 << 21 | imm << 16 |   \
 742          cond << 12 | 1 << 11 | rn->encoding_with_zr() << 5 | nzcv);            \
 743   }
 744 
 745   F(ccmn_w, 0, 0, 1)
 746   F(ccmp_w, 0, 1, 1)
 747   F(ccmn,   1, 0, 1)
 748   F(ccmp,   1, 1, 1)
 749 #undef F
 750 
 751 #define F(mnemonic, sf, op, S) \
 752   void mnemonic(Register rn, Register rm, int nzcv, AsmCondition cond) { \
 753     assert ((nzcv >> 4) == 0, "illegal nzcv");                                                    \
 754     emit_int32(sf << 31 | op << 30 | S << 29 | 0b11010010 << 21 | rm->encoding_with_zr() << 16 |  \
 755         cond << 12 | rn->encoding_with_zr() << 5 | nzcv);                                         \
 756   }
 757 
 758   F(ccmn_w, 0, 0, 1)
 759   F(ccmp_w, 0, 1, 1)
 760   F(ccmn,   1, 0, 1)
 761   F(ccmp,   1, 1, 1)
 762 #undef F
 763 
 764 #define F(mnemonic, sf, op, S, op2) \
 765   void mnemonic(Register rd, Register rn, Register rm, AsmCondition cond) { \
 766     emit_int32(sf << 31 | op << 30 | S << 29 | 0b11010100 << 21 | rm->encoding_with_zr() << 16 |  \
 767         cond << 12 | op2 << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());           \
 768   }
 769 
 770   F(csel_w,  0, 0, 0, 0b00)
 771   F(csinc_w, 0, 0, 0, 0b01)
 772   F(csinv_w, 0, 1, 0, 0b00)
 773   F(csneg_w, 0, 1, 0, 0b01)
 774 
 775   F(csel,    1, 0, 0, 0b00)
 776   F(csinc,   1, 0, 0, 0b01)
 777   F(csinv,   1, 1, 0, 0b00)
 778   F(csneg,   1, 1, 0, 0b01)
 779 #undef F
 780 
 781   void cset(Register rd, AsmCondition cond) {
 782     csinc(rd, ZR, ZR, inverse(cond));
 783   }
 784 
 785   void cset_w(Register rd, AsmCondition cond) {
 786     csinc_w(rd, ZR, ZR, inverse(cond));
 787   }
 788 
 789   void csetm(Register rd, AsmCondition cond) {
 790     csinv(rd, ZR, ZR, inverse(cond));
 791   }
 792 
 793   void csetm_w(Register rd, AsmCondition cond) {
 794     csinv_w(rd, ZR, ZR, inverse(cond));
 795   }
 796 
 797   void cinc(Register rd, Register rn, AsmCondition cond) {
 798     csinc(rd, rn, rn, inverse(cond));
 799   }
 800 
 801   void cinc_w(Register rd, Register rn, AsmCondition cond) {
 802     csinc_w(rd, rn, rn, inverse(cond));
 803   }
 804 
 805   void cinv(Register rd, Register rn, AsmCondition cond) {
 806     csinv(rd, rn, rn, inverse(cond));
 807   }
 808 
 809   void cinv_w(Register rd, Register rn, AsmCondition cond) {
 810     csinv_w(rd, rn, rn, inverse(cond));
 811   }
 812 
 813 #define F(mnemonic, sf, S, opcode) \
 814   void mnemonic(Register rd, Register rn) { \
 815     emit_int32(sf << 31 | 1 << 30 | S << 29 | 0b11010110 << 21 | opcode << 10 |  \
 816         rn->encoding_with_zr() << 5 | rd->encoding_with_zr());                   \
 817   }
 818 
 819   F(rbit_w,  0, 0, 0b000000)
 820   F(rev16_w, 0, 0, 0b000001)
 821   F(rev_w,   0, 0, 0b000010)
 822   F(clz_w,   0, 0, 0b000100)
 823   F(cls_w,   0, 0, 0b000101)
 824 
 825   F(rbit,    1, 0, 0b000000)
 826   F(rev16,   1, 0, 0b000001)
 827   F(rev32,   1, 0, 0b000010)
 828   F(rev,     1, 0, 0b000011)
 829   F(clz,     1, 0, 0b000100)
 830   F(cls,     1, 0, 0b000101)
 831 #undef F
 832 
 833 #define F(mnemonic, sf, S, opcode) \
 834   void mnemonic(Register rd, Register rn, Register rm) { \
 835     emit_int32(sf << 31 | S << 29 | 0b11010110 << 21 | rm->encoding_with_zr() << 16 |  \
 836         opcode << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());          \
 837   }
 838 
 839   F(udiv_w,  0, 0, 0b000010)
 840   F(sdiv_w,  0, 0, 0b000011)
 841   F(lslv_w,  0, 0, 0b001000)
 842   F(lsrv_w,  0, 0, 0b001001)
 843   F(asrv_w,  0, 0, 0b001010)
 844   F(rorv_w,  0, 0, 0b001011)
 845 
 846   F(udiv,    1, 0, 0b000010)
 847   F(sdiv,    1, 0, 0b000011)
 848   F(lslv,    1, 0, 0b001000)
 849   F(lsrv,    1, 0, 0b001001)
 850   F(asrv,    1, 0, 0b001010)
 851   F(rorv,    1, 0, 0b001011)
 852 #undef F
 853 
 854 #define F(mnemonic, sf, op31, o0) \
 855   void mnemonic(Register rd, Register rn, Register rm, Register ra) { \
 856     emit_int32(sf << 31 | 0b11011 << 24 | op31 << 21 | rm->encoding_with_zr() << 16 |                     \
 857         o0 << 15 | ra->encoding_with_zr() << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());  \
 858   }
 859 
 860   F(madd_w,  0, 0b000, 0)
 861   F(msub_w,  0, 0b000, 1)
 862   F(madd,    1, 0b000, 0)
 863   F(msub,    1, 0b000, 1)
 864 
 865   F(smaddl,  1, 0b001, 0)
 866   F(smsubl,  1, 0b001, 1)
 867   F(umaddl,  1, 0b101, 0)
 868   F(umsubl,  1, 0b101, 1)
 869 #undef F
 870 
 871   void mul(Register rd, Register rn, Register rm) {
 872       madd(rd, rn, rm, ZR);
 873   }
 874 
 875   void mul_w(Register rd, Register rn, Register rm) {
 876       madd_w(rd, rn, rm, ZR);
 877   }
 878 
 879 #define F(mnemonic, sf, op31, o0) \
 880   void mnemonic(Register rd, Register rn, Register rm) { \
 881     emit_int32(sf << 31 | 0b11011 << 24 | op31 << 21 | rm->encoding_with_zr() << 16 |      \
 882         o0 << 15 | 0b11111 << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());  \
 883   }
 884 
 885   F(smulh,   1, 0b010, 0)
 886   F(umulh,   1, 0b110, 0)
 887 #undef F
 888 
 889 #define F(mnemonic, op) \
 890   void mnemonic(Register rd, address addr) { \
 891     intx offset;                                                        \
 892     if (op == 0) {                                                      \
 893       offset = addr - pc();                                             \
 894     } else {                                                            \
 895       offset = (((intx)addr) - (((intx)pc()) & ~0xfff)) >> 12;          \
 896     }                                                                   \
 897     assert (is_imm_in_range(offset, 21, 0), "offset is out of range");  \
 898     emit_int32(op << 31 | (offset & 3) << 29 | 0b10000 << 24 |          \
 899         encode_imm(offset >> 2, 19, 0, 5) | rd->encoding_with_zr());    \
 900   }                                                                     \
 901 
 902   F(adr,   0)
 903   F(adrp,  1)
 904 #undef F
 905 
 906   void adr(Register rd, Label& L) {
 907     adr(rd, target(L));
 908   }
 909 
 910 #define F(mnemonic, sf, opc, N)                                                \
 911   void mnemonic(Register rd, Register rn, int immr, int imms) {                \
 912     assert ((immr >> (5 + sf)) == 0, "immr is out of range");                  \
 913     assert ((imms >> (5 + sf)) == 0, "imms is out of range");                  \
 914     emit_int32(sf << 31 | opc << 29 | 0b100110 << 23 | N << 22 | immr << 16 |  \
 915         imms << 10 | rn->encoding_with_zr() << 5 | rd->encoding_with_zr());    \
 916   }
 917 
 918   F(sbfm_w, 0, 0b00, 0)
 919   F(bfm_w,  0, 0b01, 0)
 920   F(ubfm_w, 0, 0b10, 0)
 921 
 922   F(sbfm, 1, 0b00, 1)
 923   F(bfm,  1, 0b01, 1)
 924   F(ubfm, 1, 0b10, 1)
 925 #undef F
 926 
 927 #define F(alias, mnemonic, sf, immr, imms) \
 928   void alias(Register rd, Register rn, int lsb, int width) {                        \
 929     assert ((lsb >> (5 + sf)) == 0, "lsb is out of range");                         \
 930     assert ((1 <= width) && (width <= (32 << sf) - lsb), "width is out of range");  \
 931     mnemonic(rd, rn, immr, imms);                                                   \
 932   }
 933 
 934   F(bfi_w,   bfm_w,  0, (-lsb) & 0x1f, width - 1)
 935   F(bfi,     bfm,    1, (-lsb) & 0x3f, width - 1)
 936   F(bfxil_w, bfm_w,  0, lsb,           lsb + width - 1)
 937   F(bfxil,   bfm,    1, lsb,           lsb + width - 1)
 938   F(sbfiz_w, sbfm_w, 0, (-lsb) & 0x1f, width - 1)
 939   F(sbfiz,   sbfm,   1, (-lsb) & 0x3f, width - 1)
 940   F(sbfx_w,  sbfm_w, 0, lsb,           lsb + width - 1)
 941   F(sbfx,    sbfm,   1, lsb,           lsb + width - 1)
 942   F(ubfiz_w, ubfm_w, 0, (-lsb) & 0x1f, width - 1)
 943   F(ubfiz,   ubfm,   1, (-lsb) & 0x3f, width - 1)
 944   F(ubfx_w,  ubfm_w, 0, lsb,           lsb + width - 1)
 945   F(ubfx,    ubfm,   1, lsb,           lsb + width - 1)
 946 #undef F
 947 
 948 #define F(alias, mnemonic, sf, immr, imms) \
 949   void alias(Register rd, Register rn, int shift) {              \
 950     assert ((shift >> (5 + sf)) == 0, "shift is out of range");  \
 951     mnemonic(rd, rn, immr, imms);                                \
 952   }
 953 
 954   F(_asr_w, sbfm_w, 0, shift, 31)
 955   F(_asr,   sbfm,   1, shift, 63)
 956   F(_lsl_w, ubfm_w, 0, (-shift) & 0x1f, 31 - shift)
 957   F(_lsl,   ubfm,   1, (-shift) & 0x3f, 63 - shift)
 958   F(_lsr_w, ubfm_w, 0, shift, 31)
 959   F(_lsr,   ubfm,   1, shift, 63)
 960 #undef F
 961 
 962 #define F(alias, mnemonic, immr, imms) \
 963   void alias(Register rd, Register rn) {   \
 964     mnemonic(rd, rn, immr, imms);          \
 965   }
 966 
 967   F(sxtb_w, sbfm_w, 0, 7)
 968   F(sxtb,   sbfm,   0, 7)
 969   F(sxth_w, sbfm_w, 0, 15)
 970   F(sxth,   sbfm,   0, 15)
 971   F(sxtw,   sbfm,   0, 31)
 972   F(uxtb_w, ubfm_w, 0, 7)
 973   F(uxtb,   ubfm,   0, 7)
 974   F(uxth_w, ubfm_w, 0, 15)
 975   F(uxth,   ubfm,   0, 15)
 976 #undef F
 977 
 978   // Branch instructions
 979 
 980 #define F(mnemonic, op) \
 981   void mnemonic(Register rn) {                                                             \
 982     emit_int32(0b1101011 << 25 | op << 21 | 0b11111 << 16 | rn->encoding_with_zr() << 5);  \
 983   }
 984 
 985   F(br,  0b00)
 986   F(blr, 0b01)
 987   F(ret, 0b10)
 988 #undef F
 989 
 990   void ret() {
 991     ret(LR);
 992   }
 993 
 994 #define F(mnemonic, op) \
 995   void mnemonic(address target) {                                         \
 996     intx offset = target - pc();                                          \
 997     assert (is_offset_in_range(offset, 26), "offset is out of range");    \
 998     emit_int32(op << 31 | 0b00101 << 26 | encode_offset(offset, 26, 0));  \
 999   }
1000 
1001   F(b,  0)
1002   F(bl, 1)
1003 #undef F
1004 
1005   void b(address target, AsmCondition cond) {
1006     if (cond == al) {
1007       b(target);
1008     } else {
1009       intx offset = target - pc();
1010       assert (is_offset_in_range(offset, 19), "offset is out of range");
1011       emit_int32(0b0101010 << 25 | encode_offset(offset, 19, 5) | cond);
1012     }
1013   }
1014 
1015 
1016 #define F(mnemonic, sf, op)                                             \
1017   void mnemonic(Register rt, address target) {                          \
1018     intx offset = target - pc();                                        \
1019     assert (is_offset_in_range(offset, 19), "offset is out of range");  \
1020     emit_int32(sf << 31 | 0b011010 << 25 | op << 24 | encode_offset(offset, 19, 5) | rt->encoding_with_zr()); \
1021   }                                                                     \
1022 
1023   F(cbz_w,  0, 0)
1024   F(cbnz_w, 0, 1)
1025   F(cbz,    1, 0)
1026   F(cbnz,   1, 1)
1027 #undef F
1028 
1029 #define F(mnemonic, op)                                                 \
1030   void mnemonic(Register rt, int bit, address target) {                 \
1031     intx offset = target - pc();                                        \
1032     assert (is_offset_in_range(offset, 14), "offset is out of range");  \
1033     assert (0 <= bit && bit < 64, "bit number is out of range");        \
1034     emit_int32((bit >> 5) << 31 | 0b011011 << 25 | op << 24 | (bit & 0x1f) << 19 | \
1035         encode_offset(offset, 14, 5) | rt->encoding_with_zr());         \
1036   }                                                                     \
1037 
1038   F(tbz,  0)
1039   F(tbnz, 1)
1040 #undef F
1041 
1042   // System instructions
1043 
1044   enum DMB_Opt {
1045     DMB_ld  = 0b1101,
1046     DMB_st  = 0b1110,
1047     DMB_all = 0b1111
1048   };
1049 
1050 #define F(mnemonic, L, op0, op1, CRn, op2, Rt) \
1051   void mnemonic(DMB_Opt option) {                                       \
1052     emit_int32(0b1101010100 << 22 | L << 21 | op0 << 19 | op1 << 16 |   \
1053         CRn << 12 | option << 8 | op2 << 5 | Rt);                       \
1054   }
1055 
1056   F(dsb,  0, 0b00, 0b011, 0b0011, 0b100, 0b11111)
1057   F(dmb,  0, 0b00, 0b011, 0b0011, 0b101, 0b11111)
1058 #undef F
1059 
1060 #define F(mnemonic, L, op0, op1, CRn, Rt) \
1061   void mnemonic(int imm) {                                              \
1062     assert ((imm >> 7) == 0, "immediate is out of range");              \
1063     emit_int32(0b1101010100 << 22 | L << 21 | op0 << 19 | op1 << 16 |   \
1064         CRn << 12 | imm << 5 | Rt);                                     \
1065   }
1066 
1067   F(hint, 0, 0b00, 0b011, 0b0010, 0b11111)
1068 #undef F
1069 
1070   void nop() {
1071     hint(0);
1072   }
1073 
1074   void yield() {
1075     hint(1);
1076   }
1077 
1078 #define F(mnemonic, opc, op2, LL) \
1079   void mnemonic(int imm = 0) {                                           \
1080     assert ((imm >> 16) == 0, "immediate is out of range");              \
1081     emit_int32(0b11010100 << 24 | opc << 21 | imm << 5 | op2 << 2 | LL); \
1082   }
1083 
1084   F(brk, 0b001, 0b000, 0b00)
1085   F(hlt, 0b010, 0b000, 0b00)
1086 #undef F
1087 
1088   enum SystemRegister { // o0<1> op1<3> CRn<4> CRm<4> op2<3>
1089     SysReg_NZCV = 0b101101000010000,
1090     SysReg_FPCR = 0b101101000100000,
1091   };
1092 
1093   void mrs(Register rt, SystemRegister systemReg) {
1094     assert ((systemReg >> 15) == 0, "systemReg is out of range");
1095     emit_int32(0b110101010011 << 20 | systemReg << 5 | rt->encoding_with_zr());
1096   }
1097 
1098   void msr(SystemRegister systemReg, Register rt) {
1099     assert ((systemReg >> 15) == 0, "systemReg is out of range");
1100     emit_int32(0b110101010001 << 20 | systemReg << 5 | rt->encoding_with_zr());
1101   }
1102 
1103   // Floating-point instructions
1104 
1105 #define F(mnemonic, M, S, type, opcode2) \
1106   void mnemonic(FloatRegister rn, FloatRegister rm) {                         \
1107     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |     \
1108         rm->encoding() << 16 | 0b1000 << 10 | rn->encoding() << 5 | opcode2); \
1109   }
1110 
1111   F(fcmp_s,   0, 0, 0b00, 0b00000)
1112   F(fcmpe_s,  0, 0, 0b00, 0b01000)
1113   F(fcmp_d,   0, 0, 0b01, 0b00000)
1114   F(fcmpe_d,  0, 0, 0b01, 0b10000)
1115 #undef F
1116 
1117 #define F(mnemonic, M, S, type, opcode2) \
1118   void mnemonic(FloatRegister rn) {                                           \
1119     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |     \
1120         0b1000 << 10 | rn->encoding() << 5 | opcode2);                        \
1121   }
1122 
1123   F(fcmp0_s,   0, 0, 0b00, 0b01000)
1124   F(fcmpe0_s,  0, 0, 0b00, 0b11000)
1125   F(fcmp0_d,   0, 0, 0b01, 0b01000)
1126   F(fcmpe0_d,  0, 0, 0b01, 0b11000)
1127 #undef F
1128 
1129 #define F(mnemonic, M, S, type, op) \
1130   void mnemonic(FloatRegister rn, FloatRegister rm, int nzcv, AsmCondition cond) { \
1131     assert ((nzcv >> 4) == 0, "illegal nzcv");                                                  \
1132     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                       \
1133         rm->encoding() << 16 | cond << 12 | 0b01 << 10 | rn->encoding() << 5 | op << 4 | nzcv); \
1134   }
1135 
1136   F(fccmp_s,   0, 0, 0b00, 0)
1137   F(fccmpe_s,  0, 0, 0b00, 1)
1138   F(fccmp_d,   0, 0, 0b01, 0)
1139   F(fccmpe_d,  0, 0, 0b01, 1)
1140 #undef F
1141 
1142 #define F(mnemonic, M, S, type) \
1143   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm, AsmCondition cond) { \
1144     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                       \
1145         rm->encoding() << 16 | cond << 12 | 0b11 << 10 | rn->encoding() << 5 | rd->encoding()); \
1146   }
1147 
1148   F(fcsel_s,   0, 0, 0b00)
1149   F(fcsel_d,   0, 0, 0b01)
1150 #undef F
1151 
1152 #define F(mnemonic, M, S, type, opcode) \
1153   void mnemonic(FloatRegister rd, FloatRegister rn) { \
1154     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |      \
1155         opcode << 15 | 0b10000 << 10 | rn->encoding() << 5 | rd->encoding());  \
1156   }
1157 
1158   F(fmov_s,   0, 0, 0b00, 0b000000)
1159   F(fabs_s,   0, 0, 0b00, 0b000001)
1160   F(fneg_s,   0, 0, 0b00, 0b000010)
1161   F(fsqrt_s,  0, 0, 0b00, 0b000011)
1162   F(fcvt_ds,  0, 0, 0b00, 0b000101)
1163   F(fcvt_hs,  0, 0, 0b00, 0b000111)
1164   F(frintn_s, 0, 0, 0b00, 0b001000)
1165   F(frintp_s, 0, 0, 0b00, 0b001001)
1166   F(frintm_s, 0, 0, 0b00, 0b001010)
1167   F(frintz_s, 0, 0, 0b00, 0b001011)
1168   F(frinta_s, 0, 0, 0b00, 0b001100)
1169   F(frintx_s, 0, 0, 0b00, 0b001110)
1170   F(frinti_s, 0, 0, 0b00, 0b001111)
1171 
1172   F(fmov_d,   0, 0, 0b01, 0b000000)
1173   F(fabs_d,   0, 0, 0b01, 0b000001)
1174   F(fneg_d,   0, 0, 0b01, 0b000010)
1175   F(fsqrt_d,  0, 0, 0b01, 0b000011)
1176   F(fcvt_sd,  0, 0, 0b01, 0b000100)
1177   F(fcvt_hd,  0, 0, 0b01, 0b000111)
1178   F(frintn_d, 0, 0, 0b01, 0b001000)
1179   F(frintp_d, 0, 0, 0b01, 0b001001)
1180   F(frintm_d, 0, 0, 0b01, 0b001010)
1181   F(frintz_d, 0, 0, 0b01, 0b001011)
1182   F(frinta_d, 0, 0, 0b01, 0b001100)
1183   F(frintx_d, 0, 0, 0b01, 0b001110)
1184   F(frinti_d, 0, 0, 0b01, 0b001111)
1185 
1186   F(fcvt_sh,  0, 0, 0b11, 0b000100)
1187   F(fcvt_dh,  0, 0, 0b11, 0b000101)
1188 #undef F
1189 
1190 #define F(mnemonic, M, S, type, opcode) \
1191   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm) { \
1192     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                          \
1193         rm->encoding() << 16 | opcode << 12 | 0b10 << 10 | rn->encoding() << 5 | rd->encoding());  \
1194   }
1195 
1196   F(fmul_s,   0, 0, 0b00, 0b0000)
1197   F(fdiv_s,   0, 0, 0b00, 0b0001)
1198   F(fadd_s,   0, 0, 0b00, 0b0010)
1199   F(fsub_s,   0, 0, 0b00, 0b0011)
1200   F(fmax_s,   0, 0, 0b00, 0b0100)
1201   F(fmin_s,   0, 0, 0b00, 0b0101)
1202   F(fmaxnm_s, 0, 0, 0b00, 0b0110)
1203   F(fminnm_s, 0, 0, 0b00, 0b0111)
1204   F(fnmul_s,  0, 0, 0b00, 0b1000)
1205 
1206   F(fmul_d,   0, 0, 0b01, 0b0000)
1207   F(fdiv_d,   0, 0, 0b01, 0b0001)
1208   F(fadd_d,   0, 0, 0b01, 0b0010)
1209   F(fsub_d,   0, 0, 0b01, 0b0011)
1210   F(fmax_d,   0, 0, 0b01, 0b0100)
1211   F(fmin_d,   0, 0, 0b01, 0b0101)
1212   F(fmaxnm_d, 0, 0, 0b01, 0b0110)
1213   F(fminnm_d, 0, 0, 0b01, 0b0111)
1214   F(fnmul_d,  0, 0, 0b01, 0b1000)
1215 #undef F
1216 
1217 #define F(mnemonic, M, S, type, o1, o0) \
1218   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm, FloatRegister ra) { \
1219     emit_int32(M << 31 | S << 29 | 0b11111 << 24 | type << 22 | o1 << 21 | rm->encoding() << 16 |  \
1220          o0 << 15 | ra->encoding() << 10 | rn->encoding() << 5 | rd->encoding());                  \
1221   }
1222 
1223   F(fmadd_s,  0, 0, 0b00, 0, 0)
1224   F(fmsub_s,  0, 0, 0b00, 0, 1)
1225   F(fnmadd_s, 0, 0, 0b00, 1, 0)
1226   F(fnmsub_s, 0, 0, 0b00, 1, 1)
1227 
1228   F(fmadd_d,  0, 0, 0b01, 0, 0)
1229   F(fmsub_d,  0, 0, 0b01, 0, 1)
1230   F(fnmadd_d, 0, 0, 0b01, 1, 0)
1231   F(fnmsub_d, 0, 0, 0b01, 1, 1)
1232 #undef F
1233 
1234 #define F(mnemonic, M, S, type) \
1235   void mnemonic(FloatRegister rd, int imm8) { \
1236     assert ((imm8 >> 8) == 0, "immediate is out of range");                \
1237     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |  \
1238          imm8 << 13 | 0b100 << 10 | rd->encoding());                       \
1239   }
1240 
1241   F(fmov_s, 0, 0, 0b00)
1242   F(fmov_d, 0, 0, 0b01)
1243 #undef F
1244 
1245 #define F(mnemonic, sf, S, type, rmode, opcode) \
1246   void mnemonic(Register rd, FloatRegister rn) {                                     \
1247     emit_int32(sf << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |           \
1248          rmode << 19 | opcode << 16 | rn->encoding() << 5 | rd->encoding_with_zr()); \
1249   }
1250 
1251   F(fcvtns_ws, 0, 0, 0b00, 0b00, 0b000)
1252   F(fcvtnu_ws, 0, 0, 0b00, 0b00, 0b001)
1253   F(fcvtas_ws, 0, 0, 0b00, 0b00, 0b100)
1254   F(fcvtau_ws, 0, 0, 0b00, 0b00, 0b101)
1255   F(fmov_ws,   0, 0, 0b00, 0b00, 0b110)
1256   F(fcvtps_ws, 0, 0, 0b00, 0b01, 0b000)
1257   F(fcvtpu_ws, 0, 0, 0b00, 0b01, 0b001)
1258   F(fcvtms_ws, 0, 0, 0b00, 0b10, 0b000)
1259   F(fcvtmu_ws, 0, 0, 0b00, 0b10, 0b001)
1260   F(fcvtzs_ws, 0, 0, 0b00, 0b11, 0b000)
1261   F(fcvtzu_ws, 0, 0, 0b00, 0b11, 0b001)
1262 
1263   F(fcvtns_wd, 0, 0, 0b01, 0b00, 0b000)
1264   F(fcvtnu_wd, 0, 0, 0b01, 0b00, 0b001)
1265   F(fcvtas_wd, 0, 0, 0b01, 0b00, 0b100)
1266   F(fcvtau_wd, 0, 0, 0b01, 0b00, 0b101)
1267   F(fcvtps_wd, 0, 0, 0b01, 0b01, 0b000)
1268   F(fcvtpu_wd, 0, 0, 0b01, 0b01, 0b001)
1269   F(fcvtms_wd, 0, 0, 0b01, 0b10, 0b000)
1270   F(fcvtmu_wd, 0, 0, 0b01, 0b10, 0b001)
1271   F(fcvtzs_wd, 0, 0, 0b01, 0b11, 0b000)
1272   F(fcvtzu_wd, 0, 0, 0b01, 0b11, 0b001)
1273 
1274   F(fcvtns_xs, 1, 0, 0b00, 0b00, 0b000)
1275   F(fcvtnu_xs, 1, 0, 0b00, 0b00, 0b001)
1276   F(fcvtas_xs, 1, 0, 0b00, 0b00, 0b100)
1277   F(fcvtau_xs, 1, 0, 0b00, 0b00, 0b101)
1278   F(fcvtps_xs, 1, 0, 0b00, 0b01, 0b000)
1279   F(fcvtpu_xs, 1, 0, 0b00, 0b01, 0b001)
1280   F(fcvtms_xs, 1, 0, 0b00, 0b10, 0b000)
1281   F(fcvtmu_xs, 1, 0, 0b00, 0b10, 0b001)
1282   F(fcvtzs_xs, 1, 0, 0b00, 0b11, 0b000)
1283   F(fcvtzu_xs, 1, 0, 0b00, 0b11, 0b001)
1284 
1285   F(fcvtns_xd, 1, 0, 0b01, 0b00, 0b000)
1286   F(fcvtnu_xd, 1, 0, 0b01, 0b00, 0b001)
1287   F(fcvtas_xd, 1, 0, 0b01, 0b00, 0b100)
1288   F(fcvtau_xd, 1, 0, 0b01, 0b00, 0b101)
1289   F(fmov_xd,   1, 0, 0b01, 0b00, 0b110)
1290   F(fcvtps_xd, 1, 0, 0b01, 0b01, 0b000)
1291   F(fcvtpu_xd, 1, 0, 0b01, 0b01, 0b001)
1292   F(fcvtms_xd, 1, 0, 0b01, 0b10, 0b000)
1293   F(fcvtmu_xd, 1, 0, 0b01, 0b10, 0b001)
1294   F(fcvtzs_xd, 1, 0, 0b01, 0b11, 0b000)
1295   F(fcvtzu_xd, 1, 0, 0b01, 0b11, 0b001)
1296 
1297   F(fmov_xq,   1, 0, 0b10, 0b01, 0b110)
1298 #undef F
1299 
1300 #define F(mnemonic, sf, S, type, rmode, opcode) \
1301   void mnemonic(FloatRegister rd, Register rn) {                                     \
1302     emit_int32(sf << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |           \
1303          rmode << 19 | opcode << 16 | rn->encoding_with_zr() << 5 | rd->encoding()); \
1304   }
1305 
1306   F(scvtf_sw,  0, 0, 0b00, 0b00, 0b010)
1307   F(ucvtf_sw,  0, 0, 0b00, 0b00, 0b011)
1308   F(fmov_sw,   0, 0, 0b00, 0b00, 0b111)
1309   F(scvtf_dw,  0, 0, 0b01, 0b00, 0b010)
1310   F(ucvtf_dw,  0, 0, 0b01, 0b00, 0b011)
1311 
1312   F(scvtf_sx,  1, 0, 0b00, 0b00, 0b010)
1313   F(ucvtf_sx,  1, 0, 0b00, 0b00, 0b011)
1314   F(scvtf_dx,  1, 0, 0b01, 0b00, 0b010)
1315   F(ucvtf_dx,  1, 0, 0b01, 0b00, 0b011)
1316   F(fmov_dx,   1, 0, 0b01, 0b00, 0b111)
1317 
1318   F(fmov_qx,   1, 0, 0b10, 0b01, 0b111)
1319 #undef F
1320 
1321 #define F(mnemonic, opcode) \
1322   void mnemonic(FloatRegister Vd, FloatRegister Vn) {                                     \
1323     emit_int32( opcode << 10 | Vn->encoding() << 5 | Vd->encoding());             \
1324   }
1325 
1326   F(aese, 0b0100111000101000010010);
1327   F(aesd, 0b0100111000101000010110);
1328   F(aesmc, 0b0100111000101000011010);
1329   F(aesimc, 0b0100111000101000011110);
1330 #undef F
1331 
1332 #ifdef COMPILER2
1333   typedef VFP::double_num double_num;
1334   typedef VFP::float_num  float_num;
1335 #endif
1336 
1337   void vcnt(FloatRegister Dd, FloatRegister Dn, int quad = 0, int size = 0) {
1338     // emitted at VM startup to detect whether the instruction is available
1339     assert(!VM_Version::is_initialized() || VM_Version::has_simd(), "simd instruction");
1340     assert(size == 0, "illegal size value");
1341     emit_int32(0x0e205800 | quad << 30 | size << 22 | Dn->encoding() << 5 | Dd->encoding());
1342   }
1343 
1344 #ifdef COMPILER2
1345   void addv(FloatRegister Dd, FloatRegister Dm, int quad, int size) {
1346     // emitted at VM startup to detect whether the instruction is available
1347     assert(VM_Version::has_simd(), "simd instruction");
1348     assert((quad & ~1) == 0, "illegal value");
1349     assert(size >= 0 && size < 3, "illegal value");
1350     assert(((size << 1) | quad) != 4, "illegal values (size 2, quad 0)");
1351     emit_int32(0x0e31b800 | quad << 30 | size << 22 | Dm->encoding() << 5 | Dd->encoding());
1352   }
1353 
1354   enum VElem_Size {
1355     VELEM_SIZE_8  = 0x00,
1356     VELEM_SIZE_16 = 0x01,
1357     VELEM_SIZE_32 = 0x02,
1358     VELEM_SIZE_64 = 0x03
1359   };
1360 
1361   enum VLD_Type {
1362     VLD1_TYPE_1_REG  = 0b0111,
1363     VLD1_TYPE_2_REGS = 0b1010,
1364     VLD1_TYPE_3_REGS = 0b0110,
1365     VLD1_TYPE_4_REGS = 0b0010
1366   };
1367 
1368   enum VFloat_Arith_Size {
1369     VFA_SIZE_F32 = 0b0,
1370     VFA_SIZE_F64 = 0b1
1371   };
1372 
1373 #define F(mnemonic, U, S, P) \
1374   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1375                 int size, int quad) {                                    \
1376     assert(VM_Version::has_simd(), "simd instruction");                  \
1377     assert(!(size == VFA_SIZE_F64 && !quad), "reserved");                \
1378     assert((size & 1) == size, "overflow");                              \
1379     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 |                    \
1380                S << 23 | size << 22 | 1 << 21 | P << 11 | 1 << 10 |      \
1381                fm->encoding() << 16 |                                    \
1382                fn->encoding() <<  5 |                                    \
1383                fd->encoding());                                          \
1384   }
1385 
1386   F(vaddF, 0, 0, 0b11010)  // Vd = Vn + Vm (float)
1387   F(vsubF, 0, 1, 0b11010)  // Vd = Vn - Vm (float)
1388   F(vmulF, 1, 0, 0b11011)  // Vd = Vn - Vm (float)
1389   F(vdivF, 1, 0, 0b11111)  // Vd = Vn / Vm (float)
1390 #undef F
1391 
1392 #define F(mnemonic, U) \
1393   void mnemonic(FloatRegister fd, FloatRegister fm, FloatRegister fn,    \
1394                 int size, int quad) {                                    \
1395     assert(VM_Version::has_simd(), "simd instruction");                  \
1396     assert(!(size == VELEM_SIZE_64 && !quad), "reserved");               \
1397     assert((size & 0b11) == size, "overflow");                           \
1398     int R = 0; /* rounding */                                            \
1399     int S = 0; /* saturating */                                          \
1400     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | size << 22 |       \
1401                1 << 21 | R << 12 | S << 11 | 0b10001 << 10 |             \
1402                fm->encoding() << 16 |                                    \
1403                fn->encoding() <<  5 |                                    \
1404                fd->encoding());                                          \
1405   }
1406 
1407   F(vshlSI, 0)  // Vd = ashift(Vn,Vm) (int)
1408   F(vshlUI, 1)  // Vd = lshift(Vn,Vm) (int)
1409 #undef F
1410 
1411 #define F(mnemonic, U, P, M) \
1412   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1413                 int size, int quad) {                                    \
1414     assert(VM_Version::has_simd(), "simd instruction");                  \
1415     assert(!(size == VELEM_SIZE_64 && !quad), "reserved");               \
1416     assert(!(size == VELEM_SIZE_64 && M), "reserved");                   \
1417     assert((size & 0b11) == size, "overflow");                           \
1418     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | size << 22 |       \
1419                1 << 21 | P << 11 | 1 << 10 |                             \
1420                fm->encoding() << 16 |                                    \
1421                fn->encoding() <<  5 |                                    \
1422                fd->encoding());                                          \
1423   }
1424 
1425   F(vmulI, 0, 0b10011,  true)  // Vd = Vn * Vm (int)
1426   F(vaddI, 0, 0b10000, false)  // Vd = Vn + Vm (int)
1427   F(vsubI, 1, 0b10000, false)  // Vd = Vn - Vm (int)
1428 #undef F
1429 
1430 #define F(mnemonic, U, O) \
1431   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1432                 int quad) {                                              \
1433     assert(VM_Version::has_simd(), "simd instruction");                  \
1434     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | O << 22 |          \
1435                1 << 21 | 0b00011 << 11 | 1 << 10 |                       \
1436                fm->encoding() << 16 |                                    \
1437                fn->encoding() <<  5 |                                    \
1438                fd->encoding());                                          \
1439   }
1440 
1441   F(vandI, 0, 0b00)  // Vd = Vn & Vm (int)
1442   F(vorI,  0, 0b10)  // Vd = Vn | Vm (int)
1443   F(vxorI, 1, 0b00)  // Vd = Vn ^ Vm (int)
1444 #undef F
1445 
1446   void vnegI(FloatRegister fd, FloatRegister fn, int size, int quad) {
1447     int U = 1;
1448     assert(VM_Version::has_simd(), "simd instruction");
1449     assert(quad || size != VELEM_SIZE_64, "reserved");
1450     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 |
1451               size << 22 | 0b100000101110 << 10 |
1452               fn->encoding() << 5 |
1453               fd->encoding() << 0);
1454   }
1455 
1456   void vshli(FloatRegister fd, FloatRegister fn, int esize, int imm, int quad) {
1457     assert(VM_Version::has_simd(), "simd instruction");
1458 
1459     if (imm >= esize) {
1460       // maximum shift gives all zeroes, direction doesn't matter,
1461       // but only available for shift right
1462       vshri(fd, fn, esize, esize, true /* unsigned */, quad);
1463       return;
1464     }
1465     assert(imm >= 0 && imm < esize, "out of range");
1466 
1467     int imm7 = esize + imm;
1468     int immh = imm7 >> 3;
1469     assert(immh != 0, "encoding constraint");
1470     assert((uint)immh < 16, "sanity");
1471     assert(((immh >> 2) | quad) != 0b10, "reserved");
1472     emit_int32(quad << 30 | 0b011110 << 23 | imm7 << 16 |
1473                0b010101 << 10 | fn->encoding() << 5 | fd->encoding() << 0);
1474   }
1475 
1476   void vshri(FloatRegister fd, FloatRegister fn, int esize, int imm,
1477              bool U /* unsigned */, int quad) {
1478     assert(VM_Version::has_simd(), "simd instruction");
1479     assert(imm > 0, "out of range");
1480     if (imm >= esize) {
1481       // maximum shift (all zeroes)
1482       imm = esize;
1483     }
1484     int imm7 = 2 * esize - imm ;
1485     int immh = imm7 >> 3;
1486     assert(immh != 0, "encoding constraint");
1487     assert((uint)immh < 16, "sanity");
1488     assert(((immh >> 2) | quad) != 0b10, "reserved");
1489     emit_int32(quad << 30 | U << 29 | 0b011110 << 23 | imm7 << 16 |
1490                0b000001 << 10 | fn->encoding() << 5 | fd->encoding() << 0);
1491   }
1492   void vshrUI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {
1493     vshri(fd, fm, size, imm, true /* unsigned */, quad);
1494   }
1495   void vshrSI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {
1496     vshri(fd, fm, size, imm, false /* signed */, quad);
1497   }
1498 
1499   void vld1(FloatRegister Vt, Address addr, VElem_Size size, int bits) {
1500     assert(VM_Version::has_simd(), "simd instruction");
1501     assert(bits == 128, "unsupported");
1502     assert(addr.disp() == 0 || addr.disp() == 16, "must be");
1503     int type = 0b11; // 2D
1504     int quad = 1;
1505     int L = 1;
1506     int opcode = VLD1_TYPE_1_REG;
1507     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1508                Vt->encoding() << 0 | addr.encoding_simd());
1509   }
1510 
1511   void vst1(FloatRegister Vt, Address addr, VElem_Size size, int bits) {
1512     assert(VM_Version::has_simd(), "simd instruction");
1513     assert(bits == 128, "unsupported");
1514     assert(addr.disp() == 0 || addr.disp() == 16, "must be");
1515     int type = 0b11; // 2D
1516     int quad = 1;
1517     int L = 0;
1518     int opcode = VLD1_TYPE_1_REG;
1519     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1520                Vt->encoding() << 0 | addr.encoding_simd());
1521   }
1522 
1523   void vld1(FloatRegister Vt, FloatRegister Vt2, Address addr, VElem_Size size, int bits) {
1524     assert(VM_Version::has_simd(), "simd instruction");
1525     assert(bits == 128, "unsupported");
1526     assert(Vt->successor() == Vt2, "Registers must be ordered");
1527     assert(addr.disp() == 0 || addr.disp() == 32, "must be");
1528     int type = 0b11; // 2D
1529     int quad = 1;
1530     int L = 1;
1531     int opcode = VLD1_TYPE_2_REGS;
1532     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1533                Vt->encoding() << 0 | addr.encoding_simd());
1534   }
1535 
1536   void vst1(FloatRegister Vt, FloatRegister Vt2, Address addr, VElem_Size size, int bits) {
1537     assert(VM_Version::has_simd(), "simd instruction");
1538     assert(Vt->successor() == Vt2, "Registers must be ordered");
1539     assert(bits == 128, "unsupported");
1540     assert(addr.disp() == 0 || addr.disp() == 32, "must be");
1541     int type = 0b11; // 2D
1542     int quad = 1;
1543     int L = 0;
1544     int opcode = VLD1_TYPE_2_REGS;
1545     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1546                Vt->encoding() << 0 | addr.encoding_simd());
1547   }
1548 
1549   void vld1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1550             Address addr, VElem_Size size, int bits) {
1551     assert(VM_Version::has_simd(), "simd instruction");
1552     assert(bits == 128, "unsupported");
1553     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3,
1554           "Registers must be ordered");
1555     assert(addr.disp() == 0 || addr.disp() == 48, "must be");
1556     int type = 0b11; // 2D
1557     int quad = 1;
1558     int L = 1;
1559     int opcode = VLD1_TYPE_3_REGS;
1560     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1561                Vt->encoding() << 0 | addr.encoding_simd());
1562   }
1563 
1564   void vst1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1565             Address addr, VElem_Size size, int bits) {
1566     assert(VM_Version::has_simd(), "simd instruction");
1567     assert(bits == 128, "unsupported");
1568     assert(Vt->successor() == Vt2 &&  Vt2->successor() == Vt3,
1569            "Registers must be ordered");
1570     assert(addr.disp() == 0 || addr.disp() == 48, "must be");
1571     int type = 0b11; // 2D
1572     int quad = 1;
1573     int L = 0;
1574     int opcode = VLD1_TYPE_3_REGS;
1575     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1576                Vt->encoding() << 0 | addr.encoding_simd());
1577   }
1578 
1579   void vld1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1580             FloatRegister Vt4, Address addr, VElem_Size size, int bits) {
1581     assert(VM_Version::has_simd(), "simd instruction");
1582     assert(bits == 128, "unsupported");
1583     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 &&
1584            Vt3->successor() == Vt4, "Registers must be ordered");
1585     assert(addr.disp() == 0 || addr.disp() == 64, "must be");
1586     int type = 0b11; // 2D
1587     int quad = 1;
1588     int L = 1;
1589     int opcode = VLD1_TYPE_4_REGS;
1590     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1591                Vt->encoding() << 0 | addr.encoding_simd());
1592   }
1593 
1594   void vst1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1595             FloatRegister Vt4,  Address addr, VElem_Size size, int bits) {
1596     assert(VM_Version::has_simd(), "simd instruction");
1597     assert(bits == 128, "unsupported");
1598     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 &&
1599            Vt3->successor() == Vt4, "Registers must be ordered");
1600     assert(addr.disp() == 0 || addr.disp() == 64, "must be");
1601     int type = 0b11; // 2D
1602     int quad = 1;
1603     int L = 0;
1604     int opcode = VLD1_TYPE_4_REGS;
1605     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1606                Vt->encoding() << 0 | addr.encoding_simd());
1607   }
1608 
1609   void rev32(FloatRegister Vd, FloatRegister Vn, VElem_Size size, int quad) {
1610     assert(VM_Version::has_simd(), "simd instruction");
1611     assert(size == VELEM_SIZE_8 || size == VELEM_SIZE_16, "must be");
1612     emit_int32(quad << 30 | 0b101110 << 24 | size << 22 |
1613                0b100000000010 << 10 | Vn->encoding() << 5 | Vd->encoding());
1614   }
1615 
1616   void eor(FloatRegister Vd, FloatRegister Vn,  FloatRegister Vm, VElem_Size size, int quad) {
1617     assert(VM_Version::has_simd(), "simd instruction");
1618     assert(size == VELEM_SIZE_8, "must be");
1619     emit_int32(quad << 30 | 0b101110001 << 21 | Vm->encoding() << 16 |
1620                0b000111 << 10 | Vn->encoding() << 5 | Vd->encoding());
1621   }
1622 
1623   void orr(FloatRegister Vd, FloatRegister Vn,  FloatRegister Vm, VElem_Size size, int quad) {
1624     assert(VM_Version::has_simd(), "simd instruction");
1625     assert(size == VELEM_SIZE_8, "must be");
1626     emit_int32(quad << 30 | 0b001110101 << 21 | Vm->encoding() << 16 |
1627                0b000111 << 10 | Vn->encoding() << 5 | Vd->encoding());
1628   }
1629 
1630   void vmovI(FloatRegister Dd, int imm8, VElem_Size size, int quad) {
1631     assert(VM_Version::has_simd(), "simd instruction");
1632     assert(imm8 >= 0 && imm8 < 256, "out of range");
1633     int op;
1634     int cmode;
1635     switch (size) {
1636     case VELEM_SIZE_8:
1637       op = 0;
1638       cmode = 0b1110;
1639       break;
1640     case VELEM_SIZE_16:
1641       op = 0;
1642       cmode = 0b1000;
1643       break;
1644     case VELEM_SIZE_32:
1645       op = 0;
1646       cmode = 0b0000;
1647       break;
1648     default:
1649       cmode = 0;
1650       ShouldNotReachHere();
1651     }
1652     int abc = imm8 >> 5;
1653     int defgh = imm8 & 0b11111;
1654     emit_int32(quad << 30 | op << 29 | 0b1111 << 24 |
1655                abc << 16 | cmode << 12 | 0b01 << 10 |
1656                defgh << 5 | Dd->encoding() << 0);
1657   }
1658 
1659   void vdupI(FloatRegister Dd, Register Rn, VElem_Size size, int quad) {
1660     assert(VM_Version::has_simd(), "simd instruction");
1661     assert(size <= 3, "unallocated encoding");
1662     assert(size != 3 || quad == 1, "reserved");
1663     int imm5 = 1 << size;
1664 #ifdef ASSERT
1665     switch (size) {
1666     case VELEM_SIZE_8:
1667       assert(imm5 == 0b00001, "sanity");
1668       break;
1669     case VELEM_SIZE_16:
1670       assert(imm5 == 0b00010, "sanity");
1671       break;
1672     case VELEM_SIZE_32:
1673       assert(imm5 == 0b00100, "sanity");
1674       break;
1675     case VELEM_SIZE_64:
1676       assert(imm5 == 0b01000, "sanity");
1677       break;
1678     default:
1679       ShouldNotReachHere();
1680     }
1681 #endif
1682     emit_int32(quad << 30 | 0b111 << 25 | 0b11 << 10 |
1683                imm5 << 16 | Rn->encoding() << 5 |
1684                Dd->encoding() << 0);
1685   }
1686 
1687   void vdup(FloatRegister Vd, FloatRegister Vn, VElem_Size size, int quad) {
1688     assert(VM_Version::has_simd(), "simd instruction");
1689     int index = 0;
1690     int bytes = 1 << size;
1691     int range = 16 / bytes;
1692     assert(index < range, "overflow");
1693 
1694     assert(size != VELEM_SIZE_64 || quad, "reserved");
1695     assert(8 << VELEM_SIZE_8  ==  8, "sanity");
1696     assert(8 << VELEM_SIZE_16 == 16, "sanity");
1697     assert(8 << VELEM_SIZE_32 == 32, "sanity");
1698     assert(8 << VELEM_SIZE_64 == 64, "sanity");
1699 
1700     int imm5 = (index << (size + 1)) | bytes;
1701 
1702     emit_int32(quad << 30 | 0b001110000 << 21 | imm5 << 16 | 0b000001 << 10 |
1703                Vn->encoding() << 5 | Vd->encoding() << 0);
1704   }
1705 
1706   void vdupF(FloatRegister Vd, FloatRegister Vn, int quad) {
1707     vdup(Vd, Vn, VELEM_SIZE_32, quad);
1708   }
1709 
1710   void vdupD(FloatRegister Vd, FloatRegister Vn, int quad) {
1711     vdup(Vd, Vn, VELEM_SIZE_64, quad);
1712   }
1713 #endif
1714 };
1715 
1716 
1717 #endif // CPU_ARM_VM_ASSEMBLER_ARM_64_HPP