v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
extension-riscv-c.cc
Go to the documentation of this file.
1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
5
6namespace v8 {
7namespace internal {
8// RV64C Standard Extension
9void AssemblerRISCVC::c_nop() { GenInstrCI(0b000, C1, zero_reg, 0); }
10
11void AssemblerRISCVC::c_addi(Register rd, int8_t imm6) {
12 DCHECK(rd != zero_reg && imm6 != 0);
13 GenInstrCI(0b000, C1, rd, imm6);
14}
15
16#ifdef V8_TARGET_ARCH_RISCV64
17void AssemblerRISCVC::c_addiw(Register rd, int8_t imm6) {
18 DCHECK(rd != zero_reg);
19 GenInstrCI(0b001, C1, rd, imm6);
20}
21#endif
22
23void AssemblerRISCVC::c_addi16sp(int16_t imm10) {
24 DCHECK(is_int10(imm10) && (imm10 & 0xf) == 0);
25 uint8_t uimm6 = ((imm10 & 0x200) >> 4) | (imm10 & 0x10) |
26 ((imm10 & 0x40) >> 3) | ((imm10 & 0x180) >> 6) |
27 ((imm10 & 0x20) >> 5);
28 GenInstrCIU(0b011, C1, sp, uimm6);
29}
30
31void AssemblerRISCVC::c_addi4spn(Register rd, int16_t uimm10) {
32 DCHECK(is_uint10(uimm10) && (uimm10 != 0));
33 uint8_t uimm8 = ((uimm10 & 0x4) >> 1) | ((uimm10 & 0x8) >> 3) |
34 ((uimm10 & 0x30) << 2) | ((uimm10 & 0x3c0) >> 4);
35 GenInstrCIW(0b000, C0, rd, uimm8);
36}
37
38void AssemblerRISCVC::c_li(Register rd, int8_t imm6) {
39 DCHECK(rd != zero_reg);
40 GenInstrCI(0b010, C1, rd, imm6);
41}
42
43void AssemblerRISCVC::c_lui(Register rd, int8_t imm6) {
44 DCHECK(rd != zero_reg && rd != sp && imm6 != 0);
45 GenInstrCI(0b011, C1, rd, imm6);
46}
47
48void AssemblerRISCVC::c_slli(Register rd, uint8_t shamt6) {
49 DCHECK(rd != zero_reg && shamt6 != 0);
50 GenInstrCIU(0b000, C2, rd, shamt6);
51}
52
53void AssemblerRISCVC::c_fldsp(FPURegister rd, uint16_t uimm9) {
54 DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
55 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
56 GenInstrCIU(0b001, C2, rd, uimm6);
57}
58
59#ifdef V8_TARGET_ARCH_RISCV64
60void AssemblerRISCVC::c_ldsp(Register rd, uint16_t uimm9) {
61 DCHECK(rd != zero_reg && is_uint9(uimm9) && (uimm9 & 0x7) == 0);
62 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
63 GenInstrCIU(0b011, C2, rd, uimm6);
64}
65#endif
66
67void AssemblerRISCVC::c_lwsp(Register rd, uint16_t uimm8) {
68 DCHECK(rd != zero_reg && is_uint8(uimm8) && (uimm8 & 0x3) == 0);
69 uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6);
70 GenInstrCIU(0b010, C2, rd, uimm6);
71}
72
74 DCHECK(rs1 != zero_reg);
75 GenInstrCR(0b1000, C2, rs1, zero_reg);
77}
78
80 DCHECK(rd != zero_reg && rs2 != zero_reg);
81 GenInstrCR(0b1000, C2, rd, rs2);
82}
83
84void AssemblerRISCVC::c_ebreak() { GenInstrCR(0b1001, C2, zero_reg, zero_reg); }
85
87 DCHECK(rs1 != zero_reg);
88 GenInstrCR(0b1001, C2, rs1, zero_reg);
90}
91
93 DCHECK(rd != zero_reg && rs2 != zero_reg);
94 GenInstrCR(0b1001, C2, rd, rs2);
95}
96
97// CA Instructions
99 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
100 ((rs2.code() & 0b11000) == 0b01000));
101 GenInstrCA(0b100011, C1, rd, 0b00, rs2);
102}
103
105 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
106 ((rs2.code() & 0b11000) == 0b01000));
107 GenInstrCA(0b100011, C1, rd, 0b01, rs2);
108}
109
111 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
112 ((rs2.code() & 0b11000) == 0b01000));
113 GenInstrCA(0b100011, C1, rd, 0b10, rs2);
114}
115
117 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
118 ((rs2.code() & 0b11000) == 0b01000));
119 GenInstrCA(0b100011, C1, rd, 0b11, rs2);
120}
121
122#ifdef V8_TARGET_ARCH_RISCV64
123void AssemblerRISCVC::c_subw(Register rd, Register rs2) {
124 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
125 ((rs2.code() & 0b11000) == 0b01000));
126 GenInstrCA(0b100111, C1, rd, 0b00, rs2);
127}
128
129void AssemblerRISCVC::c_addw(Register rd, Register rs2) {
130 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
131 ((rs2.code() & 0b11000) == 0b01000));
132 GenInstrCA(0b100111, C1, rd, 0b01, rs2);
133}
134#endif
135
136void AssemblerRISCVC::c_swsp(Register rs2, uint16_t uimm8) {
137 DCHECK(is_uint8(uimm8) && (uimm8 & 0x3) == 0);
138 uint8_t uimm6 = (uimm8 & 0x3c) | ((uimm8 & 0xc0) >> 6);
139 GenInstrCSS(0b110, C2, rs2, uimm6);
140}
141
142#ifdef V8_TARGET_ARCH_RISCV64
143void AssemblerRISCVC::c_sdsp(Register rs2, uint16_t uimm9) {
144 DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
145 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
146 GenInstrCSS(0b111, C2, rs2, uimm6);
147}
148#endif
149
150void AssemblerRISCVC::c_fsdsp(FPURegister rs2, uint16_t uimm9) {
151 DCHECK(is_uint9(uimm9) && (uimm9 & 0x7) == 0);
152 uint8_t uimm6 = (uimm9 & 0x38) | ((uimm9 & 0x1c0) >> 6);
153 GenInstrCSS(0b101, C2, rs2, uimm6);
154}
155
156// CL Instructions
157
158void AssemblerRISCVC::c_lw(Register rd, Register rs1, uint16_t uimm7) {
159 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
160 ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
161 ((uimm7 & 0x3) == 0));
162 uint8_t uimm5 =
163 ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
164 GenInstrCL(0b010, C0, rd, rs1, uimm5);
165}
166
167#ifdef V8_TARGET_ARCH_RISCV64
168void AssemblerRISCVC::c_ld(Register rd, Register rs1, uint16_t uimm8) {
169 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
170 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
171 ((uimm8 & 0x7) == 0));
172 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
173 GenInstrCL(0b011, C0, rd, rs1, uimm5);
174}
175#endif
176
177void AssemblerRISCVC::c_fld(FPURegister rd, Register rs1, uint16_t uimm8) {
178 DCHECK(((rd.code() & 0b11000) == 0b01000) &&
179 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
180 ((uimm8 & 0x7) == 0));
181 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
182 GenInstrCL(0b001, C0, rd, rs1, uimm5);
183}
184
185// CS Instructions
186
187void AssemblerRISCVC::c_sw(Register rs2, Register rs1, uint16_t uimm7) {
188 DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
189 ((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
190 ((uimm7 & 0x3) == 0));
191 uint8_t uimm5 =
192 ((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
193 GenInstrCS(0b110, C0, rs2, rs1, uimm5);
194}
195
196#ifdef V8_TARGET_ARCH_RISCV64
197void AssemblerRISCVC::c_sd(Register rs2, Register rs1, uint16_t uimm8) {
198 DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
199 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
200 ((uimm8 & 0x7) == 0));
201 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
202 GenInstrCS(0b111, C0, rs2, rs1, uimm5);
203}
204#endif
205
206void AssemblerRISCVC::c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8) {
207 DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
208 ((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
209 ((uimm8 & 0x7) == 0));
210 uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
211 GenInstrCS(0b101, C0, rs2, rs1, uimm5);
212}
213
214// CJ Instructions
215
216void AssemblerRISCVC::c_j(int16_t imm12) {
217 DCHECK(is_int12(imm12));
218 int16_t uimm11 = ((imm12 & 0x800) >> 1) | ((imm12 & 0x400) >> 4) |
219 ((imm12 & 0x300) >> 1) | ((imm12 & 0x80) >> 3) |
220 ((imm12 & 0x40) >> 1) | ((imm12 & 0x20) >> 5) |
221 ((imm12 & 0x10) << 5) | (imm12 & 0xe);
222 GenInstrCJ(0b101, C1, uimm11);
224}
225
226// CB Instructions
227
228void AssemblerRISCVC::c_bnez(Register rs1, int16_t imm9) {
229 DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9));
230 uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) |
231 ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1);
232 GenInstrCB(0b111, C1, rs1, uimm8);
233}
234
235void AssemblerRISCVC::c_beqz(Register rs1, int16_t imm9) {
236 DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int9(imm9));
237 uint8_t uimm8 = ((imm9 & 0x20) >> 5) | ((imm9 & 0x6)) | ((imm9 & 0xc0) >> 3) |
238 ((imm9 & 0x18) << 2) | ((imm9 & 0x100) >> 1);
239 GenInstrCB(0b110, C1, rs1, uimm8);
240}
241
242void AssemblerRISCVC::c_srli(Register rs1, int8_t shamt6) {
243 DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6));
244 GenInstrCBA(0b100, 0b00, C1, rs1, shamt6);
245}
246
247void AssemblerRISCVC::c_srai(Register rs1, int8_t shamt6) {
248 DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(shamt6));
249 GenInstrCBA(0b100, 0b01, C1, rs1, shamt6);
250}
251
252void AssemblerRISCVC::c_andi(Register rs1, int8_t imm6) {
253 DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6));
254 GenInstrCBA(0b100, 0b10, C1, rs1, imm6);
255}
256
260
262 int Op = instr & kRvcOpcodeMask;
263 return Op == RO_C_BNEZ || Op == RO_C_BEQZ;
264}
265
267 int32_t imm12 = ((instr & 0x4) << 3) | ((instr & 0x38) >> 2) |
268 ((instr & 0x40) << 1) | ((instr & 0x80) >> 1) |
269 ((instr & 0x100) << 2) | ((instr & 0x600) >> 1) |
270 ((instr & 0x800) >> 7) | ((instr & 0x1000) >> 1);
271 imm12 = imm12 << 20 >> 20;
272 return imm12;
273}
274
275} // namespace internal
276} // namespace v8
void c_fsdsp(FPURegister rs2, uint16_t uimm9)
void c_li(Register rd, int8_t imm6)
void c_srli(Register rs1, int8_t shamt6)
static bool IsCBranch(Instr instr)
void c_addi4spn(Register rd, int16_t uimm10)
void c_add(Register rd, Register rs2)
void c_sub(Register rd, Register rs2)
void c_xor(Register rd, Register rs2)
void c_mv(Register rd, Register rs2)
void c_fld(FPURegister rd, Register rs1, uint16_t uimm8)
void c_or(Register rd, Register rs2)
void c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8)
void c_lw(Register rd, Register rs1, uint16_t uimm7)
void c_and(Register rd, Register rs2)
void c_swsp(Register rs2, uint16_t uimm8)
void c_slli(Register rd, uint8_t shamt6)
void c_andi(Register rs1, int8_t imm6)
void c_bnez(Register rs1, int16_t imm9)
void c_lwsp(Register rd, uint16_t uimm8)
void c_beqz(Register rs1, int16_t imm9)
static bool IsCJal(Instr instr)
void c_srai(Register rs1, int8_t shamt6)
void c_lui(Register rd, int8_t imm6)
void c_fldsp(FPURegister rd, uint16_t uimm9)
void c_sw(Register rs2, Register rs1, uint16_t uimm7)
void c_addi(Register rd, int8_t imm6)
void GenInstrCI(uint8_t funct3, BaseOpcode opcode, Register rd, int8_t imm6)
void GenInstrCR(uint8_t funct4, BaseOpcode opcode, Register rd, Register rs2)
void GenInstrCB(uint8_t funct3, BaseOpcode opcode, Register rs1, uint8_t uimm8)
void GenInstrCIU(uint8_t funct3, BaseOpcode opcode, Register rd, uint8_t uimm6)
void GenInstrCJ(uint8_t funct3, BaseOpcode opcode, uint16_t uint11)
void GenInstrCL(uint8_t funct3, BaseOpcode opcode, Register rd, Register rs1, uint8_t uimm5)
void GenInstrCBA(uint8_t funct3, uint8_t funct2, BaseOpcode opcode, Register rs1, int8_t imm6)
virtual void BlockTrampolinePoolFor(int instructions)=0
void GenInstrCA(uint8_t funct6, BaseOpcode opcode, Register rd, uint8_t funct, Register rs2)
void GenInstrCS(uint8_t funct3, BaseOpcode opcode, Register rs2, Register rs1, uint8_t uimm5)
void GenInstrCIW(uint8_t funct3, BaseOpcode opcode, Register rd, uint8_t uimm8)
void GenInstrCSS(uint8_t funct3, BaseOpcode opcode, FPURegister rs2, uint8_t uimm6)
constexpr int8_t code() const
Instruction * instr
constexpr Opcode RO_C_BEQZ
const uint32_t kRvcOpcodeMask
constexpr Opcode RO_C_BNEZ
constexpr Opcode RO_C_J
#define DCHECK(condition)
Definition logging.h:482