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