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   F(dpcs1, 0b101, 0b000, 0b01)
1087 #undef F
1088 
1089   enum SystemRegister { // o0<1> op1<3> CRn<4> CRm<4> op2<3>
1090     SysReg_NZCV = 0b101101000010000,
1091     SysReg_FPCR = 0b101101000100000,
1092   };
1093 
1094   void mrs(Register rt, SystemRegister systemReg) {
1095     assert ((systemReg >> 15) == 0, "systemReg is out of range");
1096     emit_int32(0b110101010011 << 20 | systemReg << 5 | rt->encoding_with_zr());
1097   }
1098 
1099   void msr(SystemRegister systemReg, Register rt) {
1100     assert ((systemReg >> 15) == 0, "systemReg is out of range");
1101     emit_int32(0b110101010001 << 20 | systemReg << 5 | rt->encoding_with_zr());
1102   }
1103 
1104   // Floating-point instructions
1105 
1106 #define F(mnemonic, M, S, type, opcode2) \
1107   void mnemonic(FloatRegister rn, FloatRegister rm) {                         \
1108     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |     \
1109         rm->encoding() << 16 | 0b1000 << 10 | rn->encoding() << 5 | opcode2); \
1110   }
1111 
1112   F(fcmp_s,   0, 0, 0b00, 0b00000)
1113   F(fcmpe_s,  0, 0, 0b00, 0b01000)
1114   F(fcmp_d,   0, 0, 0b01, 0b00000)
1115   F(fcmpe_d,  0, 0, 0b01, 0b10000)
1116 #undef F
1117 
1118 #define F(mnemonic, M, S, type, opcode2) \
1119   void mnemonic(FloatRegister rn) {                                           \
1120     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |     \
1121         0b1000 << 10 | rn->encoding() << 5 | opcode2);                        \
1122   }
1123 
1124   F(fcmp0_s,   0, 0, 0b00, 0b01000)
1125   F(fcmpe0_s,  0, 0, 0b00, 0b11000)
1126   F(fcmp0_d,   0, 0, 0b01, 0b01000)
1127   F(fcmpe0_d,  0, 0, 0b01, 0b11000)
1128 #undef F
1129 
1130 #define F(mnemonic, M, S, type, op) \
1131   void mnemonic(FloatRegister rn, FloatRegister rm, int nzcv, AsmCondition cond) { \
1132     assert ((nzcv >> 4) == 0, "illegal nzcv");                                                  \
1133     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                       \
1134         rm->encoding() << 16 | cond << 12 | 0b01 << 10 | rn->encoding() << 5 | op << 4 | nzcv); \
1135   }
1136 
1137   F(fccmp_s,   0, 0, 0b00, 0)
1138   F(fccmpe_s,  0, 0, 0b00, 1)
1139   F(fccmp_d,   0, 0, 0b01, 0)
1140   F(fccmpe_d,  0, 0, 0b01, 1)
1141 #undef F
1142 
1143 #define F(mnemonic, M, S, type) \
1144   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm, AsmCondition cond) { \
1145     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                       \
1146         rm->encoding() << 16 | cond << 12 | 0b11 << 10 | rn->encoding() << 5 | rd->encoding()); \
1147   }
1148 
1149   F(fcsel_s,   0, 0, 0b00)
1150   F(fcsel_d,   0, 0, 0b01)
1151 #undef F
1152 
1153 #define F(mnemonic, M, S, type, opcode) \
1154   void mnemonic(FloatRegister rd, FloatRegister rn) { \
1155     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |      \
1156         opcode << 15 | 0b10000 << 10 | rn->encoding() << 5 | rd->encoding());  \
1157   }
1158 
1159   F(fmov_s,   0, 0, 0b00, 0b000000)
1160   F(fabs_s,   0, 0, 0b00, 0b000001)
1161   F(fneg_s,   0, 0, 0b00, 0b000010)
1162   F(fsqrt_s,  0, 0, 0b00, 0b000011)
1163   F(fcvt_ds,  0, 0, 0b00, 0b000101)
1164   F(fcvt_hs,  0, 0, 0b00, 0b000111)
1165   F(frintn_s, 0, 0, 0b00, 0b001000)
1166   F(frintp_s, 0, 0, 0b00, 0b001001)
1167   F(frintm_s, 0, 0, 0b00, 0b001010)
1168   F(frintz_s, 0, 0, 0b00, 0b001011)
1169   F(frinta_s, 0, 0, 0b00, 0b001100)
1170   F(frintx_s, 0, 0, 0b00, 0b001110)
1171   F(frinti_s, 0, 0, 0b00, 0b001111)
1172 
1173   F(fmov_d,   0, 0, 0b01, 0b000000)
1174   F(fabs_d,   0, 0, 0b01, 0b000001)
1175   F(fneg_d,   0, 0, 0b01, 0b000010)
1176   F(fsqrt_d,  0, 0, 0b01, 0b000011)
1177   F(fcvt_sd,  0, 0, 0b01, 0b000100)
1178   F(fcvt_hd,  0, 0, 0b01, 0b000111)
1179   F(frintn_d, 0, 0, 0b01, 0b001000)
1180   F(frintp_d, 0, 0, 0b01, 0b001001)
1181   F(frintm_d, 0, 0, 0b01, 0b001010)
1182   F(frintz_d, 0, 0, 0b01, 0b001011)
1183   F(frinta_d, 0, 0, 0b01, 0b001100)
1184   F(frintx_d, 0, 0, 0b01, 0b001110)
1185   F(frinti_d, 0, 0, 0b01, 0b001111)
1186 
1187   F(fcvt_sh,  0, 0, 0b11, 0b000100)
1188   F(fcvt_dh,  0, 0, 0b11, 0b000101)
1189 #undef F
1190 
1191 #define F(mnemonic, M, S, type, opcode) \
1192   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm) { \
1193     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |                          \
1194         rm->encoding() << 16 | opcode << 12 | 0b10 << 10 | rn->encoding() << 5 | rd->encoding());  \
1195   }
1196 
1197   F(fmul_s,   0, 0, 0b00, 0b0000)
1198   F(fdiv_s,   0, 0, 0b00, 0b0001)
1199   F(fadd_s,   0, 0, 0b00, 0b0010)
1200   F(fsub_s,   0, 0, 0b00, 0b0011)
1201   F(fmax_s,   0, 0, 0b00, 0b0100)
1202   F(fmin_s,   0, 0, 0b00, 0b0101)
1203   F(fmaxnm_s, 0, 0, 0b00, 0b0110)
1204   F(fminnm_s, 0, 0, 0b00, 0b0111)
1205   F(fnmul_s,  0, 0, 0b00, 0b1000)
1206 
1207   F(fmul_d,   0, 0, 0b01, 0b0000)
1208   F(fdiv_d,   0, 0, 0b01, 0b0001)
1209   F(fadd_d,   0, 0, 0b01, 0b0010)
1210   F(fsub_d,   0, 0, 0b01, 0b0011)
1211   F(fmax_d,   0, 0, 0b01, 0b0100)
1212   F(fmin_d,   0, 0, 0b01, 0b0101)
1213   F(fmaxnm_d, 0, 0, 0b01, 0b0110)
1214   F(fminnm_d, 0, 0, 0b01, 0b0111)
1215   F(fnmul_d,  0, 0, 0b01, 0b1000)
1216 #undef F
1217 
1218 #define F(mnemonic, M, S, type, o1, o0) \
1219   void mnemonic(FloatRegister rd, FloatRegister rn, FloatRegister rm, FloatRegister ra) { \
1220     emit_int32(M << 31 | S << 29 | 0b11111 << 24 | type << 22 | o1 << 21 | rm->encoding() << 16 |  \
1221          o0 << 15 | ra->encoding() << 10 | rn->encoding() << 5 | rd->encoding());                  \
1222   }
1223 
1224   F(fmadd_s,  0, 0, 0b00, 0, 0)
1225   F(fmsub_s,  0, 0, 0b00, 0, 1)
1226   F(fnmadd_s, 0, 0, 0b00, 1, 0)
1227   F(fnmsub_s, 0, 0, 0b00, 1, 1)
1228 
1229   F(fmadd_d,  0, 0, 0b01, 0, 0)
1230   F(fmsub_d,  0, 0, 0b01, 0, 1)
1231   F(fnmadd_d, 0, 0, 0b01, 1, 0)
1232   F(fnmsub_d, 0, 0, 0b01, 1, 1)
1233 #undef F
1234 
1235 #define F(mnemonic, M, S, type) \
1236   void mnemonic(FloatRegister rd, int imm8) { \
1237     assert ((imm8 >> 8) == 0, "immediate is out of range");                \
1238     emit_int32(M << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |  \
1239          imm8 << 13 | 0b100 << 10 | rd->encoding());                       \
1240   }
1241 
1242   F(fmov_s, 0, 0, 0b00)
1243   F(fmov_d, 0, 0, 0b01)
1244 #undef F
1245 
1246 #define F(mnemonic, sf, S, type, rmode, opcode) \
1247   void mnemonic(Register rd, FloatRegister rn) {                                     \
1248     emit_int32(sf << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |           \
1249          rmode << 19 | opcode << 16 | rn->encoding() << 5 | rd->encoding_with_zr()); \
1250   }
1251 
1252   F(fcvtns_ws, 0, 0, 0b00, 0b00, 0b000)
1253   F(fcvtnu_ws, 0, 0, 0b00, 0b00, 0b001)
1254   F(fcvtas_ws, 0, 0, 0b00, 0b00, 0b100)
1255   F(fcvtau_ws, 0, 0, 0b00, 0b00, 0b101)
1256   F(fmov_ws,   0, 0, 0b00, 0b00, 0b110)
1257   F(fcvtps_ws, 0, 0, 0b00, 0b01, 0b000)
1258   F(fcvtpu_ws, 0, 0, 0b00, 0b01, 0b001)
1259   F(fcvtms_ws, 0, 0, 0b00, 0b10, 0b000)
1260   F(fcvtmu_ws, 0, 0, 0b00, 0b10, 0b001)
1261   F(fcvtzs_ws, 0, 0, 0b00, 0b11, 0b000)
1262   F(fcvtzu_ws, 0, 0, 0b00, 0b11, 0b001)
1263 
1264   F(fcvtns_wd, 0, 0, 0b01, 0b00, 0b000)
1265   F(fcvtnu_wd, 0, 0, 0b01, 0b00, 0b001)
1266   F(fcvtas_wd, 0, 0, 0b01, 0b00, 0b100)
1267   F(fcvtau_wd, 0, 0, 0b01, 0b00, 0b101)
1268   F(fcvtps_wd, 0, 0, 0b01, 0b01, 0b000)
1269   F(fcvtpu_wd, 0, 0, 0b01, 0b01, 0b001)
1270   F(fcvtms_wd, 0, 0, 0b01, 0b10, 0b000)
1271   F(fcvtmu_wd, 0, 0, 0b01, 0b10, 0b001)
1272   F(fcvtzs_wd, 0, 0, 0b01, 0b11, 0b000)
1273   F(fcvtzu_wd, 0, 0, 0b01, 0b11, 0b001)
1274 
1275   F(fcvtns_xs, 1, 0, 0b00, 0b00, 0b000)
1276   F(fcvtnu_xs, 1, 0, 0b00, 0b00, 0b001)
1277   F(fcvtas_xs, 1, 0, 0b00, 0b00, 0b100)
1278   F(fcvtau_xs, 1, 0, 0b00, 0b00, 0b101)
1279   F(fcvtps_xs, 1, 0, 0b00, 0b01, 0b000)
1280   F(fcvtpu_xs, 1, 0, 0b00, 0b01, 0b001)
1281   F(fcvtms_xs, 1, 0, 0b00, 0b10, 0b000)
1282   F(fcvtmu_xs, 1, 0, 0b00, 0b10, 0b001)
1283   F(fcvtzs_xs, 1, 0, 0b00, 0b11, 0b000)
1284   F(fcvtzu_xs, 1, 0, 0b00, 0b11, 0b001)
1285 
1286   F(fcvtns_xd, 1, 0, 0b01, 0b00, 0b000)
1287   F(fcvtnu_xd, 1, 0, 0b01, 0b00, 0b001)
1288   F(fcvtas_xd, 1, 0, 0b01, 0b00, 0b100)
1289   F(fcvtau_xd, 1, 0, 0b01, 0b00, 0b101)
1290   F(fmov_xd,   1, 0, 0b01, 0b00, 0b110)
1291   F(fcvtps_xd, 1, 0, 0b01, 0b01, 0b000)
1292   F(fcvtpu_xd, 1, 0, 0b01, 0b01, 0b001)
1293   F(fcvtms_xd, 1, 0, 0b01, 0b10, 0b000)
1294   F(fcvtmu_xd, 1, 0, 0b01, 0b10, 0b001)
1295   F(fcvtzs_xd, 1, 0, 0b01, 0b11, 0b000)
1296   F(fcvtzu_xd, 1, 0, 0b01, 0b11, 0b001)
1297 
1298   F(fmov_xq,   1, 0, 0b10, 0b01, 0b110)
1299 #undef F
1300 
1301 #define F(mnemonic, sf, S, type, rmode, opcode) \
1302   void mnemonic(FloatRegister rd, Register rn) {                                     \
1303     emit_int32(sf << 31 | S << 29 | 0b11110 << 24 | type << 22 | 1 << 21 |           \
1304          rmode << 19 | opcode << 16 | rn->encoding_with_zr() << 5 | rd->encoding()); \
1305   }
1306 
1307   F(scvtf_sw,  0, 0, 0b00, 0b00, 0b010)
1308   F(ucvtf_sw,  0, 0, 0b00, 0b00, 0b011)
1309   F(fmov_sw,   0, 0, 0b00, 0b00, 0b111)
1310   F(scvtf_dw,  0, 0, 0b01, 0b00, 0b010)
1311   F(ucvtf_dw,  0, 0, 0b01, 0b00, 0b011)
1312 
1313   F(scvtf_sx,  1, 0, 0b00, 0b00, 0b010)
1314   F(ucvtf_sx,  1, 0, 0b00, 0b00, 0b011)
1315   F(scvtf_dx,  1, 0, 0b01, 0b00, 0b010)
1316   F(ucvtf_dx,  1, 0, 0b01, 0b00, 0b011)
1317   F(fmov_dx,   1, 0, 0b01, 0b00, 0b111)
1318 
1319   F(fmov_qx,   1, 0, 0b10, 0b01, 0b111)
1320 #undef F
1321 
1322 #define F(mnemonic, opcode) \
1323   void mnemonic(FloatRegister Vd, FloatRegister Vn) {                                     \
1324     emit_int32( opcode << 10 | Vn->encoding() << 5 | Vd->encoding());             \
1325   }
1326 
1327   F(aese, 0b0100111000101000010010);
1328   F(aesd, 0b0100111000101000010110);
1329   F(aesmc, 0b0100111000101000011010);
1330   F(aesimc, 0b0100111000101000011110);
1331 #undef F
1332 
1333 #ifdef COMPILER2
1334   typedef VFP::double_num double_num;
1335   typedef VFP::float_num  float_num;
1336 #endif
1337 
1338   void vcnt(FloatRegister Dd, FloatRegister Dn, int quad = 0, int size = 0) {
1339     // emitted at VM startup to detect whether the instruction is available
1340     assert(!VM_Version::is_initialized() || VM_Version::has_simd(), "simd instruction");
1341     assert(size == 0, "illegal size value");
1342     emit_int32(0x0e205800 | quad << 30 | size << 22 | Dn->encoding() << 5 | Dd->encoding());
1343   }
1344 
1345 #ifdef COMPILER2
1346   void addv(FloatRegister Dd, FloatRegister Dm, int quad, int size) {
1347     // emitted at VM startup to detect whether the instruction is available
1348     assert(VM_Version::has_simd(), "simd instruction");
1349     assert((quad & ~1) == 0, "illegal value");
1350     assert(size >= 0 && size < 3, "illegal value");
1351     assert(((size << 1) | quad) != 4, "illegal values (size 2, quad 0)");
1352     emit_int32(0x0e31b800 | quad << 30 | size << 22 | Dm->encoding() << 5 | Dd->encoding());
1353   }
1354 
1355   enum VElem_Size {
1356     VELEM_SIZE_8  = 0x00,
1357     VELEM_SIZE_16 = 0x01,
1358     VELEM_SIZE_32 = 0x02,
1359     VELEM_SIZE_64 = 0x03
1360   };
1361 
1362   enum VLD_Type {
1363     VLD1_TYPE_1_REG  = 0b0111,
1364     VLD1_TYPE_2_REGS = 0b1010,
1365     VLD1_TYPE_3_REGS = 0b0110,
1366     VLD1_TYPE_4_REGS = 0b0010
1367   };
1368 
1369   enum VFloat_Arith_Size {
1370     VFA_SIZE_F32 = 0b0,
1371     VFA_SIZE_F64 = 0b1
1372   };
1373 
1374 #define F(mnemonic, U, S, P) \
1375   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1376                 int size, int quad) {                                    \
1377     assert(VM_Version::has_simd(), "simd instruction");                  \
1378     assert(!(size == VFA_SIZE_F64 && !quad), "reserved");                \
1379     assert((size & 1) == size, "overflow");                              \
1380     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 |                    \
1381                S << 23 | size << 22 | 1 << 21 | P << 11 | 1 << 10 |      \
1382                fm->encoding() << 16 |                                    \
1383                fn->encoding() <<  5 |                                    \
1384                fd->encoding());                                          \
1385   }
1386 
1387   F(vaddF, 0, 0, 0b11010)  // Vd = Vn + Vm (float)
1388   F(vsubF, 0, 1, 0b11010)  // Vd = Vn - Vm (float)
1389   F(vmulF, 1, 0, 0b11011)  // Vd = Vn - Vm (float)
1390   F(vdivF, 1, 0, 0b11111)  // Vd = Vn / Vm (float)
1391 #undef F
1392 
1393 #define F(mnemonic, U) \
1394   void mnemonic(FloatRegister fd, FloatRegister fm, FloatRegister fn,    \
1395                 int size, int quad) {                                    \
1396     assert(VM_Version::has_simd(), "simd instruction");                  \
1397     assert(!(size == VELEM_SIZE_64 && !quad), "reserved");               \
1398     assert((size & 0b11) == size, "overflow");                           \
1399     int R = 0; /* rounding */                                            \
1400     int S = 0; /* saturating */                                          \
1401     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | size << 22 |       \
1402                1 << 21 | R << 12 | S << 11 | 0b10001 << 10 |             \
1403                fm->encoding() << 16 |                                    \
1404                fn->encoding() <<  5 |                                    \
1405                fd->encoding());                                          \
1406   }
1407 
1408   F(vshlSI, 0)  // Vd = ashift(Vn,Vm) (int)
1409   F(vshlUI, 1)  // Vd = lshift(Vn,Vm) (int)
1410 #undef F
1411 
1412 #define F(mnemonic, U, P, M) \
1413   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1414                 int size, int quad) {                                    \
1415     assert(VM_Version::has_simd(), "simd instruction");                  \
1416     assert(!(size == VELEM_SIZE_64 && !quad), "reserved");               \
1417     assert(!(size == VELEM_SIZE_64 && M), "reserved");                   \
1418     assert((size & 0b11) == size, "overflow");                           \
1419     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | size << 22 |       \
1420                1 << 21 | P << 11 | 1 << 10 |                             \
1421                fm->encoding() << 16 |                                    \
1422                fn->encoding() <<  5 |                                    \
1423                fd->encoding());                                          \
1424   }
1425 
1426   F(vmulI, 0, 0b10011,  true)  // Vd = Vn * Vm (int)
1427   F(vaddI, 0, 0b10000, false)  // Vd = Vn + Vm (int)
1428   F(vsubI, 1, 0b10000, false)  // Vd = Vn - Vm (int)
1429 #undef F
1430 
1431 #define F(mnemonic, U, O) \
1432   void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm,    \
1433                 int quad) {                                              \
1434     assert(VM_Version::has_simd(), "simd instruction");                  \
1435     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 | O << 22 |          \
1436                1 << 21 | 0b00011 << 11 | 1 << 10 |                       \
1437                fm->encoding() << 16 |                                    \
1438                fn->encoding() <<  5 |                                    \
1439                fd->encoding());                                          \
1440   }
1441 
1442   F(vandI, 0, 0b00)  // Vd = Vn & Vm (int)
1443   F(vorI,  0, 0b10)  // Vd = Vn | Vm (int)
1444   F(vxorI, 1, 0b00)  // Vd = Vn ^ Vm (int)
1445 #undef F
1446 
1447   void vnegI(FloatRegister fd, FloatRegister fn, int size, int quad) {
1448     int U = 1;
1449     assert(VM_Version::has_simd(), "simd instruction");
1450     assert(quad || size != VELEM_SIZE_64, "reserved");
1451     emit_int32(quad << 30 | U << 29 | 0b01110 << 24 |
1452               size << 22 | 0b100000101110 << 10 |
1453               fn->encoding() << 5 |
1454               fd->encoding() << 0);
1455   }
1456 
1457   void vshli(FloatRegister fd, FloatRegister fn, int esize, int imm, int quad) {
1458     assert(VM_Version::has_simd(), "simd instruction");
1459 
1460     if (imm >= esize) {
1461       // maximum shift gives all zeroes, direction doesn't matter,
1462       // but only available for shift right
1463       vshri(fd, fn, esize, esize, true /* unsigned */, quad);
1464       return;
1465     }
1466     assert(imm >= 0 && imm < esize, "out of range");
1467 
1468     int imm7 = esize + imm;
1469     int immh = imm7 >> 3;
1470     assert(immh != 0, "encoding constraint");
1471     assert((uint)immh < 16, "sanity");
1472     assert(((immh >> 2) | quad) != 0b10, "reserved");
1473     emit_int32(quad << 30 | 0b011110 << 23 | imm7 << 16 |
1474                0b010101 << 10 | fn->encoding() << 5 | fd->encoding() << 0);
1475   }
1476 
1477   void vshri(FloatRegister fd, FloatRegister fn, int esize, int imm,
1478              bool U /* unsigned */, int quad) {
1479     assert(VM_Version::has_simd(), "simd instruction");
1480     assert(imm > 0, "out of range");
1481     if (imm >= esize) {
1482       // maximum shift (all zeroes)
1483       imm = esize;
1484     }
1485     int imm7 = 2 * esize - imm ;
1486     int immh = imm7 >> 3;
1487     assert(immh != 0, "encoding constraint");
1488     assert((uint)immh < 16, "sanity");
1489     assert(((immh >> 2) | quad) != 0b10, "reserved");
1490     emit_int32(quad << 30 | U << 29 | 0b011110 << 23 | imm7 << 16 |
1491                0b000001 << 10 | fn->encoding() << 5 | fd->encoding() << 0);
1492   }
1493   void vshrUI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {
1494     vshri(fd, fm, size, imm, true /* unsigned */, quad);
1495   }
1496   void vshrSI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {
1497     vshri(fd, fm, size, imm, false /* signed */, quad);
1498   }
1499 
1500   void vld1(FloatRegister Vt, Address addr, VElem_Size size, int bits) {
1501     assert(VM_Version::has_simd(), "simd instruction");
1502     assert(bits == 128, "unsupported");
1503     assert(addr.disp() == 0 || addr.disp() == 16, "must be");
1504     int type = 0b11; // 2D
1505     int quad = 1;
1506     int L = 1;
1507     int opcode = VLD1_TYPE_1_REG;
1508     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1509                Vt->encoding() << 0 | addr.encoding_simd());
1510   }
1511 
1512   void vst1(FloatRegister Vt, Address addr, VElem_Size size, int bits) {
1513     assert(VM_Version::has_simd(), "simd instruction");
1514     assert(bits == 128, "unsupported");
1515     assert(addr.disp() == 0 || addr.disp() == 16, "must be");
1516     int type = 0b11; // 2D
1517     int quad = 1;
1518     int L = 0;
1519     int opcode = VLD1_TYPE_1_REG;
1520     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1521                Vt->encoding() << 0 | addr.encoding_simd());
1522   }
1523 
1524   void vld1(FloatRegister Vt, FloatRegister Vt2, Address addr, VElem_Size size, int bits) {
1525     assert(VM_Version::has_simd(), "simd instruction");
1526     assert(bits == 128, "unsupported");
1527     assert(Vt->successor() == Vt2, "Registers must be ordered");
1528     assert(addr.disp() == 0 || addr.disp() == 32, "must be");
1529     int type = 0b11; // 2D
1530     int quad = 1;
1531     int L = 1;
1532     int opcode = VLD1_TYPE_2_REGS;
1533     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1534                Vt->encoding() << 0 | addr.encoding_simd());
1535   }
1536 
1537   void vst1(FloatRegister Vt, FloatRegister Vt2, Address addr, VElem_Size size, int bits) {
1538     assert(VM_Version::has_simd(), "simd instruction");
1539     assert(Vt->successor() == Vt2, "Registers must be ordered");
1540     assert(bits == 128, "unsupported");
1541     assert(addr.disp() == 0 || addr.disp() == 32, "must be");
1542     int type = 0b11; // 2D
1543     int quad = 1;
1544     int L = 0;
1545     int opcode = VLD1_TYPE_2_REGS;
1546     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1547                Vt->encoding() << 0 | addr.encoding_simd());
1548   }
1549 
1550   void vld1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1551             Address addr, VElem_Size size, int bits) {
1552     assert(VM_Version::has_simd(), "simd instruction");
1553     assert(bits == 128, "unsupported");
1554     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3,
1555           "Registers must be ordered");
1556     assert(addr.disp() == 0 || addr.disp() == 48, "must be");
1557     int type = 0b11; // 2D
1558     int quad = 1;
1559     int L = 1;
1560     int opcode = VLD1_TYPE_3_REGS;
1561     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1562                Vt->encoding() << 0 | addr.encoding_simd());
1563   }
1564 
1565   void vst1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1566             Address addr, VElem_Size size, int bits) {
1567     assert(VM_Version::has_simd(), "simd instruction");
1568     assert(bits == 128, "unsupported");
1569     assert(Vt->successor() == Vt2 &&  Vt2->successor() == Vt3,
1570            "Registers must be ordered");
1571     assert(addr.disp() == 0 || addr.disp() == 48, "must be");
1572     int type = 0b11; // 2D
1573     int quad = 1;
1574     int L = 0;
1575     int opcode = VLD1_TYPE_3_REGS;
1576     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1577                Vt->encoding() << 0 | addr.encoding_simd());
1578   }
1579 
1580   void vld1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1581             FloatRegister Vt4, Address addr, VElem_Size size, int bits) {
1582     assert(VM_Version::has_simd(), "simd instruction");
1583     assert(bits == 128, "unsupported");
1584     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 &&
1585            Vt3->successor() == Vt4, "Registers must be ordered");
1586     assert(addr.disp() == 0 || addr.disp() == 64, "must be");
1587     int type = 0b11; // 2D
1588     int quad = 1;
1589     int L = 1;
1590     int opcode = VLD1_TYPE_4_REGS;
1591     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1592                Vt->encoding() << 0 | addr.encoding_simd());
1593   }
1594 
1595   void vst1(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3,
1596             FloatRegister Vt4,  Address addr, VElem_Size size, int bits) {
1597     assert(VM_Version::has_simd(), "simd instruction");
1598     assert(bits == 128, "unsupported");
1599     assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 &&
1600            Vt3->successor() == Vt4, "Registers must be ordered");
1601     assert(addr.disp() == 0 || addr.disp() == 64, "must be");
1602     int type = 0b11; // 2D
1603     int quad = 1;
1604     int L = 0;
1605     int opcode = VLD1_TYPE_4_REGS;
1606     emit_int32(quad << 30 | 0b11 << 26 | L << 22 | opcode << 12 | size << 10 |
1607                Vt->encoding() << 0 | addr.encoding_simd());
1608   }
1609 
1610   void rev32(FloatRegister Vd, FloatRegister Vn, VElem_Size size, int quad) {
1611     assert(VM_Version::has_simd(), "simd instruction");
1612     assert(size == VELEM_SIZE_8 || size == VELEM_SIZE_16, "must be");
1613     emit_int32(quad << 30 | 0b101110 << 24 | size << 22 |
1614                0b100000000010 << 10 | Vn->encoding() << 5 | Vd->encoding());
1615   }
1616 
1617   void eor(FloatRegister Vd, FloatRegister Vn,  FloatRegister Vm, VElem_Size size, int quad) {
1618     assert(VM_Version::has_simd(), "simd instruction");
1619     assert(size == VELEM_SIZE_8, "must be");
1620     emit_int32(quad << 30 | 0b101110001 << 21 | Vm->encoding() << 16 |
1621                0b000111 << 10 | Vn->encoding() << 5 | Vd->encoding());
1622   }
1623 
1624   void orr(FloatRegister Vd, FloatRegister Vn,  FloatRegister Vm, VElem_Size size, int quad) {
1625     assert(VM_Version::has_simd(), "simd instruction");
1626     assert(size == VELEM_SIZE_8, "must be");
1627     emit_int32(quad << 30 | 0b001110101 << 21 | Vm->encoding() << 16 |
1628                0b000111 << 10 | Vn->encoding() << 5 | Vd->encoding());
1629   }
1630 
1631   void vmovI(FloatRegister Dd, int imm8, VElem_Size size, int quad) {
1632     assert(VM_Version::has_simd(), "simd instruction");
1633     assert(imm8 >= 0 && imm8 < 256, "out of range");
1634     int op;
1635     int cmode;
1636     switch (size) {
1637     case VELEM_SIZE_8:
1638       op = 0;
1639       cmode = 0b1110;
1640       break;
1641     case VELEM_SIZE_16:
1642       op = 0;
1643       cmode = 0b1000;
1644       break;
1645     case VELEM_SIZE_32:
1646       op = 0;
1647       cmode = 0b0000;
1648       break;
1649     default:
1650       cmode = 0;
1651       ShouldNotReachHere();
1652     }
1653     int abc = imm8 >> 5;
1654     int defgh = imm8 & 0b11111;
1655     emit_int32(quad << 30 | op << 29 | 0b1111 << 24 |
1656                abc << 16 | cmode << 12 | 0b01 << 10 |
1657                defgh << 5 | Dd->encoding() << 0);
1658   }
1659 
1660   void vdupI(FloatRegister Dd, Register Rn, VElem_Size size, int quad) {
1661     assert(VM_Version::has_simd(), "simd instruction");
1662     assert(size <= 3, "unallocated encoding");
1663     assert(size != 3 || quad == 1, "reserved");
1664     int imm5 = 1 << size;
1665 #ifdef ASSERT
1666     switch (size) {
1667     case VELEM_SIZE_8:
1668       assert(imm5 == 0b00001, "sanity");
1669       break;
1670     case VELEM_SIZE_16:
1671       assert(imm5 == 0b00010, "sanity");
1672       break;
1673     case VELEM_SIZE_32:
1674       assert(imm5 == 0b00100, "sanity");
1675       break;
1676     case VELEM_SIZE_64:
1677       assert(imm5 == 0b01000, "sanity");
1678       break;
1679     default:
1680       ShouldNotReachHere();
1681     }
1682 #endif
1683     emit_int32(quad << 30 | 0b111 << 25 | 0b11 << 10 |
1684                imm5 << 16 | Rn->encoding() << 5 |
1685                Dd->encoding() << 0);
1686   }
1687 
1688   void vdup(FloatRegister Vd, FloatRegister Vn, VElem_Size size, int quad) {
1689     assert(VM_Version::has_simd(), "simd instruction");
1690     int index = 0;
1691     int bytes = 1 << size;
1692     int range = 16 / bytes;
1693     assert(index < range, "overflow");
1694 
1695     assert(size != VELEM_SIZE_64 || quad, "reserved");
1696     assert(8 << VELEM_SIZE_8  ==  8, "sanity");
1697     assert(8 << VELEM_SIZE_16 == 16, "sanity");
1698     assert(8 << VELEM_SIZE_32 == 32, "sanity");
1699     assert(8 << VELEM_SIZE_64 == 64, "sanity");
1700 
1701     int imm5 = (index << (size + 1)) | bytes;
1702 
1703     emit_int32(quad << 30 | 0b001110000 << 21 | imm5 << 16 | 0b000001 << 10 |
1704                Vn->encoding() << 5 | Vd->encoding() << 0);
1705   }
1706 
1707   void vdupF(FloatRegister Vd, FloatRegister Vn, int quad) {
1708     vdup(Vd, Vn, VELEM_SIZE_32, quad);
1709   }
1710 
1711   void vdupD(FloatRegister Vd, FloatRegister Vn, int quad) {
1712     vdup(Vd, Vn, VELEM_SIZE_64, quad);
1713   }
1714 #endif
1715 };
1716 
1717 
1718 #endif // CPU_ARM_VM_ASSEMBLER_ARM_64_HPP