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