1 /*
   2  * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
   4  * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  *
  25  */
  26 
  27 #ifndef CPU_RISCV_ASSEMBLER_RISCV_HPP
  28 #define CPU_RISCV_ASSEMBLER_RISCV_HPP
  29 
  30 #include "asm/register.hpp"
  31 #include "assembler_riscv.inline.hpp"
  32 
  33 #define XLEN 64
  34 
  35 // definitions of various symbolic names for machine registers
  36 
  37 // First intercalls between C and Java which use 8 general registers
  38 // and 8 floating registers
  39 
  40 class Argument {
  41  public:
  42   enum {
  43     n_int_register_parameters_c   = 8,  // x10, x11, ... x17 (c_rarg0, c_rarg1, ...)
  44     n_float_register_parameters_c = 8,  // f10, f11, ... f17 (c_farg0, c_farg1, ... )
  45 
  46     n_int_register_parameters_j   = 8, // x11, ... x17, x10 (rj_rarg0, j_rarg1, ...)
  47     n_float_register_parameters_j = 8  // f10, f11, ... f17 (j_farg0, j_farg1, ...)
  48   };
  49 };
  50 
  51 // function argument(caller-save registers)
  52 REGISTER_DECLARATION(Register, c_rarg0, x10);
  53 REGISTER_DECLARATION(Register, c_rarg1, x11);
  54 REGISTER_DECLARATION(Register, c_rarg2, x12);
  55 REGISTER_DECLARATION(Register, c_rarg3, x13);
  56 REGISTER_DECLARATION(Register, c_rarg4, x14);
  57 REGISTER_DECLARATION(Register, c_rarg5, x15);
  58 REGISTER_DECLARATION(Register, c_rarg6, x16);
  59 REGISTER_DECLARATION(Register, c_rarg7, x17);
  60 
  61 REGISTER_DECLARATION(FloatRegister, c_farg0, f10);
  62 REGISTER_DECLARATION(FloatRegister, c_farg1, f11);
  63 REGISTER_DECLARATION(FloatRegister, c_farg2, f12);
  64 REGISTER_DECLARATION(FloatRegister, c_farg3, f13);
  65 REGISTER_DECLARATION(FloatRegister, c_farg4, f14);
  66 REGISTER_DECLARATION(FloatRegister, c_farg5, f15);
  67 REGISTER_DECLARATION(FloatRegister, c_farg6, f16);
  68 REGISTER_DECLARATION(FloatRegister, c_farg7, f17);
  69 
  70 // java function register(caller-save registers)
  71 REGISTER_DECLARATION(Register, j_rarg0, c_rarg1);
  72 REGISTER_DECLARATION(Register, j_rarg1, c_rarg2);
  73 REGISTER_DECLARATION(Register, j_rarg2, c_rarg3);
  74 REGISTER_DECLARATION(Register, j_rarg3, c_rarg4);
  75 REGISTER_DECLARATION(Register, j_rarg4, c_rarg5);
  76 REGISTER_DECLARATION(Register, j_rarg5, c_rarg6);
  77 REGISTER_DECLARATION(Register, j_rarg6, c_rarg7);
  78 REGISTER_DECLARATION(Register, j_rarg7, c_rarg0);
  79 
  80 REGISTER_DECLARATION(FloatRegister, j_farg0, f10);
  81 REGISTER_DECLARATION(FloatRegister, j_farg1, f11);
  82 REGISTER_DECLARATION(FloatRegister, j_farg2, f12);
  83 REGISTER_DECLARATION(FloatRegister, j_farg3, f13);
  84 REGISTER_DECLARATION(FloatRegister, j_farg4, f14);
  85 REGISTER_DECLARATION(FloatRegister, j_farg5, f15);
  86 REGISTER_DECLARATION(FloatRegister, j_farg6, f16);
  87 REGISTER_DECLARATION(FloatRegister, j_farg7, f17);
  88 
  89 // zero rigster
  90 REGISTER_DECLARATION(Register, zr,        x0);
  91 // global pointer
  92 REGISTER_DECLARATION(Register, gp,        x3);
  93 // thread pointer
  94 REGISTER_DECLARATION(Register, tp,        x4);
  95 
  96 // volatile (caller-save) registers
  97 
  98 // current method -- must be in a call-clobbered register
  99 REGISTER_DECLARATION(Register, xmethod,   x31);
 100 // return address
 101 REGISTER_DECLARATION(Register, ra,        x1);
 102 
 103 // non-volatile (callee-save) registers
 104 
 105 // stack pointer
 106 REGISTER_DECLARATION(Register, sp,        x2);
 107 // frame pointer
 108 REGISTER_DECLARATION(Register, fp,        x8);
 109 // base of heap
 110 REGISTER_DECLARATION(Register, xheapbase, x27);
 111 // constant pool cache
 112 REGISTER_DECLARATION(Register, xcpool,    x26);
 113 // monitors allocated on stack
 114 REGISTER_DECLARATION(Register, xmonitors, x25);
 115 // locals on stack
 116 REGISTER_DECLARATION(Register, xlocals,   x24);
 117 
 118 /* If you use x4(tp) as java thread pointer according to the instruction manual,
 119  * it overlaps with the register used by c++ thread.
 120  */
 121 // java thread pointer
 122 REGISTER_DECLARATION(Register, xthread,   x23);
 123 // bytecode pointer
 124 REGISTER_DECLARATION(Register, xbcp,      x22);
 125 // Dispatch table base
 126 REGISTER_DECLARATION(Register, xdispatch, x21);
 127 // Java stack pointer
 128 REGISTER_DECLARATION(Register, esp,       x20);
 129 
 130 // tempory register(caller-save registers)
 131 REGISTER_DECLARATION(Register, t0, x5);
 132 REGISTER_DECLARATION(Register, t1, x6);
 133 REGISTER_DECLARATION(Register, t2, x7);
 134 
 135 const Register g_INTArgReg[Argument::n_int_register_parameters_c] = {
 136   c_rarg0, c_rarg1, c_rarg2, c_rarg3, c_rarg4, c_rarg5,  c_rarg6,  c_rarg7
 137 };
 138 
 139 const FloatRegister g_FPArgReg[Argument::n_float_register_parameters_c] = {
 140   c_farg0, c_farg1, c_farg2, c_farg3, c_farg4, c_farg5, c_farg6, c_farg7
 141 };
 142 
 143 #define assert_cond(ARG1) assert(ARG1, #ARG1)
 144 
 145 // Addressing modes
 146 class Address {
 147  public:
 148 
 149   enum mode { no_mode, base_plus_offset, pcrel, literal };
 150 
 151  private:
 152   Register _base;
 153   Register _index;
 154   int64_t _offset;
 155   enum mode _mode;
 156 
 157   RelocationHolder _rspec;
 158 
 159   // If the target is far we'll need to load the ea of this to a
 160   // register to reach it. Otherwise if near we can do PC-relative
 161   // addressing.
 162   address          _target;
 163 
 164  public:
 165   Address()
 166     : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { }
 167   Address(Register r)
 168     : _base(r),     _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { }
 169   Address(Register r, int o)
 170     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 171   Address(Register r, long o)
 172     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 173   Address(Register r, long long o)
 174     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 175   Address(Register r, unsigned int o)
 176     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 177   Address(Register r, unsigned long o)
 178     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 179   Address(Register r, unsigned long long o)
 180     : _base(r),     _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { }
 181   Address(Register r, ByteSize disp)
 182     : Address(r, in_bytes(disp)) {}
 183   Address(address target, RelocationHolder const& rspec)
 184     : _base(noreg),
 185       _index(noreg),
 186       _offset(0),
 187       _mode(literal),
 188       _rspec(rspec),
 189       _target(target) { }
 190   Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);
 191 
 192   const Register base() const {
 193     guarantee((_mode == base_plus_offset | _mode == pcrel | _mode == literal), "wrong mode");
 194     return _base;
 195   }
 196   long offset() const {
 197     return _offset;
 198   }
 199   Register index() const {
 200     return _index;
 201   }
 202   mode getMode() const {
 203     return _mode;
 204   }
 205 
 206   bool uses(Register reg) const { return _base == reg; }
 207   const address target() const { return _target; }
 208   const RelocationHolder& rspec() const { return _rspec; }
 209   ~Address() {
 210     _target = NULL;
 211     _base = NULL;
 212   }
 213 };
 214 
 215 // Convience classes
 216 class RuntimeAddress: public Address {
 217 
 218   public:
 219 
 220   RuntimeAddress(address target) : Address(target, relocInfo::runtime_call_type) {}
 221   ~RuntimeAddress() {}
 222 };
 223 
 224 class OopAddress: public Address {
 225 
 226   public:
 227 
 228   OopAddress(address target) : Address(target, relocInfo::oop_type) {}
 229   ~OopAddress() {}
 230 };
 231 
 232 class ExternalAddress: public Address {
 233  private:
 234   static relocInfo::relocType reloc_for_target(address target) {
 235     // Sometimes ExternalAddress is used for values which aren't
 236     // exactly addresses, like the card table base.
 237     // external_word_type can't be used for values in the first page
 238     // so just skip the reloc in that case.
 239     return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none;
 240   }
 241 
 242  public:
 243 
 244   ExternalAddress(address target) : Address(target, reloc_for_target(target)) {}
 245   ~ExternalAddress() {}
 246 };
 247 
 248 class InternalAddress: public Address {
 249 
 250   public:
 251 
 252   InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {}
 253   ~InternalAddress() {}
 254 };
 255 
 256 class Assembler : public AbstractAssembler {
 257 public:
 258 
 259   enum { instruction_size = 4 };
 260 
 261   //---<  calculate length of instruction  >---
 262   // We just use the values set above.
 263   // instruction must start at passed address
 264   static unsigned int instr_len(unsigned char *instr) { return instruction_size; }
 265 
 266   //---<  longest instructions  >---
 267   static unsigned int instr_maxlen() { return instruction_size; }
 268 
 269   enum RoundingMode {
 270     rne = 0b000,     // round to Nearest, ties to Even
 271     rtz = 0b001,     // round towards Zero
 272     rdn = 0b010,     // round Down (towards eegative infinity)
 273     rup = 0b011,     // round Up (towards infinity)
 274     rmm = 0b100,     // round to Nearest, ties to Max Magnitude
 275     rdy = 0b111,     // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid.
 276   };
 277 
 278   void baseOffset32(Register temp, const Address &adr, int32_t &offset) {
 279     assert(temp != noreg, "temp must not be empty register!");
 280     guarantee(adr.base() != temp, "should use different registers!");
 281     if (is_offset_in_range(adr.offset(), 32)) {
 282       int32_t imm = adr.offset();
 283       int32_t upper = imm, lower = imm;
 284       lower = (imm << 20) >> 20;
 285       upper -= lower;
 286       lui(temp, upper);
 287       offset = lower;
 288     } else {
 289       movptr_with_offset(temp, (address)(uintptr_t)adr.offset(), offset);
 290     }
 291     add(temp, temp, adr.base());
 292   }
 293 
 294   void baseOffset(Register temp, const Address &adr, int32_t &offset) {
 295     if (is_offset_in_range(adr.offset(), 12)) {
 296       assert(temp != noreg, "temp must not be empty register!");
 297       addi(temp, adr.base(), adr.offset());
 298       offset = 0;
 299     } else {
 300       baseOffset32(temp, adr, offset);
 301     }
 302   }
 303 
 304   void _li(Register Rd, int64_t imm);  // optimized load immediate
 305   void li32(Register Rd, int32_t imm);
 306   void li64(Register Rd, int64_t imm);
 307   void movptr(Register Rd, address addr);
 308   void movptr_with_offset(Register Rd, address addr, int32_t &offset);
 309   void movptr(Register Rd, uintptr_t imm64);
 310   void ifence();
 311   void j(const address &dest, Register temp = t0);
 312   void j(const Address &adr, Register temp = t0) ;
 313   void j(Label &l, Register temp = t0);
 314   void jal(Label &l, Register temp = t0);
 315   void jal(const address &dest, Register temp = t0);
 316   void jal(const Address &adr, Register temp = t0);
 317   void jr(Register Rs);
 318   void jalr(Register Rs);
 319   void ret();
 320   void call(const address &dest, Register temp = t0);
 321   void call(const Address &adr, Register temp = t0);
 322   void tail(const address &dest, Register temp = t0);
 323   void tail(const Address &adr, Register temp = t0);
 324   void call(Label &l, Register temp) {
 325     call(target(l), temp);
 326   }
 327   void tail(Label &l, Register temp) {
 328     tail(target(l), temp);
 329   }
 330 
 331   static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) {
 332     assert_cond(msb >= lsb && msb <= 31);
 333     unsigned nbits = msb - lsb + 1;
 334     uint32_t mask = (1U << nbits) - 1;
 335     uint32_t result = val >> lsb;
 336     result &= mask;
 337     return result;
 338   }
 339 
 340   static inline int32_t sextract(uint32_t val, unsigned msb, unsigned lsb) {
 341     assert_cond(msb >= lsb && msb <= 31);
 342     int32_t result = val << (31 - msb);
 343     result >>= (31 - msb + lsb);
 344     return result;
 345   }
 346 
 347   static void patch(address a, unsigned msb, unsigned lsb, unsigned val) {
 348     assert_cond(a != NULL);
 349     assert_cond(msb >= lsb && msb <= 31);
 350     unsigned nbits = msb - lsb + 1;
 351     guarantee(val < (1U << nbits), "Field too big for insn");
 352     unsigned mask = (1U << nbits) - 1;
 353     val <<= lsb;
 354     mask <<= lsb;
 355     unsigned target = *(unsigned *)a;
 356     target &= ~mask;
 357     target |= val;
 358     *(unsigned *)a = target;
 359   }
 360 
 361   static void patch(address a, unsigned bit, unsigned val) {
 362     patch(a, bit, bit, val);
 363   }
 364 
 365   static void patch_reg(address a, unsigned lsb, Register reg) {
 366     patch(a, lsb + 4, lsb, reg->encoding_nocheck());
 367   }
 368 
 369   static void patch_reg(address a, unsigned lsb, FloatRegister reg) {
 370     patch(a, lsb + 4, lsb, reg->encoding_nocheck());
 371   }
 372 
 373   static void patch_reg(address a, unsigned lsb, VectorRegister reg) {
 374     patch(a, lsb + 4, lsb, reg->encoding_nocheck());
 375   }
 376 
 377   void emit(unsigned insn) {
 378     emit_int32((jint)insn);
 379   }
 380 
 381   void _halt() {
 382     emit_int32(0);
 383   }
 384 
 385 // Register Instruction
 386 #define INSN(NAME, op, funct3, funct7)                          \
 387   void NAME(Register Rd, Register Rs1, Register Rs2) {          \
 388     unsigned insn = 0;                                          \
 389     patch((address)&insn, 6,  0, op);                           \
 390     patch((address)&insn, 14, 12, funct3);                      \
 391     patch((address)&insn, 31, 25, funct7);                      \
 392     patch_reg((address)&insn, 7, Rd);                           \
 393     patch_reg((address)&insn, 15, Rs1);                         \
 394     patch_reg((address)&insn, 20, Rs2);                         \
 395     emit(insn);                                                 \
 396   }
 397 
 398   INSN(_add,  0b0110011, 0b000, 0b0000000);
 399   INSN(_sub,  0b0110011, 0b000, 0b0100000);
 400   INSN(_andr, 0b0110011, 0b111, 0b0000000);
 401   INSN(_orr,  0b0110011, 0b110, 0b0000000);
 402   INSN(_xorr, 0b0110011, 0b100, 0b0000000);
 403   INSN(sll,   0b0110011, 0b001, 0b0000000);
 404   INSN(sra,   0b0110011, 0b101, 0b0100000);
 405   INSN(srl,   0b0110011, 0b101, 0b0000000);
 406   INSN(slt,   0b0110011, 0b010, 0b0000000);
 407   INSN(sltu,  0b0110011, 0b011, 0b0000000);
 408   INSN(_addw, 0b0111011, 0b000, 0b0000000);
 409   INSN(_subw, 0b0111011, 0b000, 0b0100000);
 410   INSN(sllw,  0b0111011, 0b001, 0b0000000);
 411   INSN(sraw,  0b0111011, 0b101, 0b0100000);
 412   INSN(srlw,  0b0111011, 0b101, 0b0000000);
 413   INSN(mul,   0b0110011, 0b000, 0b0000001);
 414   INSN(mulh,  0b0110011, 0b001, 0b0000001);
 415   INSN(mulhsu,0b0110011, 0b010, 0b0000001);
 416   INSN(mulhu, 0b0110011, 0b011, 0b0000001);
 417   INSN(mulw,  0b0111011, 0b000, 0b0000001);
 418   INSN(div,   0b0110011, 0b100, 0b0000001);
 419   INSN(divu,  0b0110011, 0b101, 0b0000001);
 420   INSN(divw,  0b0111011, 0b100, 0b0000001);
 421   INSN(divuw, 0b0111011, 0b101, 0b0000001);
 422   INSN(rem,   0b0110011, 0b110, 0b0000001);
 423   INSN(remu,  0b0110011, 0b111, 0b0000001);
 424   INSN(remw,  0b0111011, 0b110, 0b0000001);
 425   INSN(remuw, 0b0111011, 0b111, 0b0000001);
 426 
 427 #undef INSN
 428 
 429 #define INSN_ENTRY_RELOC(result_type, header)                               \
 430   result_type header {                                                      \
 431     InstructionMark im(this);                                               \
 432     guarantee(rtype == relocInfo::internal_word_type,                       \
 433               "only internal_word_type relocs make sense here");            \
 434     code_section()->relocate(inst_mark(), InternalAddress(dest).rspec());
 435 
 436   // Load/store register (all modes)
 437 #define INSN(NAME, op, funct3)                                                                     \
 438   void NAME(Register Rd, Register Rs, const int32_t offset) {                                      \
 439     guarantee(is_offset_in_range(offset, 12), "offset is invalid.");                               \
 440     unsigned insn = 0;                                                                             \
 441     int32_t val = offset & 0xfff;                                                                  \
 442     patch((address)&insn, 6, 0, op);                                                               \
 443     patch((address)&insn, 14, 12, funct3);                                                         \
 444     patch_reg((address)&insn, 15, Rs);                                                             \
 445     patch_reg((address)&insn, 7, Rd);                                                              \
 446     patch((address)&insn, 31, 20, val);                                                            \
 447     emit(insn);                                                                                    \
 448   }
 449 
 450   INSN(lb,  0b0000011, 0b000);
 451   INSN(lbu, 0b0000011, 0b100);
 452   INSN(lh,  0b0000011, 0b001);
 453   INSN(lhu, 0b0000011, 0b101);
 454   INSN(_lw, 0b0000011, 0b010);
 455   INSN(lwu, 0b0000011, 0b110);
 456   INSN(_ld, 0b0000011, 0b011);
 457 
 458 #undef INSN
 459 
 460 #define INSN(NAME)                                                                                 \
 461   void NAME(Register Rd, address dest) {                                                           \
 462     assert_cond(dest != NULL);                                                                     \
 463     int64_t distance = (dest - pc());                                                              \
 464     if (is_offset_in_range(distance, 32)) {                                                        \
 465       auipc(Rd, (int32_t)distance + 0x800);                                                        \
 466       NAME(Rd, Rd, ((int32_t)distance << 20) >> 20);                                               \
 467     } else {                                                                                       \
 468       int32_t offset = 0;                                                                          \
 469       movptr_with_offset(Rd, dest, offset);                                                        \
 470       NAME(Rd, Rd, offset);                                                                        \
 471     }                                                                                              \
 472   }                                                                                                \
 473   INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype))              \
 474     NAME(Rd, dest);                                                                                \
 475   }                                                                                                \
 476   void NAME(Register Rd, const Address &adr, Register temp = t0) {                                 \
 477     switch (adr.getMode()) {                                                                       \
 478       case Address::literal: {                                                                     \
 479         code_section()->relocate(pc(), adr.rspec());                                               \
 480         NAME(Rd, adr.target());                                                                    \
 481         break;                                                                                     \
 482       }                                                                                            \
 483       case Address::base_plus_offset: {                                                            \
 484         if (is_offset_in_range(adr.offset(), 12)) {                                                \
 485           NAME(Rd, adr.base(), adr.offset());                                                      \
 486         } else {                                                                                   \
 487           int32_t offset = 0;                                                                      \
 488           if (Rd == adr.base()) {                                                                  \
 489             baseOffset32(temp, adr, offset);                                                       \
 490             NAME(Rd, temp, offset);                                                                \
 491           } else {                                                                                 \
 492             baseOffset32(Rd, adr, offset);                                                         \
 493             NAME(Rd, Rd, offset);                                                                  \
 494           }                                                                                        \
 495         }                                                                                          \
 496         break;                                                                                     \
 497       }                                                                                            \
 498       default:                                                                                     \
 499         ShouldNotReachHere();                                                                      \
 500     }                                                                                              \
 501   }                                                                                                \
 502   void NAME(Register Rd, Label &L) {                                                               \
 503     wrap_label(Rd, L, &Assembler::NAME);                                                           \
 504   }
 505 
 506   INSN(lb);
 507   INSN(lbu);
 508   INSN(lh);
 509   INSN(lhu);
 510   INSN(lw);
 511   INSN(lwu);
 512   INSN(ld);
 513 
 514 #undef INSN
 515 
 516 #define INSN(NAME, op, funct3)                                                                     \
 517   void NAME(FloatRegister Rd, Register Rs, const int32_t offset) {                                 \
 518     guarantee(is_offset_in_range(offset, 12), "offset is invalid.");                               \
 519     unsigned insn = 0;                                                                             \
 520     uint32_t val = offset & 0xfff;                                                                 \
 521     patch((address)&insn, 6, 0, op);                                                               \
 522     patch((address)&insn, 14, 12, funct3);                                                         \
 523     patch_reg((address)&insn, 15, Rs);                                                             \
 524     patch_reg((address)&insn, 7, Rd);                                                              \
 525     patch((address)&insn, 31, 20, val);                                                            \
 526     emit(insn);                                                                                    \
 527   }
 528 
 529   INSN(flw,  0b0000111, 0b010);
 530   INSN(_fld, 0b0000111, 0b011);
 531 
 532 #undef INSN
 533 
 534 #define INSN(NAME)                                                                                 \
 535   void NAME(FloatRegister Rd, address dest, Register temp = t0) {                                  \
 536     assert_cond(dest != NULL);                                                                     \
 537     int64_t distance = (dest - pc());                                                              \
 538     if (is_offset_in_range(distance, 32)) {                                                        \
 539       auipc(temp, (int32_t)distance + 0x800);                                                      \
 540       NAME(Rd, temp, ((int32_t)distance << 20) >> 20);                                             \
 541     } else {                                                                                       \
 542       int32_t offset = 0;                                                                          \
 543       movptr_with_offset(temp, dest, offset);                                                      \
 544       NAME(Rd, temp, offset);                                                                      \
 545     }                                                                                              \
 546   }                                                                                                \
 547   INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, relocInfo::relocType rtype, Register temp = t0)) \
 548     NAME(Rd, dest, temp);                                                                          \
 549   }                                                                                                \
 550   void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) {                            \
 551     switch (adr.getMode()) {                                                                       \
 552       case Address::literal: {                                                                     \
 553         code_section()->relocate(pc(), adr.rspec());                                               \
 554         NAME(Rd, adr.target(), temp);                                                              \
 555         break;                                                                                     \
 556       }                                                                                            \
 557       case Address::base_plus_offset: {                                                            \
 558         if (is_offset_in_range(adr.offset(), 12)) {                                                \
 559           NAME(Rd, adr.base(), adr.offset());                                                      \
 560         } else {                                                                                   \
 561           int32_t offset = 0;                                                                      \
 562           baseOffset32(temp, adr, offset);                                                         \
 563           NAME(Rd, temp, offset);                                                                  \
 564         }                                                                                          \
 565         break;                                                                                     \
 566       }                                                                                            \
 567       default:                                                                                     \
 568         ShouldNotReachHere();                                                                      \
 569     }                                                                                              \
 570   }
 571 
 572   INSN(flw);
 573   INSN(fld);
 574 #undef INSN
 575 
 576 #define INSN(NAME, op, funct3)                                                                           \
 577   void NAME(Register Rs1, Register Rs2, const int64_t offset) {                                          \
 578     guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid.");                                     \
 579     unsigned insn = 0;                                                                                   \
 580     uint32_t val  = offset & 0x1fff;                                                                     \
 581     uint32_t val11 = (val >> 11) & 0x1;                                                                  \
 582     uint32_t val12 = (val >> 12) & 0x1;                                                                  \
 583     uint32_t low  = (val >> 1) & 0xf;                                                                    \
 584     uint32_t high = (val >> 5) & 0x3f;                                                                   \
 585     patch((address)&insn, 6, 0, op);                                                                     \
 586     patch((address)&insn, 14, 12, funct3);                                                               \
 587     patch_reg((address)&insn, 15, Rs1);                                                                  \
 588     patch_reg((address)&insn, 20, Rs2);                                                                  \
 589     patch((address)&insn, 7, val11);                                                                     \
 590     patch((address)&insn, 11, 8, low);                                                                   \
 591     patch((address)&insn, 30, 25, high);                                                                 \
 592     patch((address)&insn, 31, val12);                                                                    \
 593     emit(insn);                                                                                          \
 594   }
 595 
 596   INSN(_beq, 0b1100011, 0b000);
 597   INSN(_bne, 0b1100011, 0b001);
 598   INSN(bge,  0b1100011, 0b101);
 599   INSN(bgeu, 0b1100011, 0b111);
 600   INSN(blt,  0b1100011, 0b100);
 601   INSN(bltu, 0b1100011, 0b110);
 602 
 603 #undef INSN
 604 
 605 #define INSN(NAME)                                                                                       \
 606   void NAME(Register Rs1, Register Rs2, const address dest) {                                            \
 607     assert_cond(dest != NULL);                                                                           \
 608     int64_t offset = (dest - pc());                                                                      \
 609     guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid.");                                     \
 610     NAME(Rs1, Rs2, offset);                                                                              \
 611   }                                                                                                      \
 612   INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype))     \
 613     NAME(Rs1, Rs2, dest);                                                                                \
 614   }
 615 
 616   INSN(beq);
 617   INSN(bne);
 618   INSN(bge);
 619   INSN(bgeu);
 620   INSN(blt);
 621   INSN(bltu);
 622 
 623 #undef INSN
 624 
 625 #define INSN(NAME, NEG_INSN)                                                                \
 626   void NAME(Register Rs1, Register Rs2, Label &L, bool is_far = false) {                    \
 627     wrap_label(Rs1, Rs2, L, &Assembler::NAME, &Assembler::NEG_INSN, is_far);                \
 628   }
 629 
 630   INSN(beq,  bne);
 631   INSN(bne,  beq);
 632   INSN(blt,  bge);
 633   INSN(bge,  blt);
 634   INSN(bltu, bgeu);
 635   INSN(bgeu, bltu);
 636 
 637 #undef INSN
 638 
 639 #define INSN(NAME, REGISTER, op, funct3)                                                                    \
 640   void NAME(REGISTER Rs1, Register Rs2, const int32_t offset) {                                             \
 641     guarantee(is_offset_in_range(offset, 12), "offset is invalid.");                                        \
 642     unsigned insn = 0;                                                                                      \
 643     uint32_t val  = offset & 0xfff;                                                                         \
 644     uint32_t low  = val & 0x1f;                                                                             \
 645     uint32_t high = (val >> 5) & 0x7f;                                                                      \
 646     patch((address)&insn, 6, 0, op);                                                                        \
 647     patch((address)&insn, 14, 12, funct3);                                                                  \
 648     patch_reg((address)&insn, 15, Rs2);                                                                     \
 649     patch_reg((address)&insn, 20, Rs1);                                                                     \
 650     patch((address)&insn, 11, 7, low);                                                                      \
 651     patch((address)&insn, 31, 25, high);                                                                    \
 652     emit(insn);                                                                                             \
 653   }                                                                                                         \
 654 
 655   INSN(sb,   Register,      0b0100011, 0b000);
 656   INSN(sh,   Register,      0b0100011, 0b001);
 657   INSN(_sw,  Register,      0b0100011, 0b010);
 658   INSN(_sd,  Register,      0b0100011, 0b011);
 659   INSN(fsw,  FloatRegister, 0b0100111, 0b010);
 660   INSN(_fsd, FloatRegister, 0b0100111, 0b011);
 661 
 662 #undef INSN
 663 
 664 #define INSN(NAME, REGISTER)                                                                                \
 665   INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, relocInfo::relocType rtype, Register temp = t0))   \
 666     NAME(Rs, dest, temp);                                                                                   \
 667   }
 668 
 669   INSN(sb,  Register);
 670   INSN(sh,  Register);
 671   INSN(sw,  Register);
 672   INSN(sd,  Register);
 673   INSN(fsw, FloatRegister);
 674   INSN(fsd, FloatRegister);
 675 
 676 #undef INSN
 677 
 678 #define INSN(NAME)                                                                                 \
 679   void NAME(Register Rs, address dest, Register temp = t0) {                                       \
 680     assert_cond(dest != NULL);                                                                     \
 681     assert_different_registers(Rs, temp);                                                          \
 682     int64_t distance = (dest - pc());                                                              \
 683     if (is_offset_in_range(distance, 32)) {                                                        \
 684       auipc(temp, (int32_t)distance + 0x800);                                                      \
 685       NAME(Rs, temp, ((int32_t)distance << 20) >> 20);                                             \
 686     } else {                                                                                       \
 687       int32_t offset = 0;                                                                          \
 688       movptr_with_offset(temp, dest, offset);                                                      \
 689       NAME(Rs, temp, offset);                                                                      \
 690     }                                                                                              \
 691   }                                                                                                \
 692   void NAME(Register Rs, const Address &adr, Register temp = t0) {                                 \
 693     switch (adr.getMode()) {                                                                       \
 694       case Address::literal: {                                                                     \
 695         assert_different_registers(Rs, temp);                                                      \
 696         code_section()->relocate(pc(), adr.rspec());                                               \
 697         NAME(Rs, adr.target(), temp);                                                              \
 698         break;                                                                                     \
 699       }                                                                                            \
 700       case Address::base_plus_offset: {                                                            \
 701         if (is_offset_in_range(adr.offset(), 12)) {                                                \
 702           NAME(Rs, adr.base(), adr.offset());                                                      \
 703         } else {                                                                                   \
 704           int32_t offset= 0;                                                                       \
 705           assert_different_registers(Rs, temp);                                                    \
 706           baseOffset32(temp, adr, offset);                                                         \
 707           NAME(Rs, temp, offset);                                                                  \
 708         }                                                                                          \
 709         break;                                                                                     \
 710       }                                                                                            \
 711       default:                                                                                     \
 712         ShouldNotReachHere();                                                                      \
 713     }                                                                                              \
 714   }
 715 
 716   INSN(sb);
 717   INSN(sh);
 718   INSN(sw);
 719   INSN(sd);
 720 
 721 #undef INSN
 722 
 723 #define INSN(NAME)                                                                                 \
 724   void NAME(FloatRegister Rs, address dest, Register temp = t0) {                                  \
 725     assert_cond(dest != NULL);                                                                     \
 726     int64_t distance = (dest - pc());                                                              \
 727     if (is_offset_in_range(distance, 32)) {                                                        \
 728       auipc(temp, (int32_t)distance + 0x800);                                                      \
 729       NAME(Rs, temp, ((int32_t)distance << 20) >> 20);                                             \
 730     } else {                                                                                       \
 731       int32_t offset = 0;                                                                          \
 732       movptr_with_offset(temp, dest, offset);                                                      \
 733       NAME(Rs, temp, offset);                                                                      \
 734     }                                                                                              \
 735   }                                                                                                \
 736   void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) {                            \
 737     switch (adr.getMode()) {                                                                       \
 738       case Address::literal: {                                                                     \
 739         code_section()->relocate(pc(), adr.rspec());                                               \
 740         NAME(Rs, adr.target(), temp);                                                              \
 741         break;                                                                                     \
 742       }                                                                                            \
 743       case Address::base_plus_offset: {                                                            \
 744         if (is_offset_in_range(adr.offset(), 12)) {                                                \
 745           NAME(Rs, adr.base(), adr.offset());                                                      \
 746         } else {                                                                                   \
 747           int32_t offset = 0;                                                                      \
 748           baseOffset32(temp, adr, offset);                                                         \
 749           NAME(Rs, temp, offset);                                                                  \
 750         }                                                                                          \
 751         break;                                                                                     \
 752       }                                                                                            \
 753       default:                                                                                     \
 754         ShouldNotReachHere();                                                                      \
 755     }                                                                                              \
 756   }
 757 
 758   INSN(fsw);
 759   INSN(fsd);
 760 
 761 #undef INSN
 762 
 763 #define INSN(NAME, op, funct3)                                                        \
 764   void NAME(Register Rd, const uint32_t csr, Register Rs1) {                          \
 765     guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid");                \
 766     unsigned insn = 0;                                                                \
 767     patch((address)&insn, 6, 0, op);                                                  \
 768     patch((address)&insn, 14, 12, funct3);                                            \
 769     patch_reg((address)&insn, 7, Rd);                                                 \
 770     patch_reg((address)&insn, 15, Rs1);                                               \
 771     patch((address)&insn, 31, 20, csr);                                               \
 772     emit(insn);                                                                       \
 773   }
 774 
 775   INSN(csrrw, 0b1110011, 0b001);
 776   INSN(csrrs, 0b1110011, 0b010);
 777   INSN(csrrc, 0b1110011, 0b011);
 778 
 779 #undef INSN
 780 
 781 #define INSN(NAME, op, funct3)                                                        \
 782   void NAME(Register Rd, const uint32_t csr, const uint32_t uimm) {                   \
 783     guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid");                \
 784     guarantee(is_unsigned_imm_in_range(uimm, 5, 0), "uimm is invalid");               \
 785     unsigned insn = 0;                                                                \
 786     uint32_t val  = uimm & 0x1f;                                                      \
 787     patch((address)&insn, 6, 0, op);                                                  \
 788     patch((address)&insn, 14, 12, funct3);                                            \
 789     patch_reg((address)&insn, 7, Rd);                                                 \
 790     patch((address)&insn, 19, 15, val);                                               \
 791     patch((address)&insn, 31, 20, csr);                                               \
 792     emit(insn);                                                                       \
 793   }
 794 
 795   INSN(csrrwi, 0b1110011, 0b101);
 796   INSN(csrrsi, 0b1110011, 0b110);
 797   INSN(csrrci, 0b1110011, 0b111);
 798 
 799 #undef INSN
 800 
 801 #define INSN(NAME, op)                                                                        \
 802   void NAME(Register Rd, const int32_t offset) {                                              \
 803     guarantee(is_imm_in_range(offset, 20, 1), "offset is invalid.");                          \
 804     unsigned insn = 0;                                                                        \
 805     patch((address)&insn, 6, 0, op);                                                          \
 806     patch_reg((address)&insn, 7, Rd);                                                         \
 807     patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff));                         \
 808     patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1));                              \
 809     patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff));                         \
 810     patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1));                              \
 811     emit(insn);                                                                               \
 812   }
 813 
 814   INSN(_jal, 0b1101111);
 815 
 816 #undef INSN
 817 
 818 #define INSN(NAME)                                                                            \
 819   void NAME(Register Rd, const address dest, Register temp = t0) {                            \
 820     assert_cond(dest != NULL);                                                                \
 821     int64_t offset = dest - pc();                                                             \
 822     if (is_imm_in_range(offset, 20, 1)) {                                                     \
 823       NAME(Rd, offset);                                                                       \
 824     } else {                                                                                  \
 825       assert_different_registers(Rd, temp);                                                   \
 826       int32_t off = 0;                                                                        \
 827       movptr_with_offset(temp, dest, off);                                                    \
 828       jalr(Rd, temp, off);                                                                    \
 829     }                                                                                         \
 830   }                                                                                           \
 831   void NAME(Register Rd, Label &L, Register temp = t0) {                                      \
 832     assert_different_registers(Rd, temp);                                                     \
 833     wrap_label(Rd, L, temp, &Assembler::NAME);                                                \
 834   }
 835 
 836   INSN(jal);
 837 
 838 #undef INSN
 839 
 840 #undef INSN_ENTRY_RELOC
 841 
 842 #define INSN(NAME, op, funct)                                                              \
 843   void NAME(Register Rd, Register Rs, const int32_t offset) {                              \
 844     guarantee(is_offset_in_range(offset, 12), "offset is invalid.");                       \
 845     unsigned insn = 0;                                                                     \
 846     patch((address)&insn, 6, 0, op);                                                       \
 847     patch_reg((address)&insn, 7, Rd);                                                      \
 848     patch((address)&insn, 14, 12, funct);                                                  \
 849     patch_reg((address)&insn, 15, Rs);                                                     \
 850     int32_t val = offset & 0xfff;                                                          \
 851     patch((address)&insn, 31, 20, val);                                                    \
 852     emit(insn);                                                                            \
 853   }
 854 
 855   INSN(_jalr, 0b1100111, 0b000);
 856 
 857 #undef INSN
 858 
 859   enum barrier {
 860     i = 0b1000, o = 0b0100, r = 0b0010, w = 0b0001,
 861     ir = i | r, ow = o | w, iorw = i | o | r | w
 862   };
 863 
 864   void fence(const uint32_t predecessor, const uint32_t successor) {
 865     unsigned insn = 0;
 866     guarantee(predecessor < 16, "predecessor is invalid");
 867     guarantee(successor < 16, "successor is invalid");
 868     patch((address)&insn, 6, 0, 0b001111);
 869     patch((address)&insn, 11, 7, 0b00000);
 870     patch((address)&insn, 14, 12, 0b000);
 871     patch((address)&insn, 19, 15, 0b00000);
 872     patch((address)&insn, 23, 20, successor);
 873     patch((address)&insn, 27, 24, predecessor);
 874     patch((address)&insn, 31, 28, 0b0000);
 875     emit(insn);
 876   }
 877 
 878 #define INSN(NAME, op, funct3, funct7)                      \
 879   void NAME() {                                             \
 880     unsigned insn = 0;                                      \
 881     patch((address)&insn, 6, 0, op);                        \
 882     patch((address)&insn, 11, 7, 0b00000);                  \
 883     patch((address)&insn, 14, 12, funct3);                  \
 884     patch((address)&insn, 19, 15, 0b00000);                 \
 885     patch((address)&insn, 31, 20, funct7);                  \
 886     emit(insn);                                             \
 887   }
 888 
 889   INSN(fence_i, 0b0001111, 0b001, 0b000000000000);
 890   INSN(ecall,   0b1110011, 0b000, 0b000000000000);
 891   INSN(_ebreak, 0b1110011, 0b000, 0b000000000001);
 892 
 893 #undef INSN
 894 
 895 enum Aqrl {relaxed = 0b00, rl = 0b01, aq = 0b10, aqrl = 0b11};
 896 
 897 #define INSN(NAME, op, funct3, funct7)                                                  \
 898   void NAME(Register Rd, Register Rs1, Register Rs2, Aqrl memory_order = aqrl) {        \
 899     unsigned insn = 0;                                                                  \
 900     patch((address)&insn, 6, 0, op);                                                    \
 901     patch((address)&insn, 14, 12, funct3);                                              \
 902     patch_reg((address)&insn, 7, Rd);                                                   \
 903     patch_reg((address)&insn, 15, Rs1);                                                 \
 904     patch_reg((address)&insn, 20, Rs2);                                                 \
 905     patch((address)&insn, 31, 27, funct7);                                              \
 906     patch((address)&insn, 26, 25, memory_order);                                        \
 907     emit(insn);                                                                         \
 908   }
 909 
 910   INSN(amoswap_w, 0b0101111, 0b010, 0b00001);
 911   INSN(amoadd_w,  0b0101111, 0b010, 0b00000);
 912   INSN(amoxor_w,  0b0101111, 0b010, 0b00100);
 913   INSN(amoand_w,  0b0101111, 0b010, 0b01100);
 914   INSN(amoor_w,   0b0101111, 0b010, 0b01000);
 915   INSN(amomin_w,  0b0101111, 0b010, 0b10000);
 916   INSN(amomax_w,  0b0101111, 0b010, 0b10100);
 917   INSN(amominu_w, 0b0101111, 0b010, 0b11000);
 918   INSN(amomaxu_w, 0b0101111, 0b010, 0b11100);
 919   INSN(amoswap_d, 0b0101111, 0b011, 0b00001);
 920   INSN(amoadd_d,  0b0101111, 0b011, 0b00000);
 921   INSN(amoxor_d,  0b0101111, 0b011, 0b00100);
 922   INSN(amoand_d,  0b0101111, 0b011, 0b01100);
 923   INSN(amoor_d,   0b0101111, 0b011, 0b01000);
 924   INSN(amomin_d,  0b0101111, 0b011, 0b10000);
 925   INSN(amomax_d , 0b0101111, 0b011, 0b10100);
 926   INSN(amominu_d, 0b0101111, 0b011, 0b11000);
 927   INSN(amomaxu_d, 0b0101111, 0b011, 0b11100);
 928 #undef INSN
 929 
 930 enum operand_size { int8, int16, int32, uint32, int64 };
 931 
 932 #define INSN(NAME, op, funct3, funct7)                                              \
 933   void NAME(Register Rd, Register Rs1, Aqrl memory_order = relaxed) {               \
 934     unsigned insn = 0;                                                              \
 935     uint32_t val = memory_order & 0x3;                                              \
 936     patch((address)&insn, 6, 0, op);                                                \
 937     patch((address)&insn, 14, 12, funct3);                                          \
 938     patch_reg((address)&insn, 7, Rd);                                               \
 939     patch_reg((address)&insn, 15, Rs1);                                             \
 940     patch((address)&insn, 25, 20, 0b00000);                                         \
 941     patch((address)&insn, 31, 27, funct7);                                          \
 942     patch((address)&insn, 26, 25, val);                                             \
 943     emit(insn);                                                                     \
 944   }
 945 
 946   INSN(lr_w, 0b0101111, 0b010, 0b00010);
 947   INSN(lr_d, 0b0101111, 0b011, 0b00010);
 948 
 949 #undef INSN
 950 
 951 #define INSN(NAME, op, funct3, funct7)                                                      \
 952   void NAME(Register Rd, Register Rs1, Register Rs2, Aqrl memory_order = relaxed) {         \
 953     unsigned insn = 0;                                                                      \
 954     uint32_t val = memory_order & 0x3;                                                      \
 955     patch((address)&insn, 6, 0, op);                                                        \
 956     patch((address)&insn, 14, 12, funct3);                                                  \
 957     patch_reg((address)&insn, 7, Rd);                                                       \
 958     patch_reg((address)&insn, 15, Rs2);                                                     \
 959     patch_reg((address)&insn, 20, Rs1);                                                     \
 960     patch((address)&insn, 31, 27, funct7);                                                  \
 961     patch((address)&insn, 26, 25, val);                                                     \
 962     emit(insn);                                                                             \
 963   }
 964 
 965   INSN(sc_w, 0b0101111, 0b010, 0b00011);
 966   INSN(sc_d, 0b0101111, 0b011, 0b00011);
 967 #undef INSN
 968 
 969 #define INSN(NAME, op, funct5, funct7)                                                      \
 970   void NAME(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) {                   \
 971     unsigned insn = 0;                                                                      \
 972     patch((address)&insn, 6, 0, op);                                                        \
 973     patch((address)&insn, 14, 12, rm);                                                      \
 974     patch((address)&insn, 24, 20, funct5);                                                  \
 975     patch((address)&insn, 31, 25, funct7);                                                  \
 976     patch_reg((address)&insn, 7, Rd);                                                       \
 977     patch_reg((address)&insn, 15, Rs1);                                                     \
 978     emit(insn);                                                                             \
 979   }
 980 
 981   INSN(fsqrt_s,   0b1010011, 0b00000, 0b0101100);
 982   INSN(fsqrt_d,   0b1010011, 0b00000, 0b0101101);
 983   INSN(fcvt_s_d,  0b1010011, 0b00001, 0b0100000);
 984   INSN(fcvt_d_s,  0b1010011, 0b00000, 0b0100001);
 985 #undef INSN
 986 
 987 // Immediate Instruction
 988 #define INSN(NAME, op, funct3)                                                              \
 989   void NAME(Register Rd, Register Rs1, int32_t imm) {                                       \
 990     guarantee(is_imm_in_range(imm, 12, 0), "Immediate is out of validity");                 \
 991     unsigned insn = 0;                                                                      \
 992     patch((address)&insn, 6, 0, op);                                                        \
 993     patch((address)&insn, 14, 12, funct3);                                                  \
 994     patch((address)&insn, 31, 20, imm & 0x00000fff);                                        \
 995     patch_reg((address)&insn, 7, Rd);                                                       \
 996     patch_reg((address)&insn, 15, Rs1);                                                     \
 997     emit(insn);                                                                             \
 998   }
 999 
