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