1000   INSN(_addi,      0b0010011, 0b000);
1001   INSN(slti,       0b0010011, 0b010);
1002   INSN(_addiw,     0b0011011, 0b000);
1003   INSN(_and_imm12, 0b0010011, 0b111);
1004   INSN(ori,        0b0010011, 0b110);
1005   INSN(xori,       0b0010011, 0b100);
1006 
1007 #undef INSN
1008 
1009 #define INSN(NAME, op, funct3)                                                              \
1010   void NAME(Register Rd, Register Rs1, uint32_t imm) {                                      \
1011     guarantee(is_unsigned_imm_in_range(imm, 12, 0), "Immediate is out of validity");        \
1012     unsigned insn = 0;                                                                      \
1013     patch((address)&insn,6, 0,  op);                                                        \
1014     patch((address)&insn, 14, 12, funct3);                                                  \
1015     patch((address)&insn, 31, 20, imm & 0x00000fff);                                        \
1016     patch_reg((address)&insn, 7, Rd);                                                       \
1017     patch_reg((address)&insn, 15, Rs1);                                                     \
1018     emit(insn);                                                                             \
1019   }
1020 
1021   INSN(sltiu, 0b0010011, 0b011);
1022 
1023 #undef INSN
1024 
1025 // Shift Immediate Instruction
1026 #define INSN(NAME, op, funct3, funct6)                                   \
1027   void NAME(Register Rd, Register Rs1, unsigned shamt) {                 \
1028     guarantee(shamt <= 0x3f, "Shamt is invalid");                        \
1029     unsigned insn = 0;                                                   \
1030     patch((address)&insn, 6, 0, op);                                     \
1031     patch((address)&insn, 14, 12, funct3);                               \
1032     patch((address)&insn, 25, 20, shamt);                                \
1033     patch((address)&insn, 31, 26, funct6);                               \
1034     patch_reg((address)&insn, 7, Rd);                                    \
1035     patch_reg((address)&insn, 15, Rs1);                                  \
1036     emit(insn);                                                          \
1037   }
1038 
1039   INSN(_slli, 0b0010011, 0b001, 0b000000);
1040   INSN(_srai, 0b0010011, 0b101, 0b010000);
1041   INSN(_srli, 0b0010011, 0b101, 0b000000);
1042 
1043 #undef INSN
1044 
1045 // Shift Word Immediate Instruction
1046 #define INSN(NAME, op, funct3, funct7)                                  \
1047   void NAME(Register Rd, Register Rs1, unsigned shamt) {                \
1048     guarantee(shamt <= 0x1f, "Shamt is invalid");                       \
1049     unsigned insn = 0;                                                  \
1050     patch((address)&insn, 6, 0, op);                                    \
1051     patch((address)&insn, 14, 12, funct3);                              \
1052     patch((address)&insn, 24, 20, shamt);                               \
1053     patch((address)&insn, 31, 25, funct7);                              \
1054     patch_reg((address)&insn, 7, Rd);                                   \
1055     patch_reg((address)&insn, 15, Rs1);                                 \
1056     emit(insn);                                                         \
1057   }
1058 
1059   INSN(slliw, 0b0011011, 0b001, 0b0000000);
1060   INSN(sraiw, 0b0011011, 0b101, 0b0100000);
1061   INSN(srliw, 0b0011011, 0b101, 0b0000000);
1062 
1063 #undef INSN
1064 
1065 // Upper Immediate Instruction
1066 #define INSN(NAME, op)                                                  \
1067   void NAME(Register Rd, int32_t imm) {                                 \
1068     int32_t upperImm = imm >> 12;                                       \
1069     unsigned insn = 0;                                                  \
1070     patch((address)&insn, 6, 0, op);                                    \
1071     patch_reg((address)&insn, 7, Rd);                                   \
1072     upperImm &= 0x000fffff;                                             \
1073     patch((address)&insn, 31, 12, upperImm);                            \
1074     emit(insn);                                                         \
1075   }
1076 
1077   INSN(_lui,  0b0110111);
1078   INSN(auipc, 0b0010111);
1079 
1080 #undef INSN
1081 
1082 // Float and Double Rigster Instruction
1083 #define INSN(NAME, op, funct2)                                                                                     \
1084   void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) {    \
1085     unsigned insn = 0;                                                                                             \
1086     patch((address)&insn, 6, 0, op);                                                                               \
1087     patch((address)&insn, 14, 12, rm);                                                                             \
1088     patch((address)&insn, 26, 25, funct2);                                                                         \
1089     patch_reg((address)&insn, 7, Rd);                                                                              \
1090     patch_reg((address)&insn, 15, Rs1);                                                                            \
1091     patch_reg((address)&insn, 20, Rs2);                                                                            \
1092     patch_reg((address)&insn, 27, Rs3);                                                                            \
1093     emit(insn);                                                                                                    \
1094   }
1095 
1096   INSN(fmadd_s,   0b1000011,  0b00);
1097   INSN(fmsub_s,   0b1000111,  0b00);
1098   INSN(fnmsub_s,  0b1001011,  0b00);
1099   INSN(fnmadd_s,  0b1001111,  0b00);
1100   INSN(fmadd_d,   0b1000011,  0b01);
1101   INSN(fmsub_d,   0b1000111,  0b01);
1102   INSN(fnmsub_d,  0b1001011,  0b01);
1103   INSN(fnmadd_d,  0b1001111,  0b01);
1104 
1105 #undef INSN
1106 
1107 // Float and Double Rigster Instruction
1108 #define INSN(NAME, op, funct3, funct7)                                        \
1109   void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) {         \
1110     unsigned insn = 0;                                                        \
1111     patch((address)&insn, 6, 0, op);                                          \
1112     patch((address)&insn, 14, 12, funct3);                                    \
1113     patch((address)&insn, 31, 25, funct7);                                    \
1114     patch_reg((address)&insn, 7, Rd);                                         \
1115     patch_reg((address)&insn, 15, Rs1);                                       \
1116     patch_reg((address)&insn, 20, Rs2);                                       \
1117     emit(insn);                                                               \
1118   }
1119 
1120   INSN(fsgnj_s,  0b1010011, 0b000, 0b0010000);
1121   INSN(fsgnjn_s, 0b1010011, 0b001, 0b0010000);
1122   INSN(fsgnjx_s, 0b1010011, 0b010, 0b0010000);
1123   INSN(fmin_s,   0b1010011, 0b000, 0b0010100);
1124   INSN(fmax_s,   0b1010011, 0b001, 0b0010100);
1125   INSN(fsgnj_d,  0b1010011, 0b000, 0b0010001);
1126   INSN(fsgnjn_d, 0b1010011, 0b001, 0b0010001);
1127   INSN(fsgnjx_d, 0b1010011, 0b010, 0b0010001);
1128   INSN(fmin_d,   0b1010011, 0b000, 0b0010101);
1129   INSN(fmax_d,   0b1010011, 0b001, 0b0010101);
1130 
1131 #undef INSN
1132 
1133 // Float and Double Rigster Arith Instruction
1134 #define INSN(NAME, op, funct3, funct7)                                    \
1135   void NAME(Register Rd, FloatRegister Rs1, FloatRegister Rs2) {          \
1136     unsigned insn = 0;                                                    \
1137     patch((address)&insn, 6, 0, op);                                      \
1138     patch((address)&insn, 14, 12, funct3);                                \
1139     patch((address)&insn, 31, 25, funct7);                                \
1140     patch_reg((address)&insn, 7, Rd);                                     \
1141     patch_reg((address)&insn, 15, Rs1);                                   \
1142     patch_reg((address)&insn, 20, Rs2);                                   \
1143     emit(insn);                                                           \
1144   }
1145 
1146   INSN(feq_s,    0b1010011, 0b010, 0b1010000);
1147   INSN(flt_s,    0b1010011, 0b001, 0b1010000);
1148   INSN(fle_s,    0b1010011, 0b000, 0b1010000);
1149   INSN(feq_d,    0b1010011, 0b010, 0b1010001);
1150   INSN(fle_d,    0b1010011, 0b000, 0b1010001);
1151   INSN(flt_d,    0b1010011, 0b001, 0b1010001);
1152 #undef INSN
1153 
1154 // Float and Double Arith Instruction
1155 #define INSN(NAME, op, funct7)                                                                  \
1156   void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) {    \
1157     unsigned insn = 0;                                                                          \
1158     patch((address)&insn, 6, 0, op);                                                            \
1159     patch((address)&insn, 14, 12, rm);                                                          \
1160     patch((address)&insn, 31, 25, funct7);                                                      \
1161     patch_reg((address)&insn, 7, Rd);                                                           \
1162     patch_reg((address)&insn, 15, Rs1);                                                         \
1163     patch_reg((address)&insn, 20, Rs2);                                                         \
1164     emit(insn);                                                                                 \
1165   }
1166 
1167   INSN(fadd_s,   0b1010011, 0b0000000);
1168   INSN(fsub_s,   0b1010011, 0b0000100);
1169   INSN(fmul_s,   0b1010011, 0b0001000);
1170   INSN(fdiv_s,   0b1010011, 0b0001100);
1171   INSN(fadd_d,   0b1010011, 0b0000001);
1172   INSN(fsub_d,   0b1010011, 0b0000101);
1173   INSN(fmul_d,   0b1010011, 0b0001001);
1174   INSN(fdiv_d,   0b1010011, 0b0001101);
1175 
1176 #undef INSN
1177 
1178 // Whole Float and Double Conversion Instruction
1179 #define INSN(NAME, op, funct5, funct7)                                  \
1180   void NAME(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) {    \
1181     unsigned insn = 0;                                                  \
1182     patch((address)&insn, 6, 0, op);                                    \
1183     patch((address)&insn, 14, 12, rm);                                  \
1184     patch((address)&insn, 24, 20, funct5);                              \
1185     patch((address)&insn, 31, 25, funct7);                              \
1186     patch_reg((address)&insn, 7, Rd);                                   \
1187     patch_reg((address)&insn, 15, Rs1);                                 \
1188     emit(insn);                                                         \
1189   }
1190 
1191   INSN(fcvt_s_w,   0b1010011, 0b00000, 0b1101000);
1192   INSN(fcvt_s_wu,  0b1010011, 0b00001, 0b1101000);
1193   INSN(fcvt_s_l,   0b1010011, 0b00010, 0b1101000);
1194   INSN(fcvt_s_lu,  0b1010011, 0b00011, 0b1101000);
1195   INSN(fcvt_d_w,   0b1010011, 0b00000, 0b1101001);
1196   INSN(fcvt_d_wu,  0b1010011, 0b00001, 0b1101001);
1197   INSN(fcvt_d_l,   0b1010011, 0b00010, 0b1101001);
1198   INSN(fcvt_d_lu,  0b1010011, 0b00011, 0b1101001);
1199 
1200 #undef INSN
1201 
1202 // Float and Double Conversion Instruction
1203 #define INSN(NAME, op, funct5, funct7)                                  \
1204   void NAME(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) {    \
1205     unsigned insn = 0;                                                  \
1206     patch((address)&insn, 6, 0, op);                                    \
1207     patch((address)&insn, 14, 12, rm);                                  \
1208     patch((address)&insn, 24, 20, funct5);                              \
1209     patch((address)&insn, 31, 25, funct7);                              \
1210     patch_reg((address)&insn, 7, Rd);                                   \
1211     patch_reg((address)&insn, 15, Rs1);                                 \
1212     emit(insn);                                                         \
1213   }
1214 
1215   INSN(fcvt_w_s,   0b1010011, 0b00000, 0b1100000);
1216   INSN(fcvt_l_s,   0b1010011, 0b00010, 0b1100000);
1217   INSN(fcvt_wu_s,  0b1010011, 0b00001, 0b1100000);
1218   INSN(fcvt_lu_s,  0b1010011, 0b00011, 0b1100000);
1219   INSN(fcvt_w_d,   0b1010011, 0b00000, 0b1100001);
1220   INSN(fcvt_wu_d,  0b1010011, 0b00001, 0b1100001);
1221   INSN(fcvt_l_d,   0b1010011, 0b00010, 0b1100001);
1222   INSN(fcvt_lu_d,  0b1010011, 0b00011, 0b1100001);
1223 
1224 #undef INSN
1225 
1226 // Float and Double Move Instruction
1227 #define INSN(NAME, op, funct3, funct5, funct7)       \
1228   void NAME(FloatRegister Rd, Register Rs1) {        \
1229     unsigned insn = 0;                               \
1230     patch((address)&insn, 6, 0, op);                 \
1231     patch((address)&insn, 14, 12, funct3);           \
1232     patch((address)&insn, 20, funct5);               \
1233     patch((address)&insn, 31, 25, funct7);           \
1234     patch_reg((address)&insn, 7, Rd);                \
1235     patch_reg((address)&insn, 15, Rs1);              \
1236     emit(insn);                                      \
1237   }
1238 
1239   INSN(fmv_w_x,  0b1010011, 0b000, 0b00000, 0b1111000);
1240   INSN(fmv_d_x,  0b1010011, 0b000, 0b00000, 0b1111001);
1241 
1242 #undef INSN
1243 
1244 // Float and Double Conversion Instruction
1245 #define INSN(NAME, op, funct3, funct5, funct7)            \
1246   void NAME(Register Rd, FloatRegister Rs1) {             \
1247     unsigned insn = 0;                                    \
1248     patch((address)&insn, 6, 0, op);                      \
1249     patch((address)&insn, 14, 12, funct3);                \
1250     patch((address)&insn, 20, funct5);                    \
1251     patch((address)&insn, 31, 25, funct7);                \
1252     patch_reg((address)&insn, 7, Rd);                     \
1253     patch_reg((address)&insn, 15, Rs1);                   \
1254     emit(insn);                                           \
1255   }
1256 
1257   INSN(fclass_s, 0b1010011, 0b001, 0b00000, 0b1110000);
1258   INSN(fclass_d, 0b1010011, 0b001, 0b00000, 0b1110001);
1259   INSN(fmv_x_w,  0b1010011, 0b000, 0b00000, 0b1110000);
1260   INSN(fmv_x_d,  0b1010011, 0b000, 0b00000, 0b1110001);
1261 
1262 #undef INSN
1263 
1264 // ==========================
1265 // RISC-V Vector Extension
1266 // ==========================
1267 enum SEW {
1268   e8,
1269   e16,
1270   e32,
1271   e64,
1272   RESERVED,
1273 };
1274 
1275 enum LMUL {
1276   mf8 = 0b101,
1277   mf4 = 0b110,
1278   mf2 = 0b111,
1279   m1  = 0b000,
1280   m2  = 0b001,
1281   m4  = 0b010,
1282   m8  = 0b011,
1283 };
1284 
1285 enum VMA {
1286   mu, // undisturbed
1287   ma, // agnostic
1288 };
1289 
1290 enum VTA {
1291   tu, // undisturbed
1292   ta, // agnostic
1293 };
1294 
1295 static Assembler::SEW elembytes_to_sew(int ebytes) {
1296   assert(ebytes > 0 && ebytes <= 8, "unsupported element size");
1297   return (Assembler::SEW) exact_log2(ebytes);
1298 }
1299 
1300 static Assembler::SEW elemtype_to_sew(BasicType etype) {
1301   return Assembler::elembytes_to_sew(type2aelembytes(etype));
1302 }
1303 
1304 #define patch_vtype(hsb, lsb, vlmul, vsew, vta, vma, vill)   \
1305     if (vill == 1) {                                         \
1306       guarantee((vlmul | vsew | vta | vma == 0),             \
1307                 "the other bits in vtype shall be zero");    \
1308     }                                                        \
1309     patch((address)&insn, lsb + 2, lsb, vlmul);              \
1310     patch((address)&insn, lsb + 5, lsb + 3, vsew);           \
1311     patch((address)&insn, lsb + 6, vta);                     \
1312     patch((address)&insn, lsb + 7, vma);                     \
1313     patch((address)&insn, hsb - 1, lsb + 8, 0);              \
1314     patch((address)&insn, hsb, vill)
1315 
1316 #define INSN(NAME, op, funct3)                                            \
1317   void NAME(Register Rd, Register Rs1, SEW sew, LMUL lmul = m1,           \
1318             VMA vma = mu, VTA vta = tu, bool vill = false) {              \
1319     unsigned insn = 0;                                                    \
1320     patch((address)&insn, 6, 0, op);                                      \
1321     patch((address)&insn, 14, 12, funct3);                                \
1322     patch_vtype(30, 20, lmul, sew, vta, vma, vill);                       \
1323     patch((address)&insn, 31, 0);                                         \
1324     patch_reg((address)&insn, 7, Rd);                                     \
1325     patch_reg((address)&insn, 15, Rs1);                                   \
1326     emit(insn);                                                           \
1327   }
1328 
1329   INSN(vsetvli, 0b1010111, 0b111);
1330 
1331 #undef INSN
1332 
1333 #define INSN(NAME, op, funct3)                                            \
1334   void NAME(Register Rd, uint32_t imm, SEW sew, LMUL lmul = m1,           \
1335             VMA vma = mu, VTA vta = tu, bool vill = false) {              \
1336     unsigned insn = 0;                                                    \
1337     guarantee(is_unsigned_imm_in_range(imm, 5, 0), "imm is invalid");     \
1338     patch((address)&insn, 6, 0, op);                                      \
1339     patch((address)&insn, 14, 12, funct3);                                \
1340     patch((address)&insn, 19, 15, imm);                                   \
1341     patch_vtype(29, 20, lmul, sew, vta, vma, vill);                       \
1342     patch((address)&insn, 31, 30, 0b11);                                  \
1343     patch_reg((address)&insn, 7, Rd);                                     \
1344     emit(insn);                                                           \
1345   }
1346 
1347   INSN(vsetivli, 0b1010111, 0b111);
1348 
1349 #undef INSN
1350 
1351 #undef patch_vtype
1352 
1353 #define INSN(NAME, op, funct3, funct7)                          \
1354   void NAME(Register Rd, Register Rs1, Register Rs2) {          \
1355     unsigned insn = 0;                                          \
1356     patch((address)&insn, 6,  0, op);                           \
1357     patch((address)&insn, 14, 12, funct3);                      \
1358     patch((address)&insn, 31, 25, funct7);                      \
1359     patch_reg((address)&insn, 7, Rd);                           \
1360     patch_reg((address)&insn, 15, Rs1);                         \
1361     patch_reg((address)&insn, 20, Rs2);                         \
1362     emit(insn);                                                 \
1363   }
1364 
1365   // Vector Configuration Instruction
1366   INSN(vsetvl, 0b1010111, 0b111, 0b1000000);
1367 
1368 #undef INSN
1369 
1370 enum VectorMask {
1371   v0_t = 0b0,
1372   unmasked = 0b1
1373 };
1374 
1375 #define patch_VArith(op, Reg, funct3, Reg_or_Imm5, Vs2, vm, funct6)            \
1376     unsigned insn = 0;                                                         \
1377     patch((address)&insn, 6, 0, op);                                           \
1378     patch((address)&insn, 14, 12, funct3);                                     \
1379     patch((address)&insn, 19, 15, Reg_or_Imm5);                                \
1380     patch((address)&insn, 25, vm);                                             \
1381     patch((address)&insn, 31, 26, funct6);                                     \
1382     patch_reg((address)&insn, 7, Reg);                                         \
1383     patch_reg((address)&insn, 20, Vs2);                                        \
1384     emit(insn)
1385 
1386 // r2_vm
1387 #define INSN(NAME, op, funct3, Vs1, funct6)                                    \
1388   void NAME(Register Rd, VectorRegister Vs2, VectorMask vm = unmasked) {       \
1389     patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6);                        \
1390   }
1391 
1392   // Vector Mask
1393   INSN(vpopc_m,  0b1010111, 0b010, 0b10000, 0b010000);
1394   INSN(vfirst_m, 0b1010111, 0b010, 0b10001, 0b010000);
1395 #undef INSN
1396 
1397 #define INSN(NAME, op, funct3, Vs1, funct6)                                    \
1398   void NAME(VectorRegister Vd, VectorRegister Vs2, VectorMask vm = unmasked) { \
1399     patch_VArith(op, Vd, funct3, Vs1, Vs2, vm, funct6);                        \
1400   }
1401 
1402   // Vector Integer Extension
1403   INSN(vzext_vf2, 0b1010111, 0b010, 0b00110, 0b010010);
1404   INSN(vzext_vf4, 0b1010111, 0b010, 0b00100, 0b010010);
1405   INSN(vzext_vf8, 0b1010111, 0b010, 0b00010, 0b010010);
1406   INSN(vsext_vf2, 0b1010111, 0b010, 0b00111, 0b010010);
1407   INSN(vsext_vf4, 0b1010111, 0b010, 0b00101, 0b010010);
1408   INSN(vsext_vf8, 0b1010111, 0b010, 0b00011, 0b010010);
1409 
1410   // Vector Mask
1411   INSN(vmsbf_m,   0b1010111, 0b010, 0b00001, 0b010100);
1412   INSN(vmsif_m,   0b1010111, 0b010, 0b00011, 0b010100);
1413   INSN(vmsof_m,   0b1010111, 0b010, 0b00010, 0b010100);
1414   INSN(viota_m,   0b1010111, 0b010, 0b10000, 0b010100);
1415 
1416   // Vector Single-Width Floating-Point/Integer Type-Convert Instructions
1417   INSN(vfcvt_xu_f_v, 0b1010111, 0b001, 0b00000, 0b010010);
1418   INSN(vfcvt_x_f_v,  0b1010111, 0b001, 0b00001, 0b010010);
1419   INSN(vfcvt_f_xu_v, 0b1010111, 0b001, 0b00010, 0b010010);
1420   INSN(vfcvt_f_x_v,  0b1010111, 0b001, 0b00011, 0b010010);
1421   INSN(vfcvt_rtz_xu_f_v, 0b1010111, 0b001, 0b00110, 0b010010);
1422   INSN(vfcvt_rtz_x_f_v,  0b1010111, 0b001, 0b00111, 0b010010);
1423 
1424   // Vector Floating-Point Instruction
1425   INSN(vfsqrt_v,  0b1010111, 0b001, 0b00000, 0b010011);
1426   INSN(vfclass_v, 0b1010111, 0b001, 0b10000, 0b010011);
1427 
1428 #undef INSN
1429 
1430 // r2rd
1431 #define INSN(NAME, op, funct3, simm5, vm, funct6)         \
1432   void NAME(VectorRegister Vd, VectorRegister Vs2) {      \
1433     patch_VArith(op, Vd, funct3, simm5, Vs2, vm, funct6); \
1434   }
1435 
1436   // Vector Whole Vector Register Move
1437   INSN(vmv1r_v, 0b1010111, 0b011, 0b00000, 0b1, 0b100111);
1438   INSN(vmv2r_v, 0b1010111, 0b011, 0b00001, 0b1, 0b100111);
1439   INSN(vmv4r_v, 0b1010111, 0b011, 0b00011, 0b1, 0b100111);
1440   INSN(vmv8r_v, 0b1010111, 0b011, 0b00111, 0b1, 0b100111);
1441 
1442 #undef INSN
1443 
1444 #define INSN(NAME, op, funct3, Vs1, vm, funct6)           \
1445   void NAME(FloatRegister Rd, VectorRegister Vs2) {       \
1446     patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6);   \
1447   }
1448 
1449   // Vector Floating-Point Move Instruction
1450   INSN(vfmv_f_s, 0b1010111, 0b001, 0b00000, 0b1, 0b010000);
1451 
1452 #undef INSN
1453 
1454 #define INSN(NAME, op, funct3, Vs1, vm, funct6)          \
1455   void NAME(Register Rd, VectorRegister Vs2) {           \
1456     patch_VArith(op, Rd, funct3, Vs1, Vs2, vm, funct6);  \
1457   }
1458 
1459   // Vector Integer Scalar Move Instructions
1460   INSN(vmv_x_s, 0b1010111, 0b010, 0b00000, 0b1, 0b010000);
1461 
1462 #undef INSN
1463 
1464 // r_vm
1465 #define INSN(NAME, op, funct3, funct6)                                                             \
1466   void NAME(VectorRegister Vd, VectorRegister Vs2, uint32_t imm, VectorMask vm = unmasked) {       \
1467     guarantee(is_unsigned_imm_in_range(imm, 5, 0), "imm is invalid");                              \
1468     patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6);                         \
1469   }
1470 
1471   // Vector Single-Width Bit Shift Instructions
1472   INSN(vsra_vi,    0b1010111, 0b011, 0b101001);
1473   INSN(vsrl_vi,    0b1010111, 0b011, 0b101000);
1474   INSN(vsll_vi,    0b1010111, 0b011, 0b100101);
1475 
1476 #undef INSN
1477 
1478 #define INSN(NAME, op, funct3, funct6)                                                             \
1479   void NAME(VectorRegister Vd, VectorRegister Vs1, VectorRegister Vs2, VectorMask vm = unmasked) { \
1480     patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1481   }
1482 
1483   // Vector Single-Width Floating-Point Fused Multiply-Add Instructions
1484   INSN(vfnmsub_vv, 0b1010111, 0b001, 0b101011);
1485   INSN(vfmsub_vv,  0b1010111, 0b001, 0b101010);
1486   INSN(vfnmadd_vv, 0b1010111, 0b001, 0b101001);
1487   INSN(vfmadd_vv,  0b1010111, 0b001, 0b101000);
1488   INSN(vfnmsac_vv, 0b1010111, 0b001, 0b101111);
1489   INSN(vfmsac_vv,  0b1010111, 0b001, 0b101110);
1490   INSN(vfmacc_vv,  0b1010111, 0b001, 0b101100);
1491   INSN(vfnmacc_vv, 0b1010111, 0b001, 0b101101);
1492 
1493   // Vector Single-Width Integer Multiply-Add Instructions
1494   INSN(vnmsub_vv, 0b1010111, 0b010, 0b101011);
1495   INSN(vmadd_vv,  0b1010111, 0b010, 0b101001);
1496   INSN(vnmsac_vv, 0b1010111, 0b010, 0b101111);
1497   INSN(vmacc_vv,  0b1010111, 0b010, 0b101101);
1498 
1499 #undef INSN
1500 
1501 #define INSN(NAME, op, funct3, funct6)                                                             \
1502   void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked) {       \
1503     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1504   }
1505 
1506   // Vector Single-Width Integer Multiply-Add Instructions
1507   INSN(vnmsub_vx, 0b1010111, 0b110, 0b101011);
1508   INSN(vmadd_vx,  0b1010111, 0b110, 0b101001);
1509   INSN(vnmsac_vx, 0b1010111, 0b110, 0b101111);
1510   INSN(vmacc_vx,  0b1010111, 0b110, 0b101101);
1511 
1512   INSN(vrsub_vx,  0b1010111, 0b100, 0b000011);
1513 
1514 #undef INSN
1515 
1516 #define INSN(NAME, op, funct3, funct6)                                                             \
1517   void NAME(VectorRegister Vd, FloatRegister Rs1, VectorRegister Vs2, VectorMask vm = unmasked) {  \
1518     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1519   }
1520 
1521   // Vector Single-Width Floating-Point Fused Multiply-Add Instructions
1522   INSN(vfnmsub_vf, 0b1010111, 0b101, 0b101011);
1523   INSN(vfmsub_vf,  0b1010111, 0b101, 0b101010);
1524   INSN(vfnmadd_vf, 0b1010111, 0b101, 0b101001);
1525   INSN(vfmadd_vf,  0b1010111, 0b101, 0b101000);
1526   INSN(vfnmsac_vf, 0b1010111, 0b101, 0b101111);
1527   INSN(vfmsac_vf,  0b1010111, 0b101, 0b101110);
1528   INSN(vfmacc_vf,  0b1010111, 0b101, 0b101100);
1529   INSN(vfnmacc_vf, 0b1010111, 0b101, 0b101101);
1530 
1531 #undef INSN
1532 
1533 #define INSN(NAME, op, funct3, funct6)                                                             \
1534   void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1, VectorMask vm = unmasked) { \
1535     patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1536   }
1537 
1538   // Vector Single-Width Floating-Point Reduction Instructions
1539   INSN(vfredsum_vs,   0b1010111, 0b001, 0b000001);
1540   INSN(vfredosum_vs,  0b1010111, 0b001, 0b000011);
1541   INSN(vfredmin_vs,   0b1010111, 0b001, 0b000101);
1542   INSN(vfredmax_vs,   0b1010111, 0b001, 0b000111);
1543 
1544   // Vector Single-Width Integer Reduction Instructions
1545   INSN(vredsum_vs,    0b1010111, 0b010, 0b000000);
1546   INSN(vredand_vs,    0b1010111, 0b010, 0b000001);
1547   INSN(vredor_vs,     0b1010111, 0b010, 0b000010);
1548   INSN(vredxor_vs,    0b1010111, 0b010, 0b000011);
1549   INSN(vredminu_vs,   0b1010111, 0b010, 0b000100);
1550   INSN(vredmin_vs,    0b1010111, 0b010, 0b000101);
1551   INSN(vredmaxu_vs,   0b1010111, 0b010, 0b000110);
1552   INSN(vredmax_vs,    0b1010111, 0b010, 0b000111);
1553 
1554   // Vector Floating-Point Compare Instructions
1555   INSN(vmfle_vv, 0b1010111, 0b001, 0b011001);
1556   INSN(vmflt_vv, 0b1010111, 0b001, 0b011011);
1557   INSN(vmfne_vv, 0b1010111, 0b001, 0b011100);
1558   INSN(vmfeq_vv, 0b1010111, 0b001, 0b011000);
1559 
1560   // Vector Floating-Point Sign-Injection Instructions
1561   INSN(vfsgnjx_vv, 0b1010111, 0b001, 0b001010);
1562   INSN(vfsgnjn_vv, 0b1010111, 0b001, 0b001001);
1563   INSN(vfsgnj_vv,  0b1010111, 0b001, 0b001000);
1564 
1565   // Vector Floating-Point MIN/MAX Instructions
1566   INSN(vfmax_vv,   0b1010111, 0b001, 0b000110);
1567   INSN(vfmin_vv,   0b1010111, 0b001, 0b000100);
1568 
1569   // Vector Single-Width Floating-Point Multiply/Divide Instructions
1570   INSN(vfdiv_vv,   0b1010111, 0b001, 0b100000);
1571   INSN(vfmul_vv,   0b1010111, 0b001, 0b100100);
1572 
1573   // Vector Single-Width Floating-Point Add/Subtract Instructions
1574   INSN(vfsub_vv, 0b1010111, 0b001, 0b000010);
1575   INSN(vfadd_vv, 0b1010111, 0b001, 0b000000);
1576 
1577   // Vector Single-Width Fractional Multiply with Rounding and Saturation
1578   INSN(vsmul_vv, 0b1010111, 0b000, 0b100111);
1579 
1580   // Vector Integer Divide Instructions
1581   INSN(vrem_vv,  0b1010111, 0b010, 0b100011);
1582   INSN(vremu_vv, 0b1010111, 0b010, 0b100010);
1583   INSN(vdiv_vv,  0b1010111, 0b010, 0b100001);
1584   INSN(vdivu_vv, 0b1010111, 0b010, 0b100000);
1585 
1586   // Vector Single-Width Integer Multiply Instructions
1587   INSN(vmulhsu_vv, 0b1010111, 0b010, 0b100110);
1588   INSN(vmulhu_vv,  0b1010111, 0b010, 0b100100);
1589   INSN(vmulh_vv,   0b1010111, 0b010, 0b100111);
1590   INSN(vmul_vv,    0b1010111, 0b010, 0b100101);
1591 
1592   // Vector Integer Min/Max Instructions
1593   INSN(vmax_vv,  0b1010111, 0b000, 0b000111);
1594   INSN(vmaxu_vv, 0b1010111, 0b000, 0b000110);
1595   INSN(vmin_vv,  0b1010111, 0b000, 0b000101);
1596   INSN(vminu_vv, 0b1010111, 0b000, 0b000100);
1597 
1598   // Vector Integer Comparison Instructions
1599   INSN(vmsle_vv,  0b1010111, 0b000, 0b011101);
1600   INSN(vmsleu_vv, 0b1010111, 0b000, 0b011100);
1601   INSN(vmslt_vv,  0b1010111, 0b000, 0b011011);
1602   INSN(vmsltu_vv, 0b1010111, 0b000, 0b011010);
1603   INSN(vmsne_vv,  0b1010111, 0b000, 0b011001);
1604   INSN(vmseq_vv,  0b1010111, 0b000, 0b011000);
1605 
1606   // Vector Single-Width Bit Shift Instructions
1607   INSN(vsra_vv, 0b1010111, 0b000, 0b101001);
1608   INSN(vsrl_vv, 0b1010111, 0b000, 0b101000);
1609   INSN(vsll_vv, 0b1010111, 0b000, 0b100101);
1610 
1611   // Vector Bitwise Logical Instructions
1612   INSN(vxor_vv, 0b1010111, 0b000, 0b001011);
1613   INSN(vor_vv,  0b1010111, 0b000, 0b001010);
1614   INSN(vand_vv, 0b1010111, 0b000, 0b001001);
1615 
1616   // Vector Single-Width Integer Add and Subtract
1617   INSN(vsub_vv, 0b1010111, 0b000, 0b000010);
1618   INSN(vadd_vv, 0b1010111, 0b000, 0b000000);
1619 
1620 #undef INSN
1621 
1622 
1623 #define INSN(NAME, op, funct3, funct6)                                                             \
1624   void NAME(VectorRegister Vd, VectorRegister Vs2, Register Rs1, VectorMask vm = unmasked) {       \
1625     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1626   }
1627 
1628   // Vector Integer Divide Instructions
1629   INSN(vrem_vx,  0b1010111, 0b110, 0b100011);
1630   INSN(vremu_vx, 0b1010111, 0b110, 0b100010);
1631   INSN(vdiv_vx,  0b1010111, 0b110, 0b100001);
1632   INSN(vdivu_vx, 0b1010111, 0b110, 0b100000);
1633 
1634   // Vector Single-Width Integer Multiply Instructions
1635   INSN(vmulhsu_vx, 0b1010111, 0b110, 0b100110);
1636   INSN(vmulhu_vx,  0b1010111, 0b110, 0b100100);
1637   INSN(vmulh_vx,   0b1010111, 0b110, 0b100111);
1638   INSN(vmul_vx,    0b1010111, 0b110, 0b100101);
1639 
1640   // Vector Integer Min/Max Instructions
1641   INSN(vmax_vx,  0b1010111, 0b100, 0b000111);
1642   INSN(vmaxu_vx, 0b1010111, 0b100, 0b000110);
1643   INSN(vmin_vx,  0b1010111, 0b100, 0b000101);
1644   INSN(vminu_vx, 0b1010111, 0b100, 0b000100);
1645 
1646   // Vector Integer Comparison Instructions
1647   INSN(vmsgt_vx,  0b1010111, 0b100, 0b011111);
1648   INSN(vmsgtu_vx, 0b1010111, 0b100, 0b011110);
1649   INSN(vmsle_vx,  0b1010111, 0b100, 0b011101);
1650   INSN(vmsleu_vx, 0b1010111, 0b100, 0b011100);
1651   INSN(vmslt_vx,  0b1010111, 0b100, 0b011011);
1652   INSN(vmsltu_vx, 0b1010111, 0b100, 0b011010);
1653   INSN(vmsne_vx,  0b1010111, 0b100, 0b011001);
1654   INSN(vmseq_vx,  0b1010111, 0b100, 0b011000);
1655 
1656   // Vector Narrowing Integer Right Shift Instructions
1657   INSN(vnsra_wx, 0b1010111, 0b100, 0b101101);
1658   INSN(vnsrl_wx, 0b1010111, 0b100, 0b101100);
1659 
1660   // Vector Single-Width Bit Shift Instructions
1661   INSN(vsra_vx, 0b1010111, 0b100, 0b101001);
1662   INSN(vsrl_vx, 0b1010111, 0b100, 0b101000);
1663   INSN(vsll_vx, 0b1010111, 0b100, 0b100101);
1664 
1665   // Vector Bitwise Logical Instructions
1666   INSN(vxor_vx, 0b1010111, 0b100, 0b001011);
1667   INSN(vor_vx,  0b1010111, 0b100, 0b001010);
1668   INSN(vand_vx, 0b1010111, 0b100, 0b001001);
1669 
1670   // Vector Single-Width Integer Add and Subtract
1671   INSN(vsub_vx, 0b1010111, 0b100, 0b000010);
1672   INSN(vadd_vx, 0b1010111, 0b100, 0b000000);
1673 
1674 #undef INSN
1675 
1676 #define INSN(NAME, op, funct3, funct6)                                                             \
1677   void NAME(VectorRegister Vd, VectorRegister Vs2, FloatRegister Rs1, VectorMask vm = unmasked) {  \
1678     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6);                        \
1679   }
1680 
1681   // Vector Floating-Point Compare Instructions
1682   INSN(vmfge_vf, 0b1010111, 0b101, 0b011111);
1683   INSN(vmfgt_vf, 0b1010111, 0b101, 0b011101);
1684   INSN(vmfle_vf, 0b1010111, 0b101, 0b011001);
1685   INSN(vmflt_vf, 0b1010111, 0b101, 0b011011);
1686   INSN(vmfne_vf, 0b1010111, 0b101, 0b011100);
1687   INSN(vmfeq_vf, 0b1010111, 0b101, 0b011000);
1688 
1689   // Vector Floating-Point Sign-Injection Instructions
1690   INSN(vfsgnjx_vf, 0b1010111, 0b101, 0b001010);
1691   INSN(vfsgnjn_vf, 0b1010111, 0b101, 0b001001);
1692   INSN(vfsgnj_vf,  0b1010111, 0b101, 0b001000);
1693 
1694   // Vector Floating-Point MIN/MAX Instructions
1695   INSN(vfmax_vf, 0b1010111, 0b101, 0b000110);
1696   INSN(vfmin_vf, 0b1010111, 0b101, 0b000100);
1697 
1698   // Vector Single-Width Floating-Point Multiply/Divide Instructions
1699   INSN(vfdiv_vf,  0b1010111, 0b101, 0b100000);
1700   INSN(vfmul_vf,  0b1010111, 0b101, 0b100100);
1701   INSN(vfrdiv_vf, 0b1010111, 0b101, 0b100001);
1702 
1703   // Vector Single-Width Floating-Point Add/Subtract Instructions
1704   INSN(vfsub_vf,  0b1010111, 0b101, 0b000010);
1705   INSN(vfadd_vf,  0b1010111, 0b101, 0b000000);
1706   INSN(vfrsub_vf, 0b1010111, 0b101, 0b100111);
1707 
1708 #undef INSN
1709 
1710 #define INSN(NAME, op, funct3, funct6)                                                             \
1711   void NAME(VectorRegister Vd, VectorRegister Vs2, int32_t imm, VectorMask vm = unmasked) {        \
1712     guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid");                                       \
1713     patch_VArith(op, Vd, funct3, (uint32_t)imm & 0x1f, Vs2, vm, funct6);                           \
1714   }
1715 
1716   INSN(vmsgt_vi,  0b1010111, 0b011, 0b011111);
1717   INSN(vmsgtu_vi, 0b1010111, 0b011, 0b011110);
1718   INSN(vmsle_vi,  0b1010111, 0b011, 0b011101);
1719   INSN(vmsleu_vi, 0b1010111, 0b011, 0b011100);
1720   INSN(vmsne_vi,  0b1010111, 0b011, 0b011001);
1721   INSN(vmseq_vi,  0b1010111, 0b011, 0b011000);
1722   INSN(vxor_vi,   0b1010111, 0b011, 0b001011);
1723   INSN(vor_vi,    0b1010111, 0b011, 0b001010);
1724   INSN(vand_vi,   0b1010111, 0b011, 0b001001);
1725   INSN(vadd_vi,   0b1010111, 0b011, 0b000000);
1726 
1727 #undef INSN
1728 
1729 #define INSN(NAME, op, funct3, funct6)                                                             \
1730   void NAME(VectorRegister Vd, int32_t imm, VectorRegister Vs2, VectorMask vm = unmasked) {        \
1731     guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid");                                       \
1732     patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6);                         \
1733   }
1734 
1735   INSN(vrsub_vi, 0b1010111, 0b011, 0b000011);
1736 
1737 #undef INSN
1738 
1739 #define INSN(NAME, op, funct3, vm, funct6)                                   \
1740   void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1) {     \
1741     patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6);  \
1742   }
1743 
1744   // Vector Compress Instruction
1745   INSN(vcompress_vm, 0b1010111, 0b010, 0b1, 0b010111);
1746 
1747   // Vector Mask-Register Logical Instructions
1748   INSN(vmxnor_mm,   0b1010111, 0b010, 0b1, 0b011111);
1749   INSN(vmornot_mm,  0b1010111, 0b010, 0b1, 0b011100);
1750   INSN(vmnor_mm,    0b1010111, 0b010, 0b1, 0b011110);
1751   INSN(vmor_mm,     0b1010111, 0b010, 0b1, 0b011010);
1752   INSN(vmxor_mm,    0b1010111, 0b010, 0b1, 0b011011);
1753   INSN(vmandnot_mm, 0b1010111, 0b010, 0b1, 0b011000);
1754   INSN(vmnand_mm,   0b1010111, 0b010, 0b1, 0b011101);
1755   INSN(vmand_mm,    0b1010111, 0b010, 0b1, 0b011001);
1756 
1757 #undef INSN
1758 
1759 #define INSN(NAME, op, funct3, Vs2, vm, funct6)                            \
1760   void NAME(VectorRegister Vd, int32_t imm) {                              \
1761     guarantee(is_imm_in_range(imm, 5, 0), "imm is invalid");               \
1762     patch_VArith(op, Vd, funct3, (uint32_t)(imm & 0x1f), Vs2, vm, funct6); \
1763   }
1764 
1765   // Vector Integer Move Instructions
1766   INSN(vmv_v_i, 0b1010111, 0b011, v0, 0b1, 0b010111);
1767 
1768 #undef INSN
1769 
1770 #define INSN(NAME, op, funct3, Vs2, vm, funct6)                             \
1771   void NAME(VectorRegister Vd, FloatRegister Rs1) {                         \
1772     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \
1773   }
1774 
1775   // Floating-Point Scalar Move Instructions
1776   INSN(vfmv_s_f, 0b1010111, 0b101, v0, 0b1, 0b010000);
1777   // Vector Floating-Point Move Instruction
1778   INSN(vfmv_v_f, 0b1010111, 0b101, v0, 0b1, 0b010111);
1779 
1780 #undef INSN
1781 
1782 #define INSN(NAME, op, funct3, Vs2, vm, funct6)                             \
1783   void NAME(VectorRegister Vd, VectorRegister Vs1) {                        \
1784     patch_VArith(op, Vd, funct3, Vs1->encoding_nocheck(), Vs2, vm, funct6); \
1785   }
1786 
1787   // Vector Integer Move Instructions
1788   INSN(vmv_v_v, 0b1010111, 0b000, v0, 0b1, 0b010111);
1789 
1790 #undef INSN
1791 
1792 #define INSN(NAME, op, funct3, Vs2, vm, funct6)                             \
1793    void NAME(VectorRegister Vd, Register Rs1) {                             \
1794     patch_VArith(op, Vd, funct3, Rs1->encoding_nocheck(), Vs2, vm, funct6); \
1795    }
1796 
1797   // Integer Scalar Move Instructions
1798   INSN(vmv_s_x, 0b1010111, 0b110, v0, 0b1, 0b010000);
1799 
1800   // Vector Integer Move Instructions
1801   INSN(vmv_v_x, 0b1010111, 0b100, v0, 0b1, 0b010111);
1802 
1803 #undef INSN
1804 #undef patch_VArith
1805 
1806 #define INSN(NAME, op, funct13, funct6)                    \
1807   void NAME(VectorRegister Vd, VectorMask vm = unmasked) { \
1808     unsigned insn = 0;                                     \
1809     patch((address)&insn, 6, 0, op);                       \
1810     patch((address)&insn, 24, 12, funct13);                \
1811     patch((address)&insn, 25, vm);                         \
1812     patch((address)&insn, 31, 26, funct6);                 \
1813     patch_reg((address)&insn, 7, Vd);                      \
1814     emit(insn);                                            \
1815   }
1816 
1817   // Vector Element Index Instruction
1818   INSN(vid_v, 0b1010111, 0b0000010001010, 0b010100);
1819 
1820 #undef INSN
1821 
1822 enum Nf {
1823   g1 = 0b000,
1824   g2 = 0b001,
1825   g3 = 0b010,
1826   g4 = 0b011,
1827   g5 = 0b100,
1828   g6 = 0b101,
1829   g7 = 0b110,
1830   g8 = 0b111
1831 };
1832 
1833 #define patch_VLdSt(op, VReg, width, Rs1, Reg_or_umop, vm, mop, mew, nf) \
1834     unsigned insn = 0;                                                   \
1835     patch((address)&insn, 6, 0, op);                                     \
1836     patch((address)&insn, 14, 12, width);                                \
1837     patch((address)&insn, 24, 20, Reg_or_umop);                          \
1838     patch((address)&insn, 25, vm);                                       \
1839     patch((address)&insn, 27, 26, mop);                                  \
1840     patch((address)&insn, 28, mew);                                      \
1841     patch((address)&insn, 31, 29, nf);                                   \
1842     patch_reg((address)&insn, 7, VReg);                                  \
1843     patch_reg((address)&insn, 15, Rs1);                                  \
1844     emit(insn)
1845 
1846 #define INSN(NAME, op, lumop, vm, mop, nf)                                           \
1847   void NAME(VectorRegister Vd, Register Rs1, uint32_t width = 0, bool mew = false) { \
1848     guarantee(is_unsigned_imm_in_range(width, 3, 0), "width is invalid");            \
1849     patch_VLdSt(op, Vd, width, Rs1, lumop, vm, mop, mew, nf);                        \
1850   }
1851 
1852   // Vector Load/Store Instructions
1853   INSN(vl1r_v, 0b0000111, 0b01000, 0b1, 0b00, g1);
1854 
1855 #undef INSN
1856 
1857 #define INSN(NAME, op, width, sumop, vm, mop, mew, nf)           \
1858   void NAME(VectorRegister Vs3, Register Rs1) {                  \
1859     patch_VLdSt(op, Vs3, width, Rs1, sumop, vm, mop, mew, nf);   \
1860   }
1861 
1862   // Vector Load/Store Instructions
1863   INSN(vs1r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g1);
1864 
1865 #undef INSN
1866 
1867 // r2_nfvm
1868 #define INSN(NAME, op, width, umop, mop, mew)                         \
1869   void NAME(VectorRegister Vd_or_Vs3, Register Rs1, Nf nf = g1) {     \
1870     patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, 1, mop, mew, nf);    \
1871   }
1872 
1873   // Vector Unit-Stride Instructions
1874   INSN(vle1_v, 0b0000111, 0b000, 0b01011, 0b00, 0b0);
1875   INSN(vse1_v, 0b0100111, 0b000, 0b01011, 0b00, 0b0);
1876 
1877 #undef INSN
1878 
1879 #define INSN(NAME, op, width, umop, mop, mew)                                               \
1880   void NAME(VectorRegister Vd_or_Vs3, Register Rs1, VectorMask vm = unmasked, Nf nf = g1) { \
1881     patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, vm, mop, mew, nf);                         \
1882   }
1883 
1884   // Vector Unit-Stride Instructions
1885   INSN(vle8_v,    0b0000111, 0b000, 0b00000, 0b00, 0b0);
1886   INSN(vle16_v,   0b0000111, 0b101, 0b00000, 0b00, 0b0);
1887   INSN(vle32_v,   0b0000111, 0b110, 0b00000, 0b00, 0b0);
1888   INSN(vle64_v,   0b0000111, 0b111, 0b00000, 0b00, 0b0);
1889 
1890   // Vector unit-stride fault-only-first Instructions
1891   INSN(vle8ff_v,  0b0000111, 0b000, 0b10000, 0b00, 0b0);
1892   INSN(vle16ff_v, 0b0000111, 0b101, 0b10000, 0b00, 0b0);
1893   INSN(vle32ff_v, 0b0000111, 0b110, 0b10000, 0b00, 0b0);
1894   INSN(vle64ff_v, 0b0000111, 0b111, 0b10000, 0b00, 0b0);
1895 
1896   INSN(vse8_v,  0b0100111, 0b000, 0b00000, 0b00, 0b0);
1897   INSN(vse16_v, 0b0100111, 0b101, 0b00000, 0b00, 0b0);
1898   INSN(vse32_v, 0b0100111, 0b110, 0b00000, 0b00, 0b0);
1899   INSN(vse64_v, 0b0100111, 0b111, 0b00000, 0b00, 0b0);
1900 
1901 #undef INSN
1902 
1903 #define INSN(NAME, op, width, mop, mew)                                                                  \
1904   void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked, Nf nf = g1) { \
1905     patch_VLdSt(op, Vd, width, Rs1, Vs2->encoding_nocheck(), vm, mop, mew, nf);                          \
1906   }
1907 
1908   // Vector unordered indexed load instructions
1909   INSN(vluxei8_v,  0b0000111, 0b000, 0b01, 0b0);
1910   INSN(vluxei16_v, 0b0000111, 0b101, 0b01, 0b0);
1911   INSN(vluxei32_v, 0b0000111, 0b110, 0b01, 0b0);
1912   INSN(vluxei64_v, 0b0000111, 0b111, 0b01, 0b0);
1913 
1914   // Vector ordered indexed load instructions
1915   INSN(vloxei8_v,  0b0000111, 0b000, 0b11, 0b0);
1916   INSN(vloxei16_v, 0b0000111, 0b101, 0b11, 0b0);
1917   INSN(vloxei32_v, 0b0000111, 0b110, 0b11, 0b0);
1918   INSN(vloxei64_v, 0b0000111, 0b111, 0b11, 0b0);
1919 #undef INSN
1920 
1921 #define INSN(NAME, op, width, mop, mew)                                                                  \
1922   void NAME(VectorRegister Vd, Register Rs1, Register Rs2, VectorMask vm = unmasked, Nf nf = g1) {       \
1923     patch_VLdSt(op, Vd, width, Rs1, Rs2->encoding_nocheck(), vm, mop, mew, nf);                          \
1924   }
1925 
1926   // Vector Strided Instructions
1927   INSN(vlse8_v,  0b0000111, 0b000, 0b10, 0b0);
1928   INSN(vlse16_v, 0b0000111, 0b101, 0b10, 0b0);
1929   INSN(vlse32_v, 0b0000111, 0b110, 0b10, 0b0);
1930   INSN(vlse64_v, 0b0000111, 0b111, 0b10, 0b0);
1931 
1932 #undef INSN
1933 #undef patch_VLdSt
1934 
1935 // ====================================
1936 // RISC-V Bit-Manipulation Extension
1937 // ====================================
1938 #define INSN(NAME, op, funct3, funct7)                  \
1939   void NAME(Register Rd, Register Rs1, Register Rs2) {  \
1940     unsigned insn = 0;                                  \
1941     patch((address)&insn, 6,  0, op);                   \
1942     patch((address)&insn, 14, 12, funct3);              \
1943     patch((address)&insn, 31, 25, funct7);              \
1944     patch_reg((address)&insn, 7, Rd);                   \
1945     patch_reg((address)&insn, 15, Rs1);                 \
1946     patch_reg((address)&insn, 20, Rs2);                 \
1947     emit(insn);                                         \
1948   }
1949 
1950   INSN(add_uw,    0b0111011, 0b000, 0b0000100);
1951   INSN(rol,       0b0110011, 0b001, 0b0110000);
1952   INSN(rolw,      0b0111011, 0b001, 0b0110000);
1953   INSN(ror,       0b0110011, 0b101, 0b0110000);
1954   INSN(rorw,      0b0111011, 0b101, 0b0110000);
1955   INSN(sh1add,    0b0110011, 0b010, 0b0010000);
1956   INSN(sh2add,    0b0110011, 0b100, 0b0010000);
1957   INSN(sh3add,    0b0110011, 0b110, 0b0010000);
1958   INSN(sh1add_uw, 0b0111011, 0b010, 0b0010000);
1959   INSN(sh2add_uw, 0b0111011, 0b100, 0b0010000);
1960   INSN(sh3add_uw, 0b0111011, 0b110, 0b0010000);
1961   INSN(andn,      0b0110011, 0b111, 0b0100000);
1962   INSN(orn,       0b0110011, 0b110, 0b0100000);
1963   INSN(xnor,      0b0110011, 0b100, 0b0100000);
1964   INSN(max,       0b0110011, 0b110, 0b0000101);
1965   INSN(maxu,      0b0110011, 0b111, 0b0000101);
1966   INSN(min,       0b0110011, 0b100, 0b0000101);
1967   INSN(minu,      0b0110011, 0b101, 0b0000101);
1968 
1969 #undef INSN
1970 
1971 #define INSN(NAME, op, funct3, funct12)                 \
1972   void NAME(Register Rd, Register Rs1) {                \
1973     unsigned insn = 0;                                  \
1974     patch((address)&insn, 6, 0, op);                    \
1975     patch((address)&insn, 14, 12, funct3);              \
1976     patch((address)&insn, 31, 20, funct12);             \
1977     patch_reg((address)&insn, 7, Rd);                   \
1978     patch_reg((address)&insn, 15, Rs1);                 \
1979     emit(insn);                                         \
1980   }
1981 
1982   INSN(rev8,   0b0010011, 0b101, 0b011010111000);
1983   INSN(sext_b, 0b0010011, 0b001, 0b011000000100);
1984   INSN(sext_h, 0b0010011, 0b001, 0b011000000101);
1985   INSN(zext_h, 0b0111011, 0b100, 0b000010000000);
1986   INSN(clz,    0b0010011, 0b001, 0b011000000000);
1987   INSN(clzw,   0b0011011, 0b001, 0b011000000000);
1988   INSN(ctz,    0b0010011, 0b001, 0b011000000001);
1989   INSN(ctzw,   0b0011011, 0b001, 0b011000000001);
1990   INSN(cpop,   0b0010011, 0b001, 0b011000000010);
1991   INSN(cpopw,  0b0011011, 0b001, 0b011000000010);
1992   INSN(orc_b,  0b0010011, 0b101, 0b001010000111);
1993 
1994 #undef INSN
1995 
1996 #define INSN(NAME, op, funct3, funct6)                  \
1997   void NAME(Register Rd, Register Rs1, unsigned shamt) {\
1998     guarantee(shamt <= 0x3f, "Shamt is invalid");       \
1999     unsigned insn = 0;                                  \
2000     patch((address)&insn, 6, 0, op);                    \
2001     patch((address)&insn, 14, 12, funct3);              \
2002     patch((address)&insn, 25, 20, shamt);               \
2003     patch((address)&insn, 31, 26, funct6);              \
2004     patch_reg((address)&insn, 7, Rd);                   \
2005     patch_reg((address)&insn, 15, Rs1);                 \
2006     emit(insn);                                         \
2007   }
2008 
2009   INSN(rori,    0b0010011, 0b101, 0b011000);
2010   INSN(slli_uw, 0b0011011, 0b001, 0b000010);
2011 
2012 #undef INSN
2013 
2014 #define INSN(NAME, op, funct3, funct7)                  \
2015   void NAME(Register Rd, Register Rs1, unsigned shamt) {\
2016     guarantee(shamt <= 0x1f, "Shamt is invalid");       \
2017     unsigned insn = 0;                                  \
2018     patch((address)&insn, 6, 0, op);                    \
2019     patch((address)&insn, 14, 12, funct3);              \
2020     patch((address)&insn, 24, 20, shamt);               \
2021     patch((address)&insn, 31, 25, funct7);              \
2022     patch_reg((address)&insn, 7, Rd);                   \
2023     patch_reg((address)&insn, 15, Rs1);                 \
2024     emit(insn);                                         \
2025   }
2026 
2027   INSN(roriw, 0b0011011, 0b101, 0b0110000);
2028 
2029 #undef INSN
2030 
2031 // ========================================
2032 // RISC-V Compressed Instructions Extension
2033 // ========================================
2034 // Note:
2035 // 1. When UseRVC is enabled, 32-bit instructions under 'CompressibleRegion's will be
2036 //    transformed to 16-bit instructions if compressible.
2037 // 2. RVC instructions in Assembler always begin with 'c_' prefix, as 'c_li',
2038 //    but most of time we have no need to explicitly use these instructions.
2039 // 3. 'CompressibleRegion' is introduced to hint instructions in this Region's RTTI range
2040 //    are qualified to be compressed with their 2-byte versions.
2041 //    An example:
2042 //
2043 //      CompressibleRegion cr(_masm);
2044 //      __ andr(...);      // this instruction could change to c.and if able to
2045 //
2046 // 4. Using -XX:PrintAssemblyOptions=no-aliases could distinguish RVC instructions from
2047 //    normal ones.
2048 //
2049 
2050 private:
2051   bool _in_compressible_region;
2052 public:
2053   bool in_compressible_region() const { return _in_compressible_region; }
2054   void set_in_compressible_region(bool b) { _in_compressible_region = b; }
2055 public:
2056 
2057   // a compressible region
2058   class CompressibleRegion : public StackObj {
2059   protected:
2060     Assembler *_masm;
2061     bool _saved_in_compressible_region;
2062   public:
2063     CompressibleRegion(Assembler *_masm)
2064     : _masm(_masm)
2065     , _saved_in_compressible_region(_masm->in_compressible_region()) {
2066       _masm->set_in_compressible_region(true);
2067     }
2068     ~CompressibleRegion() {
2069       _masm->set_in_compressible_region(_saved_in_compressible_region);
2070     }
2071   };
2072 
2073   // patch a 16-bit instruction.
2074   static void c_patch(address a, unsigned msb, unsigned lsb, uint16_t val) {
2075     assert_cond(a != NULL);
2076     assert_cond(msb >= lsb && msb <= 15);
2077     unsigned nbits = msb - lsb + 1;
2078     guarantee(val < (1U << nbits), "Field too big for insn");
2079     uint16_t mask = (1U << nbits) - 1;
2080     val <<= lsb;
2081     mask <<= lsb;
2082     uint16_t target = *(uint16_t *)a;
2083     target &= ~mask;
2084     target |= val;
2085     *(uint16_t *)a = target;
2086   }
2087 
2088   static void c_patch(address a, unsigned bit, uint16_t val) {
2089     c_patch(a, bit, bit, val);
2090   }
2091 
2092   // patch a 16-bit instruction with a general purpose register ranging [0, 31] (5 bits)
2093   static void c_patch_reg(address a, unsigned lsb, Register reg) {
2094     c_patch(a, lsb + 4, lsb, reg->encoding_nocheck());
2095   }
2096 
2097   // patch a 16-bit instruction with a general purpose register ranging [8, 15] (3 bits)
2098   static void c_patch_compressed_reg(address a, unsigned lsb, Register reg) {
2099     c_patch(a, lsb + 2, lsb, reg->compressed_encoding_nocheck());
2100   }
2101 
2102   // patch a 16-bit instruction with a float register ranging [0, 31] (5 bits)
2103   static void c_patch_reg(address a, unsigned lsb, FloatRegister reg) {
2104     c_patch(a, lsb + 4, lsb, reg->encoding_nocheck());
2105   }
2106 
2107   // patch a 16-bit instruction with a float register ranging [8, 15] (3 bits)
2108   static void c_patch_compressed_reg(address a, unsigned lsb, FloatRegister reg) {
2109     c_patch(a, lsb + 2, lsb, reg->compressed_encoding_nocheck());
2110   }
2111 
2112 // --------------  RVC Instruction Definitions  --------------
2113 
2114   void c_nop() {
2115     c_addi(x0, 0);
2116   }
2117 
2118 #define INSN(NAME, funct3, op)                                                               \
2119   void NAME(Register Rd_Rs1, int32_t imm) {                                                  \
2120     assert_cond(is_imm_in_range(imm, 6, 0));                                                 \
2121     uint16_t insn = 0;                                                                       \
2122     c_patch((address)&insn, 1, 0, op);                                                       \
2123     c_patch((address)&insn, 6, 2, (imm & right_n_bits(5)));                                  \
2124     c_patch_reg((address)&insn, 7, Rd_Rs1);                                                  \
2125     c_patch((address)&insn, 12, 12, (imm & nth_bit(5)) >> 5);                                \
2126     c_patch((address)&insn, 15, 13, funct3);                                                 \
2127     emit_int16(insn);                                                                        \
2128   }
2129 
2130   INSN(c_addi,   0b000, 0b01);
2131   INSN(c_addiw,  0b001, 0b01);
2132 
2133 #undef INSN
2134 
2135 #define INSN(NAME, funct3, op)                                                               \
2136   void NAME(int32_t imm) {                                                                   \
2137     assert_cond(is_imm_in_range(imm, 10, 0));                                                \
2138     assert_cond((imm & 0b1111) == 0);                                                        \
2139     assert_cond(imm != 0);                                                                   \
2140     uint16_t insn = 0;                                                                       \
2141     c_patch((address)&insn, 1, 0, op);                                                       \
2142     c_patch((address)&insn, 2, 2, (imm & nth_bit(5)) >> 5);                                  \
2143     c_patch((address)&insn, 4, 3, (imm & right_n_bits(9)) >> 7);                             \
2144     c_patch((address)&insn, 5, 5, (imm & nth_bit(6)) >> 6);                                  \
2145     c_patch((address)&insn, 6, 6, (imm & nth_bit(4)) >> 4);                                  \
2146     c_patch_reg((address)&insn, 7, sp);                                                      \
2147     c_patch((address)&insn, 12, 12, (imm & nth_bit(9)) >> 9);                                \
2148     c_patch((address)&insn, 15, 13, funct3);                                                 \
2149     emit_int16(insn);                                                                        \
2150   }
2151 
2152   INSN(c_addi16sp, 0b011, 0b01);
2153 
2154 #undef INSN
2155 
2156 #define INSN(NAME, funct3, op)                                                               \
2157   void NAME(Register Rd, uint32_t uimm) {                                                    \
2158     assert_cond(is_unsigned_imm_in_range(uimm, 10, 0));                                      \
2159     assert_cond((uimm & 0b11) == 0);                                                         \
2160     assert_cond(uimm != 0);                                                                  \
2161     uint16_t insn = 0;                                                                       \
2162     c_patch((address)&insn, 1, 0, op);                                                       \
2163     c_patch_compressed_reg((address)&insn, 2, Rd);                                           \
2164     c_patch((address)&insn, 5, 5, (uimm & nth_bit(3)) >> 3);                                 \
2165     c_patch((address)&insn, 6, 6, (uimm & nth_bit(2)) >> 2);                                 \
2166     c_patch((address)&insn, 10, 7, (uimm & right_n_bits(10)) >> 6);                          \
2167     c_patch((address)&insn, 12, 11, (uimm & right_n_bits(6)) >> 4);                          \
2168     c_patch((address)&insn, 15, 13, funct3);                                                 \
2169     emit_int16(insn);                                                                        \
2170   }
2171 
2172   INSN(c_addi4spn, 0b000, 0b00);
2173 
2174 #undef INSN
2175 
2176 #define INSN(NAME, funct3, op)                                                               \
2177   void NAME(Register Rd_Rs1, uint32_t shamt) {                                               \
2178     assert_cond(is_unsigned_imm_in_range(shamt, 6, 0));                                      \
2179     assert_cond(shamt != 0);                                                                 \
2180     assert_cond(Rd_Rs1 != x0);                                                               \
2181     uint16_t insn = 0;                                                                       \
2182     c_patch((address)&insn, 1, 0, op);                                                       \
2183     c_patch((address)&insn, 6, 2, (shamt & right_n_bits(5)));                                \
2184     c_patch_reg((address)&insn, 7, Rd_Rs1);                                                  \
2185     c_patch((address)&insn, 12, 12, (shamt & nth_bit(5)) >> 5);                              \
2186     c_patch((address)&insn, 15, 13, funct3);                                                 \
2187     emit_int16(insn);                                                                        \
2188   }
2189 
2190   INSN(c_slli, 0b000, 0b10);
2191 
2192 #undef INSN
2193 
2194 #define INSN(NAME, funct3, funct2, op)                                                       \
2195   void NAME(Register Rd_Rs1, uint32_t shamt) {                                               \
2196     assert_cond(is_unsigned_imm_in_range(shamt, 6, 0));                                      \
2197     assert_cond(shamt != 0);                                                                 \
2198     uint16_t insn = 0;                                                                       \
2199     c_patch((address)&insn, 1, 0, op);                                                       \
2200     c_patch((address)&insn, 6, 2, (shamt & right_n_bits(5)));                                \
2201     c_patch_compressed_reg((address)&insn, 7, Rd_Rs1);                                       \
2202     c_patch((address)&insn, 11, 10, funct2);                                                 \
2203     c_patch((address)&insn, 12, 12, (shamt & nth_bit(5)) >> 5);                              \
2204     c_patch((address)&insn, 15, 13, funct3);                                                 \
2205     emit_int16(insn);                                                                        \
2206   }
2207 
2208   INSN(c_srli, 0b100, 0b00, 0b01);
2209   INSN(c_srai, 0b100, 0b01, 0b01);
2210 
2211 #undef INSN
2212 
2213 #define INSN(NAME, funct3, funct2, op)                                                       \
2214   void NAME(Register Rd_Rs1, int32_t imm) {                                                  \
2215     assert_cond(is_imm_in_range(imm, 6, 0));                                                 \
2216     uint16_t insn = 0;                                                                       \
2217     c_patch((address)&insn, 1, 0, op);                                                       \
2218     c_patch((address)&insn, 6, 2, (imm & right_n_bits(5)));                                  \
2219     c_patch_compressed_reg((address)&insn, 7, Rd_Rs1);                                       \
2220     c_patch((address)&insn, 11, 10, funct2);                                                 \
2221     c_patch((address)&insn, 12, 12, (imm & nth_bit(5)) >> 5);                                \
2222     c_patch((address)&insn, 15, 13, funct3);                                                 \
2223     emit_int16(insn);                                                                        \
2224   }
2225 
2226   INSN(c_andi, 0b100, 0b10, 0b01);
2227 
2228 #undef INSN
2229 
2230 #define INSN(NAME, funct6, funct2, op)                                                       \
2231   void NAME(Register Rd_Rs1, Register Rs2) {                                                 \
2232     uint16_t insn = 0;                                                                       \
2233     c_patch((address)&insn, 1, 0, op);                                                       \
2234     c_patch_compressed_reg((address)&insn, 2, Rs2);                                          \
2235     c_patch((address)&insn, 6, 5, funct2);                                                   \
2236     c_patch_compressed_reg((address)&insn, 7, Rd_Rs1);                                       \
2237     c_patch((address)&insn, 15, 10, funct6);                                                 \
2238     emit_int16(insn);                                                                        \
2239   }
2240 
2241   INSN(c_sub,  0b100011, 0b00, 0b01);
2242   INSN(c_xor,  0b100011, 0b01, 0b01);
2243   INSN(c_or,   0b100011, 0b10, 0b01);
2244   INSN(c_and,  0b100011, 0b11, 0b01);
2245   INSN(c_subw, 0b100111, 0b00, 0b01);
2246   INSN(c_addw, 0b100111, 0b01, 0b01);
2247 
2248 #undef INSN
2249 
2250 #define INSN(NAME, funct4, op)                                                               \
2251   void NAME(Register Rd_Rs1, Register Rs2) {                                                 \
2252     assert_cond(Rd_Rs1 != x0);                                                               \
2253     uint16_t insn = 0;                                                                       \
2254     c_patch((address)&insn, 1, 0, op);                                                       \
2255     c_patch_reg((address)&insn, 2, Rs2);                                                     \
2256     c_patch_reg((address)&insn, 7, Rd_Rs1);                                                  \
2257     c_patch((address)&insn, 15, 12, funct4);                                                 \
2258     emit_int16(insn);                                                                        \
2259   }
2260 
2261   INSN(c_mv,  0b1000, 0b10);
2262   INSN(c_add, 0b1001, 0b10);
2263 
2264 #undef INSN
2265 
2266 #define INSN(NAME, funct4, op)                                                               \
2267   void NAME(Register Rs1) {                                                                  \
2268     assert_cond(Rs1 != x0);                                                                  \
2269     uint16_t insn = 0;                                                                       \
2270     c_patch((address)&insn, 1, 0, op);                                                       \
2271     c_patch_reg((address)&insn, 2, x0);                                                      \
2272     c_patch_reg((address)&insn, 7, Rs1);                                                     \
2273     c_patch((address)&insn, 15, 12, funct4);                                                 \
2274     emit_int16(insn);                                                                        \
2275   }
2276 
2277   INSN(c_jr,   0b1000, 0b10);
2278   INSN(c_jalr, 0b1001, 0b10);
2279 
2280 #undef INSN
2281 
2282   typedef void (Assembler::* j_c_insn)(address dest);
2283   typedef void (Assembler::* compare_and_branch_c_insn)(Register Rs1, address dest);
2284 
2285   void wrap_label(Label &L, j_c_insn insn) {
2286     if (L.is_bound()) {
2287       (this->*insn)(target(L));
2288     } else {
2289       L.add_patch_at(code(), locator());
2290       (this->*insn)(pc());
2291     }
2292   }
2293 
2294   void wrap_label(Label &L, Register r, compare_and_branch_c_insn insn) {
2295     if (L.is_bound()) {
2296       (this->*insn)(r, target(L));
2297     } else {
2298       L.add_patch_at(code(), locator());
2299       (this->*insn)(r, pc());
2300     }
2301   }
2302 
2303 #define INSN(NAME, funct3, op)                                                               \
2304   void NAME(int32_t offset) {                                                                \
2305     assert_cond(is_imm_in_range(offset, 11, 1));                                             \
2306     uint16_t insn = 0;                                                                       \
2307     c_patch((address)&insn, 1, 0, op);                                                       \
2308     c_patch((address)&insn, 2, 2, (offset & nth_bit(5)) >> 5);                               \
2309     c_patch((address)&insn, 5, 3, (offset & right_n_bits(4)) >> 1);                          \
2310     c_patch((address)&insn, 6, 6, (offset & nth_bit(7)) >> 7);                               \
2311     c_patch((address)&insn, 7, 7, (offset & nth_bit(6)) >> 6);                               \
2312     c_patch((address)&insn, 8, 8, (offset & nth_bit(10)) >> 10);                             \
2313     c_patch((address)&insn, 10, 9, (offset & right_n_bits(10)) >> 8);                        \
2314     c_patch((address)&insn, 11, 11, (offset & nth_bit(4)) >> 4);                             \
2315     c_patch((address)&insn, 12, 12, (offset & nth_bit(11)) >> 11);                           \
2316     c_patch((address)&insn, 15, 13, funct3);                                                 \
2317     emit_int16(insn);                                                                        \
2318   }                                                                                          \
2319   void NAME(address dest) {                                                                  \
2320     assert_cond(dest != NULL);                                                               \
2321     int64_t distance = dest - pc();                                                          \
2322     assert_cond(is_imm_in_range(distance, 11, 1));                                           \
2323     c_j(distance);                                                                           \
2324   }                                                                                          \
2325   void NAME(Label &L) {                                                                      \
2326     wrap_label(L, &Assembler::NAME);                                                         \
2327   }
2328 
2329   INSN(c_j, 0b101, 0b01);
2330 
2331 #undef INSN
2332 
2333 #define INSN(NAME, funct3, op)                                                               \
2334   void NAME(Register Rs1, int32_t imm) {                                                     \
2335     assert_cond(is_imm_in_range(imm, 8, 1));                                                 \
2336     uint16_t insn = 0;                                                                       \
2337     c_patch((address)&insn, 1, 0, op);                                                       \
2338     c_patch((address)&insn, 2, 2, (imm & nth_bit(5)) >> 5);                                  \
2339     c_patch((address)&insn, 4, 3, (imm & right_n_bits(3)) >> 1);                             \
2340     c_patch((address)&insn, 6, 5, (imm & right_n_bits(8)) >> 6);                             \
2341     c_patch_compressed_reg((address)&insn, 7, Rs1);                                          \
2342     c_patch((address)&insn, 11, 10, (imm & right_n_bits(5)) >> 3);                           \
2343     c_patch((address)&insn, 12, 12, (imm & nth_bit(8)) >> 8);                                \
2344     c_patch((address)&insn, 15, 13, funct3);                                                 \
2345     emit_int16(insn);                                                                        \
2346   }                                                                                          \
2347   void NAME(Register Rs1, address dest) {                                                    \
2348     assert_cond(dest != NULL);                                                               \
2349     int64_t distance = dest - pc();                                                          \
2350     assert_cond(is_imm_in_range(distance, 8, 1));                                            \
2351     NAME(Rs1, distance);                                                                     \
2352   }                                                                                          \
2353   void NAME(Register Rs1, Label &L) {                                                        \
2354     wrap_label(L, Rs1, &Assembler::NAME);                                                    \
2355   }
2356 
2357   INSN(c_beqz, 0b110, 0b01);
2358   INSN(c_bnez, 0b111, 0b01);
2359 
2360 #undef INSN
2361 
2362 #define INSN(NAME, funct3, op)                                                               \
2363   void NAME(Register Rd, int32_t imm) {                                                      \
2364     assert_cond(is_imm_in_range(imm, 18, 0));                                                \
2365     assert_cond((imm & 0xfff) == 0);                                                         \
2366     assert_cond(imm != 0);                                                                   \
2367     assert_cond(Rd != x0 && Rd != x2);                                                       \
2368     uint16_t insn = 0;                                                                       \
2369     c_patch((address)&insn, 1, 0, op);                                                       \
2370     c_patch((address)&insn, 6, 2, (imm & right_n_bits(17)) >> 12);                           \
2371     c_patch_reg((address)&insn, 7, Rd);                                                      \
2372     c_patch((address)&insn, 12, 12, (imm & nth_bit(17)) >> 17);                              \
2373     c_patch((address)&insn, 15, 13, funct3);                                                 \
2374     emit_int16(insn);                                                                        \
2375   }
2376 
2377   INSN(c_lui, 0b011, 0b01);
2378 
2379 #undef INSN
2380 
2381 #define INSN(NAME, funct3, op)                                                               \
2382   void NAME(Register Rd, int32_t imm) {                                                      \
2383     assert_cond(is_imm_in_range(imm, 6, 0));                                                 \
2384     assert_cond(Rd != x0);                                                                   \
2385     uint16_t insn = 0;                                                                       \
2386     c_patch((address)&insn, 1, 0, op);                                                       \
2387     c_patch((address)&insn, 6, 2, (imm & right_n_bits(5)));                                  \
2388     c_patch_reg((address)&insn, 7, Rd);                                                      \
2389     c_patch((address)&insn, 12, 12, (imm & right_n_bits(6)) >> 5);                           \
2390     c_patch((address)&insn, 15, 13, funct3);                                                 \
2391     emit_int16(insn);                                                                        \
2392   }
2393 
2394   INSN(c_li, 0b010, 0b01);
2395 
2396 #undef INSN
2397 
2398 #define INSN(NAME, funct3, op)                                                               \
2399   void NAME(Register Rd, uint32_t uimm) {                                                    \
2400     assert_cond(is_unsigned_imm_in_range(uimm, 9, 0));                                       \
2401     assert_cond((uimm & 0b111) == 0);                                                        \
2402     assert_cond(Rd != x0);                                                                   \
2403     uint16_t insn = 0;                                                                       \
2404     c_patch((address)&insn, 1, 0, op);                                                       \
2405     c_patch((address)&insn, 4, 2, (uimm & right_n_bits(9)) >> 6);                            \
2406     c_patch((address)&insn, 6, 5, (uimm & right_n_bits(5)) >> 3);                            \
2407     c_patch_reg((address)&insn, 7, Rd);                                                      \
2408     c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5);                               \
2409     c_patch((address)&insn, 15, 13, funct3);                                                 \
2410     emit_int16(insn);                                                                        \
2411   }
2412 
2413   INSN(c_ldsp,  0b011, 0b10);
2414 
2415 #undef INSN
2416 
2417 #define INSN(NAME, funct3, op)                                                               \
2418   void NAME(FloatRegister Rd, uint32_t uimm) {                                               \
2419     assert_cond(is_unsigned_imm_in_range(uimm, 9, 0));                                       \
2420     assert_cond((uimm & 0b111) == 0);                                                        \
2421     uint16_t insn = 0;                                                                       \
2422     c_patch((address)&insn, 1, 0, op);                                                       \
2423     c_patch((address)&insn, 4, 2, (uimm & right_n_bits(9)) >> 6);                            \
2424     c_patch((address)&insn, 6, 5, (uimm & right_n_bits(5)) >> 3);                            \
2425     c_patch_reg((address)&insn, 7, Rd);                                                      \
2426     c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5);                               \
2427     c_patch((address)&insn, 15, 13, funct3);                                                 \
2428     emit_int16(insn);                                                                        \
2429   }
2430 
2431   INSN(c_fldsp, 0b001, 0b10);
2432 
2433 #undef INSN
2434 
2435 #define INSN(NAME, funct3, op, REGISTER_TYPE)                                                \
2436   void NAME(REGISTER_TYPE Rd_Rs2, Register Rs1, uint32_t uimm) {                             \
2437     assert_cond(is_unsigned_imm_in_range(uimm, 8, 0));                                       \
2438     assert_cond((uimm & 0b111) == 0);                                                        \
2439     uint16_t insn = 0;                                                                       \
2440     c_patch((address)&insn, 1, 0, op);                                                       \
2441     c_patch_compressed_reg((address)&insn, 2, Rd_Rs2);                                       \
2442     c_patch((address)&insn, 6, 5, (uimm & right_n_bits(8)) >> 6);                            \
2443     c_patch_compressed_reg((address)&insn, 7, Rs1);                                          \
2444     c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3);                          \
2445     c_patch((address)&insn, 15, 13, funct3);                                                 \
2446     emit_int16(insn);                                                                        \
2447   }
2448 
2449   INSN(c_ld,  0b011, 0b00, Register);
2450   INSN(c_sd,  0b111, 0b00, Register);
2451   INSN(c_fld, 0b001, 0b00, FloatRegister);
2452   INSN(c_fsd, 0b101, 0b00, FloatRegister);
2453 
2454 #undef INSN
2455 
2456 #define INSN(NAME, funct3, op, REGISTER_TYPE)                                                \
2457   void NAME(REGISTER_TYPE Rs2, uint32_t uimm) {                                              \
2458     assert_cond(is_unsigned_imm_in_range(uimm, 9, 0));                                       \
2459     assert_cond((uimm & 0b111) == 0);                                                        \
2460     uint16_t insn = 0;                                                                       \
2461     c_patch((address)&insn, 1, 0, op);                                                       \
2462     c_patch_reg((address)&insn, 2, Rs2);                                                     \
2463     c_patch((address)&insn, 9, 7, (uimm & right_n_bits(9)) >> 6);                            \
2464     c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3);                          \
2465     c_patch((address)&insn, 15, 13, funct3);                                                 \
2466     emit_int16(insn);                                                                        \
2467   }
2468 
2469   INSN(c_sdsp,  0b111, 0b10, Register);
2470   INSN(c_fsdsp, 0b101, 0b10, FloatRegister);
2471 
2472 #undef INSN
2473 
2474 #define INSN(NAME, funct3, op)                                                               \
2475   void NAME(Register Rs2, uint32_t uimm) {                                                   \
2476     assert_cond(is_unsigned_imm_in_range(uimm, 8, 0));                                       \
2477     assert_cond((uimm & 0b11) == 0);                                                         \
2478     uint16_t insn = 0;                                                                       \
2479     c_patch((address)&insn, 1, 0, op);                                                       \
2480     c_patch_reg((address)&insn, 2, Rs2);                                                     \
2481     c_patch((address)&insn, 8, 7, (uimm & right_n_bits(8)) >> 6);                            \
2482     c_patch((address)&insn, 12, 9, (uimm & right_n_bits(6)) >> 2);                           \
2483     c_patch((address)&insn, 15, 13, funct3);                                                 \
2484     emit_int16(insn);                                                                        \
2485   }
2486 
2487   INSN(c_swsp, 0b110, 0b10);
2488 
2489 #undef INSN
2490 
2491 #define INSN(NAME, funct3, op)                                                               \
2492   void NAME(Register Rd, uint32_t uimm) {                                                    \
2493     assert_cond(is_unsigned_imm_in_range(uimm, 8, 0));                                       \
2494     assert_cond((uimm & 0b11) == 0);                                                         \
2495     assert_cond(Rd != x0);                                                                   \
2496     uint16_t insn = 0;                                                                       \
2497     c_patch((address)&insn, 1, 0, op);                                                       \
2498     c_patch((address)&insn, 3, 2, (uimm & right_n_bits(8)) >> 6);                            \
2499     c_patch((address)&insn, 6, 4, (uimm & right_n_bits(5)) >> 2);                            \
2500     c_patch_reg((address)&insn, 7, Rd);                                                      \
2501     c_patch((address)&insn, 12, 12, (uimm & nth_bit(5)) >> 5);                               \
2502     c_patch((address)&insn, 15, 13, funct3);                                                 \
2503     emit_int16(insn);                                                                        \
2504   }
2505 
2506   INSN(c_lwsp, 0b010, 0b10);
2507 
2508 #undef INSN
2509 
2510 #define INSN(NAME, funct3, op)                                                               \
2511   void NAME(Register Rd_Rs2, Register Rs1, uint32_t uimm) {                                  \
2512     assert_cond(is_unsigned_imm_in_range(uimm, 7, 0));                                       \
2513     assert_cond((uimm & 0b11) == 0);                                                         \
2514     uint16_t insn = 0;                                                                       \
2515     c_patch((address)&insn, 1, 0, op);                                                       \
2516     c_patch_compressed_reg((address)&insn, 2, Rd_Rs2);                                       \
2517     c_patch((address)&insn, 5, 5, (uimm & nth_bit(6)) >> 6);                                 \
2518     c_patch((address)&insn, 6, 6, (uimm & nth_bit(2)) >> 2);                                 \
2519     c_patch_compressed_reg((address)&insn, 7, Rs1);                                          \
2520     c_patch((address)&insn, 12, 10, (uimm & right_n_bits(6)) >> 3);                          \
2521     c_patch((address)&insn, 15, 13, funct3);                                                 \
2522     emit_int16(insn);                                                                        \
2523   }
2524 
2525   INSN(c_lw, 0b010, 0b00);
2526   INSN(c_sw, 0b110, 0b00);
2527 
2528 #undef INSN
2529 
2530 #define INSN(NAME, funct3, op)                                                               \
2531   void NAME() {                                                                              \
2532     uint16_t insn = 0;                                                                       \
2533     c_patch((address)&insn, 1, 0, op);                                                       \
2534     c_patch((address)&insn, 11, 2, 0x0);                                                     \
2535     c_patch((address)&insn, 12, 12, 0b1);                                                    \
2536     c_patch((address)&insn, 15, 13, funct3);                                                 \
2537     emit_int16(insn);                                                                        \
2538   }
2539 
2540   INSN(c_ebreak, 0b100, 0b10);
2541 
2542 #undef INSN
2543 
2544 // --------------  RVC Transformation Functions  --------------
2545 
2546 // --------------------------
2547 // Register instructions
2548 // --------------------------
2549 #define INSN(NAME)                                                                             \
2550   void NAME(Register Rd, Register Rs1, Register Rs2) {                                         \
2551     /* add -> c.add */                                                                         \
2552     if (do_compress()) {                                                                       \
2553       Register src = noreg;                                                                    \
2554       if (Rs1 != x0 && Rs2 != x0 && ((src = Rs1, Rs2 == Rd) || (src = Rs2, Rs1 == Rd))) {      \
2555         c_add(Rd, src);                                                                        \
2556         return;                                                                                \
2557       }                                                                                        \
2558     }                                                                                          \
2559     _add(Rd, Rs1, Rs2);                                                                        \
2560   }
2561 
2562   INSN(add);
2563 
2564 #undef INSN
2565 
2566 // --------------------------
2567 #define INSN(NAME, C_NAME, NORMAL_NAME)                                                      \
2568   void NAME(Register Rd, Register Rs1, Register Rs2) {                                       \
2569     /* sub/subw -> c.sub/c.subw */                                                           \
2570     if (do_compress() &&                                                                     \
2571         (Rd == Rs1 && Rd->is_compressed_valid() && Rs2->is_compressed_valid())) {            \
2572       C_NAME(Rd, Rs2);                                                                       \
2573       return;                                                                                \
2574     }                                                                                        \
2575     NORMAL_NAME(Rd, Rs1, Rs2);                                                               \
2576   }
2577 
2578   INSN(sub,  c_sub,  _sub);
2579   INSN(subw, c_subw, _subw);
2580 
2581 #undef INSN
2582 
2583 // --------------------------
2584 #define INSN(NAME, C_NAME, NORMAL_NAME)                                                      \
2585   void NAME(Register Rd, Register Rs1, Register Rs2) {                                       \
2586     /* and/or/xor/addw -> c.and/c.or/c.xor/c.addw */                                         \
2587     if (do_compress()) {                                                                     \
2588       Register src = noreg;                                                                  \
2589       if (Rs1->is_compressed_valid() && Rs2->is_compressed_valid() &&                        \
2590         ((src = Rs1, Rs2 == Rd) || (src = Rs2, Rs1 == Rd))) {                                \
2591         C_NAME(Rd, src);                                                                     \
2592         return;                                                                              \
2593       }                                                                                      \
2594     }                                                                                        \
2595     NORMAL_NAME(Rd, Rs1, Rs2);                                                               \
2596   }
2597 
2598   INSN(andr, c_and,  _andr);
2599   INSN(orr,  c_or,   _orr);
2600   INSN(xorr, c_xor,  _xorr);
2601   INSN(addw, c_addw, _addw);
2602 
2603 #undef INSN
2604 
2605 private:
2606 // some helper functions
2607   bool do_compress() const {
2608     return UseRVC && in_compressible_region();
2609   }
2610 
2611 #define FUNC(NAME, funct3, bits)                                                             \
2612   bool NAME(Register rs1, Register rd_rs2, int32_t imm12, bool ld) {                         \
2613     return rs1 == sp &&                                                                      \
2614       is_unsigned_imm_in_range(imm12, bits, 0) &&                                            \
2615       (intx(imm12) & funct3) == 0x0 &&                                                       \
2616       (!ld || rd_rs2 != x0);                                                                 \
2617   }                                                                                          \
2618 
2619   FUNC(is_c_ldsdsp,  0b111, 9);
2620   FUNC(is_c_lwswsp,  0b011, 8);
2621 
2622 #undef FUNC
2623 
2624 #define FUNC(NAME, funct3, bits)                                                             \
2625   bool NAME(Register rs1, int32_t imm12) {                                                   \
2626     return rs1 == sp &&                                                                      \
2627       is_unsigned_imm_in_range(imm12, bits, 0) &&                                            \
2628       (intx(imm12) & funct3) == 0x0;                                                         \
2629   }                                                                                          \
2630 
2631   FUNC(is_c_fldsdsp, 0b111, 9);
2632 
2633 #undef FUNC
2634 
2635 #define FUNC(NAME, REG_TYPE, funct3, bits)                                                   \
2636   bool NAME(Register rs1, REG_TYPE rd_rs2, int32_t imm12) {                                  \
2637     return rs1->is_compressed_valid() &&                                                     \
2638       rd_rs2->is_compressed_valid() &&                                                       \
2639       is_unsigned_imm_in_range(imm12, bits, 0) &&                                            \
2640       (intx(imm12) & funct3) == 0x0;                                                         \
2641   }                                                                                          \
2642 
2643   FUNC(is_c_ldsd,  Register,      0b111, 8);
2644   FUNC(is_c_lwsw,  Register,      0b011, 7);
2645   FUNC(is_c_fldsd, FloatRegister, 0b111, 8);
2646 
2647 #undef FUNC
2648 
2649 public:
2650 // --------------------------
2651 // Load/store register
2652 // --------------------------
2653 #define INSN(NAME)                                                                           \
2654   void NAME(Register Rd, Register Rs, const int32_t offset) {                                \
2655     /* lw -> c.lwsp/c.lw */                                                                  \
2656     if (do_compress()) {                                                                     \
2657       if (is_c_lwswsp(Rs, Rd, offset, true)) {                                               \
2658         c_lwsp(Rd, offset);                                                                  \
2659         return;                                                                              \
2660       } else if (is_c_lwsw(Rs, Rd, offset)) {                                                \
2661         c_lw(Rd, Rs, offset);                                                                \
2662         return;                                                                              \
2663       }                                                                                      \
2664     }                                                                                        \
2665     _lw(Rd, Rs, offset);                                                                     \
2666   }
2667 
2668   INSN(lw);
2669 
2670 #undef INSN
2671 
2672 // --------------------------
2673 #define INSN(NAME)                                                                           \
2674   void NAME(Register Rd, Register Rs, const int32_t offset) {                                \
2675     /* ld -> c.ldsp/c.ld */                                                                  \
2676     if (do_compress()) {                                                                     \
2677       if (is_c_ldsdsp(Rs, Rd, offset, true)) {                                               \
2678         c_ldsp(Rd, offset);                                                                  \
2679         return;                                                                              \
2680       } else if (is_c_ldsd(Rs, Rd, offset)) {                                                \
2681         c_ld(Rd, Rs, offset);                                                                \
2682         return;                                                                              \
2683       }                                                                                      \
2684     }                                                                                        \
2685     _ld(Rd, Rs, offset);                                                                     \
2686   }
2687 
2688   INSN(ld);
2689 
2690 #undef INSN
2691 
2692 // --------------------------
2693 #define INSN(NAME)                                                                           \
2694   void NAME(FloatRegister Rd, Register Rs, const int32_t offset) {                           \
2695     /* fld -> c.fldsp/c.fld */                                                               \
2696     if (do_compress()) {                                                                     \
2697       if (is_c_fldsdsp(Rs, offset)) {                                                        \
2698         c_fldsp(Rd, offset);                                                                 \
2699         return;                                                                              \
2700       } else if (is_c_fldsd(Rs, Rd, offset)) {                                               \
2701         c_fld(Rd, Rs, offset);                                                               \
2702         return;                                                                              \
2703       }                                                                                      \
2704     }                                                                                        \
2705     _fld(Rd, Rs, offset);                                                                    \
2706   }
2707 
2708   INSN(fld);
2709 
2710 #undef INSN
2711 
2712 // --------------------------
2713 #define INSN(NAME)                                                                           \
2714   void NAME(Register Rd, Register Rs, const int32_t offset) {                                \
2715     /* sd -> c.sdsp/c.sd */                                                                  \
2716     if (do_compress()) {                                                                     \
2717       if (is_c_ldsdsp(Rs, Rd, offset, false)) {                                              \
2718         c_sdsp(Rd, offset);                                                                  \
2719         return;                                                                              \
2720       } else if (is_c_ldsd(Rs, Rd, offset)) {                                                \
2721         c_sd(Rd, Rs, offset);                                                                \
2722         return;                                                                              \
2723       }                                                                                      \
2724     }                                                                                        \
2725     _sd(Rd, Rs, offset);                                                                     \
2726   }
2727 
2728   INSN(sd);
2729 
2730 #undef INSN
2731 
2732 // --------------------------
2733 #define INSN(NAME)                                                                           \
2734   void NAME(Register Rd, Register Rs, const int32_t offset) {                                \
2735     /* sw -> c.swsp/c.sw */                                                                  \
2736     if (do_compress()) {                                                                     \
2737       if (is_c_lwswsp(Rs, Rd, offset, false)) {                                              \
2738         c_swsp(Rd, offset);                                                                  \
2739         return;                                                                              \
2740       } else if (is_c_lwsw(Rs, Rd, offset)) {                                                \
2741         c_sw(Rd, Rs, offset);                                                                \
2742         return;                                                                              \
2743       }                                                                                      \
2744     }                                                                                        \
2745     _sw(Rd, Rs, offset);                                                                     \
2746   }
2747 
2748   INSN(sw);
2749 
2750 #undef INSN
2751 
2752 // --------------------------
2753 #define INSN(NAME)                                                                           \
2754   void NAME(FloatRegister Rd, Register Rs, const int32_t offset) {                           \
2755     /* fsd -> c.fsdsp/c.fsd */                                                               \
2756     if (do_compress()) {                                                                     \
2757       if (is_c_fldsdsp(Rs, offset)) {                                                        \
2758         c_fsdsp(Rd, offset);                                                                 \
2759         return;                                                                              \
2760       } else if (is_c_fldsd(Rs, Rd, offset)) {                                               \
2761         c_fsd(Rd, Rs, offset);                                                               \
2762         return;                                                                              \
2763       }                                                                                      \
2764     }                                                                                        \
2765     _fsd(Rd, Rs, offset);                                                                    \
2766   }
2767 
2768   INSN(fsd);
2769 
2770 #undef INSN
2771 
2772 // --------------------------
2773 // Conditional branch instructions
2774 // --------------------------
2775 #define INSN(NAME, C_NAME, NORMAL_NAME)                                                      \
2776   void NAME(Register Rs1, Register Rs2, const int64_t offset) {                              \
2777     /* beq/bne -> c.beqz/c.bnez */                                                           \
2778     if (do_compress() &&                                                                     \
2779         (offset != 0 && Rs2 == x0 && Rs1->is_compressed_valid() &&                           \
2780         is_imm_in_range(offset, 8, 1))) {                                                    \
2781       C_NAME(Rs1, offset);                                                                   \
2782       return;                                                                                \
2783     }                                                                                        \
2784     NORMAL_NAME(Rs1, Rs2, offset);                                                           \
2785   }
2786 
2787   INSN(beq, c_beqz, _beq);
2788   INSN(bne, c_beqz, _bne);
2789 
2790 #undef INSN
2791 
2792 // --------------------------
2793 // Unconditional branch instructions
2794 // --------------------------
2795 #define INSN(NAME)                                                                           \
2796   void NAME(Register Rd, const int32_t offset) {                                             \
2797     /* jal -> c.j */                                                                         \
2798     if (do_compress() && offset != 0 && Rd == x0 && is_imm_in_range(offset, 11, 1)) {        \
2799       c_j(offset);                                                                           \
2800       return;                                                                                \
2801     }                                                                                        \
2802     _jal(Rd, offset);                                                                        \
2803   }
2804 
2805   INSN(jal);
2806 
2807 #undef INSN
2808 
2809 // --------------------------
2810 #define INSN(NAME)                                                                           \
2811   void NAME(Register Rd, Register Rs, const int32_t offset) {                                \
2812     /* jalr -> c.jr/c.jalr */                                                                \
2813     if (do_compress() && (offset == 0 && Rs != x0)) {                                        \
2814       if (Rd == x1) {                                                                        \
2815         c_jalr(Rs);                                                                          \
2816         return;                                                                              \
2817       } else if (Rd == x0) {                                                                 \
2818         c_jr(Rs);                                                                            \
2819         return;                                                                              \
2820       }                                                                                      \
2821     }                                                                                        \
2822     _jalr(Rd, Rs, offset);                                                                   \
2823   }
2824 
2825   INSN(jalr);
2826 
2827 #undef INSN
2828 
2829 // --------------------------
2830 // Miscellaneous Instructions
2831 // --------------------------
2832 #define INSN(NAME)                                                     \
2833   void NAME() {                                                        \
2834     /* ebreak -> c.ebreak */                                           \
2835     if (do_compress()) {                                               \
2836       c_ebreak();                                                      \
2837       return;                                                          \
2838     }                                                                  \
2839     _ebreak();                                                         \
2840   }
2841 
2842   INSN(ebreak);
2843 
2844 #undef INSN
2845 
2846 #define INSN(NAME)                                                      \
2847   void NAME() {                                                         \
2848     /* The illegal instruction in RVC is presented by a 16-bit 0. */    \
2849     if (do_compress()) {                                                \
2850       emit_int16(0);                                                    \
2851       return;                                                           \
2852     }                                                                   \
2853     _halt();                                                            \
2854   }
2855 
2856   INSN(halt);
2857 
2858 #undef INSN
2859 
2860 // --------------------------
2861 // Immediate Instructions
2862 // --------------------------
2863 #define INSN(NAME)                                                                           \
2864   void NAME(Register Rd, int64_t imm) {                                                      \
2865     /* li -> c.li */                                                                         \
2866     if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) {                         \
2867       c_li(Rd, imm);                                                                         \
2868       return;                                                                                \
2869     }                                                                                        \
2870     _li(Rd, imm);                                                                            \
2871   }
2872 
2873   INSN(li);
2874 
2875 #undef INSN
2876 
2877 // --------------------------
2878 #define INSN(NAME)                                                                           \
2879   void NAME(Register Rd, Register Rs1, int32_t imm) {                                        \
2880     /* addi -> c.addi/c.nop/c.mv/c.addi16sp/c.addi4spn */                                    \
2881     if (do_compress()) {                                                                     \
2882       if (Rd == Rs1 && is_imm_in_range(imm, 6, 0)) {                                         \
2883         c_addi(Rd, imm);                                                                     \
2884         return;                                                                              \
2885       } else if (imm == 0 && Rd != x0 && Rs1 != x0) {                                        \
2886         c_mv(Rd, Rs1);                                                                       \
2887         return;                                                                              \
2888       } else if (Rs1 == sp && imm != 0) {                                                    \
2889         if (Rd == Rs1 && (imm & 0b1111) == 0x0 && is_imm_in_range(imm, 10, 0)) {             \
2890           c_addi16sp(imm);                                                                   \
2891           return;                                                                            \
2892         } else if (Rd->is_compressed_valid() && (imm & 0b11) == 0x0 && is_unsigned_imm_in_range(imm, 10, 0)) { \
2893           c_addi4spn(Rd, imm);                                                               \
2894           return;                                                                            \
2895         }                                                                                    \
2896       }                                                                                      \
2897     }                                                                                        \
2898     _addi(Rd, Rs1, imm);                                                                     \
2899   }
2900 
2901   INSN(addi);
2902 
2903 #undef INSN
2904 
2905 // --------------------------
2906 #define INSN(NAME)                                                                           \
2907   void NAME(Register Rd, Register Rs1, int32_t imm) {                                        \
2908     /* addiw -> c.addiw */                                                                   \
2909     if (do_compress() && (Rd == Rs1 && Rd != x0 && is_imm_in_range(imm, 6, 0))) {            \
2910       c_addiw(Rd, imm);                                                                      \
2911       return;                                                                                \
2912     }                                                                                        \
2913     _addiw(Rd, Rs1, imm);                                                                    \
2914   }
2915 
2916   INSN(addiw);
2917 
2918 #undef INSN
2919 
2920 // --------------------------
2921 #define INSN(NAME)                                                                           \
2922   void NAME(Register Rd, Register Rs1, int32_t imm) {                                        \
2923     /* and_imm12 -> c.andi */                                                                \
2924     if (do_compress() &&                                                                     \
2925         (Rd == Rs1 && Rd->is_compressed_valid() && is_imm_in_range(imm, 6, 0))) {            \
2926       c_andi(Rd, imm);                                                                       \
2927       return;                                                                                \
2928     }                                                                                        \
2929     _and_imm12(Rd, Rs1, imm);                                                                \
2930   }
2931 
2932   INSN(and_imm12);
2933 
2934 #undef INSN
2935 
2936 // --------------------------
2937 // Shift Immediate Instructions
2938 // --------------------------
2939 #define INSN(NAME)                                                                           \
2940   void NAME(Register Rd, Register Rs1, unsigned shamt) {                                     \
2941     /* slli -> c.slli */                                                                     \
2942     if (do_compress() && (Rd == Rs1 && Rd != x0 && shamt != 0)) {                            \
2943       c_slli(Rd, shamt);                                                                     \
2944       return;                                                                                \
2945     }                                                                                        \
2946     _slli(Rd, Rs1, shamt);                                                                   \
2947   }
2948 
2949   INSN(slli);
2950 
2951 #undef INSN
2952 
2953 // --------------------------
2954 #define INSN(NAME, C_NAME, NORMAL_NAME)                                                      \
2955   void NAME(Register Rd, Register Rs1, unsigned shamt) {                                     \
2956     /* srai/srli -> c.srai/c.srli */                                                         \
2957     if (do_compress() && (Rd == Rs1 && Rd->is_compressed_valid() && shamt != 0)) {           \
2958       C_NAME(Rd, shamt);                                                                     \
2959       return;                                                                                \
2960     }                                                                                        \
2961     NORMAL_NAME(Rd, Rs1, shamt);                                                             \
2962   }
2963 
2964   INSN(srai, c_srai, _srai);
2965   INSN(srli, c_srli, _srli);
2966 
2967 #undef INSN
2968 
2969 // --------------------------
2970 // Upper Immediate Instruction
2971 // --------------------------
2972 #define INSN(NAME)                                                                           \
2973   void NAME(Register Rd, int32_t imm) {                                                      \
2974     /* lui -> c.lui */                                                                       \
2975     if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_imm_in_range(imm, 18, 0))) { \
2976       c_lui(Rd, imm);                                                                        \
2977       return;                                                                                \
2978     }                                                                                        \
2979     _lui(Rd, imm);                                                                           \
2980   }
2981 
2982   INSN(lui);
2983 
2984 #undef INSN
2985 
2986 // ---------------------------------------------------------------------------------------
2987 
2988   void bgt(Register Rs, Register Rt, const address &dest);
2989   void ble(Register Rs, Register Rt, const address &dest);
2990   void bgtu(Register Rs, Register Rt, const address &dest);
2991   void bleu(Register Rs, Register Rt, const address &dest);
2992   void bgt(Register Rs, Register Rt, Label &l, bool is_far = false);
2993   void ble(Register Rs, Register Rt, Label &l, bool is_far = false);
2994   void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false);
2995   void bleu(Register Rs, Register Rt, Label &l, bool is_far = false);
2996 
2997   typedef void (Assembler::* jal_jalr_insn)(Register Rt, address dest);
2998   typedef void (Assembler::* load_insn_by_temp)(Register Rt, address dest, Register temp);
2999   typedef void (Assembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest);
3000   typedef void (Assembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far);
3001 
3002   void wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn,
3003                   compare_and_branch_label_insn neg_insn, bool is_far);
3004   void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn);
3005   void wrap_label(Register r, Label &L, jal_jalr_insn insn);
3006 
3007   // calculate pseudoinstruction
3008   void add(Register Rd, Register Rn, int64_t increment, Register temp = t0);
3009   void addw(Register Rd, Register Rn, int64_t increment, Register temp = t0);
3010   void sub(Register Rd, Register Rn, int64_t decrement, Register temp = t0);
3011   void subw(Register Rd, Register Rn, int64_t decrement, Register temp = t0);
3012 
3013   // RVB pseudo instructions
3014   // zero extend word
3015   void zext_w(Register Rd, Register Rs);
3016 
3017   Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) {
3018   }
3019 
3020   // Stack overflow checking
3021   virtual void bang_stack_with_offset(int offset) { Unimplemented(); }
3022 
3023   static bool operand_valid_for_add_immediate(long imm) {
3024     return is_imm_in_range(imm, 12, 0);
3025   }
3026 
3027   // The maximum range of a branch is fixed for the riscv64
3028   // architecture.
3029   static const unsigned long branch_range = 1 * M;
3030 
3031   static bool reachable_from_branch_at(address branch, address target) {
3032     return uabs(target - branch) < branch_range;
3033   }
3034 
3035   virtual ~Assembler() {}
3036 
3037 };
3038 
3039 #endif // CPU_RISCV_ASSEMBLER_RISCV_HPP